summaryrefslogtreecommitdiff
path: root/udev_dbus.c
blob: 7b672ef363e33454192dc635d8f667a86dffb0c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>

#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>

#include "udev.h"
#include "udev_version.h"
#include "udev_dbus.h"
#include "logging.h"


/** variable for the connection the to system message bus or #NULL
 *  if we cannot connect or acquire the org.kernel.udev service
 */
static DBusConnection* sysbus_connection;

/** Disconnect from the system message bus */
void sysbus_disconnect(void)
{
	if (sysbus_connection == NULL)
		return;

	dbus_connection_disconnect(sysbus_connection);
	sysbus_connection = NULL;
}

/** Connect to the system message bus */
void sysbus_connect(void)
{
	DBusError error;

	/* Connect to a well-known bus instance, the system bus */
	dbus_error_init(&error);
	sysbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
	if (sysbus_connection == NULL) {
		dbg("cannot connect to system message bus, error %s: %s", 
		    error.name, error.message);
		dbus_error_free(&error);
		return;
	}

	/*  Acquire the org.kernel.udev service such that listeners
	 *  know that the message is really from us and not from a
	 *  random attacker. See the file udev_sysbus_policy.conf for
	 *  details.
	 *
	 *  Note that a service can have multiple owners (though there
	 *  is a concept of a primary owner for reception of messages)
	 *  so no race is introduced if two copies of udev is running
	 *  at the same time.
	 */
	dbus_bus_acquire_service(sysbus_connection, "org.kernel.udev", 0, 
				 &error);
	if (dbus_error_is_set(&error)) {
		printf("cannot acquire org.kernel.udev service, error %s: %s'",
		       error.name, error.message);
		sysbus_disconnect();
		return;
	}
}


/** Send out a signal that a device node is created
 *
 *  @param  dev                 udevice object
 *  @param  path                Sysfs path of device
 */
void sysbus_send_create(struct udevice *dev, const char *path)
{
	char filename[255];
	DBusMessage* message;
	DBusMessageIter iter;

	if (sysbus_connection == NULL)
		return;

	strfieldcpy(filename, udev_root);
	strfieldcat(filename, dev->name);

	/* object, interface, member */
	message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
					  "org.kernel.udev.NodeMonitor",
					  "NodeCreated");

	dbus_message_iter_init(message, &iter);
	dbus_message_iter_append_string(&iter, filename);
	dbus_message_iter_append_string(&iter, path);

	if ( !dbus_connection_send(sysbus_connection, message, NULL) )
		dbg("error sending d-bus signal");

	dbus_message_unref(message);

	dbus_connection_flush(sysbus_connection);
}

/** Send out a signal that a device node is deleted
 *
 *  @param  name                Name of the device node, e.g. /udev/sda1
 *  @param  path                Sysfs path of device
 */
void sysbus_send_remove(const char* name, const char *path)
{
	char filename[255];
	DBusMessage* message;
	DBusMessageIter iter;

	if (sysbus_connection == NULL)
		return;

	strfieldcpy(filename, udev_root);
	strfieldcat(filename, name);

	/* object, interface, member */
	message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
					  "org.kernel.udev.NodeMonitor",
					  "NodeDeleted");

	dbus_message_iter_init(message, &iter);
	dbus_message_iter_append_string(&iter, filename);
	dbus_message_iter_append_string(&iter, path);

	if ( !dbus_connection_send(sysbus_connection, message, NULL) )
		dbg("error sending d-bus signal");

	dbus_message_unref(message);

	dbus_connection_flush(sysbus_connection);
}