summaryrefslogtreecommitdiff
path: root/udev
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2009-03-29 04:24:39 +0200
committerKay Sievers <kay.sievers@vrfy.org>2009-03-29 04:24:39 +0200
commit116254097ad3c07d9f7ed06042dbec7ba4f0f4fd (patch)
treee2d79a92d01937d3d292badc93ffdb4130d51d7c /udev
parent241e5a21f9ad7bc986e1bb74093adf9fdb98b170 (diff)
send monitor events back to netlink socket
Instead of of our own private monitor socket, we send the processed event back to our netlink socket, to the multicast group 2 -- so any number of users can listen to udev events, just like they can listen to kernel emitted events on group 1.
Diffstat (limited to 'udev')
-rw-r--r--udev/lib/libudev-monitor.c31
-rw-r--r--udev/lib/libudev.h6
-rw-r--r--udev/udevadm-monitor.c10
-rw-r--r--udev/udevd.c6
4 files changed, 34 insertions, 19 deletions
diff --git a/udev/lib/libudev-monitor.c b/udev/lib/libudev-monitor.c
index c0aa99c65a..b2f76c3129 100644
--- a/udev/lib/libudev-monitor.c
+++ b/udev/lib/libudev-monitor.c
@@ -29,6 +29,7 @@ struct udev_monitor {
int refcount;
int sock;
struct sockaddr_nl snl;
+ struct sockaddr_nl snl_peer;
struct sockaddr_un sun;
socklen_t addrlen;
};
@@ -90,7 +91,7 @@ struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char
return udev_monitor;
}
-struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev)
+struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, unsigned int group)
{
struct udev_monitor *udev_monitor;
@@ -110,10 +111,11 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev)
}
udev_monitor->snl.nl_family = AF_NETLINK;
- udev_monitor->snl.nl_pid = getpid();
- udev_monitor->snl.nl_groups = 1;
+ udev_monitor->snl.nl_groups = group;
+ udev_monitor->snl_peer.nl_family = AF_NETLINK;
+ udev_monitor->snl_peer.nl_groups = UDEV_MONITOR_UDEV;
- dbg(udev, "monitor %p created with NETLINK_KOBJECT_UEVENT\n", udev_monitor);
+ dbg(udev, "monitor %p created with NETLINK_KOBJECT_UEVENT (%u)\n", udev_monitor, group);
return udev_monitor;
}
@@ -123,14 +125,16 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
const int on = 1;
if (udev_monitor->snl.nl_family != 0) {
- err = bind(udev_monitor->sock, (struct sockaddr *)&udev_monitor->snl, sizeof(struct sockaddr_nl));
+ err = bind(udev_monitor->sock,
+ (struct sockaddr *)&udev_monitor->snl, sizeof(struct sockaddr_nl));
if (err < 0) {
err(udev_monitor->udev, "bind failed: %m\n");
return err;
}
dbg(udev_monitor->udev, "monitor %p listening on netlink\n", udev_monitor);
} else if (udev_monitor->sun.sun_family != 0) {
- err = bind(udev_monitor->sock, (struct sockaddr *)&udev_monitor->sun, udev_monitor->addrlen);
+ err = bind(udev_monitor->sock,
+ (struct sockaddr *)&udev_monitor->sun, udev_monitor->addrlen);
if (err < 0) {
err(udev_monitor->udev, "bind failed: %m\n");
return err;
@@ -381,9 +385,18 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_devi
len = udev_device_get_properties_monitor_buf(udev_device, &buf);
if (len < 32)
return -1;
- count = sendto(udev_monitor->sock,
- buf, len, 0,
- (struct sockaddr *)&udev_monitor->sun, udev_monitor->addrlen);
+ if (udev_monitor->sun.sun_family != 0) {
+ count = sendto(udev_monitor->sock,
+ buf, len, 0,
+ (struct sockaddr *)&udev_monitor->sun,
+ udev_monitor->addrlen);
+ } else {
+ /* no destination besides the muticast group, we will always get -1 ECONNREFUSED */
+ count = sendto(udev_monitor->sock,
+ buf, len, 0,
+ (struct sockaddr *)&udev_monitor->snl_peer,
+ sizeof(struct sockaddr_nl));
+ }
info(udev_monitor->udev, "passed %zi bytes to monitor %p, \n", count, udev_monitor);
return count;
}
diff --git a/udev/lib/libudev.h b/udev/lib/libudev.h
index a5d2c22e8c..be09ddb75a 100644
--- a/udev/lib/libudev.h
+++ b/udev/lib/libudev.h
@@ -76,8 +76,12 @@ extern const char *udev_device_get_sysattr_value(struct udev_device *udev_device
/* udev and kernel device events */
struct udev_monitor;
+enum udev_monitor_netlink_group {
+ UDEV_MONITOR_KERNEL = 1,
+ UDEV_MONITOR_UDEV = 2,
+};
extern struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char *socket_path);
-extern struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev);
+extern struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, enum udev_monitor_netlink_group group);
extern int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
extern struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
extern void udev_monitor_unref(struct udev_monitor *udev_monitor);
diff --git a/udev/udevadm-monitor.c b/udev/udevadm-monitor.c
index 9be02da16c..43c1cc1163 100644
--- a/udev/udevadm-monitor.c
+++ b/udev/udevadm-monitor.c
@@ -115,11 +115,6 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[])
print_udev =1;
}
- if (getuid() != 0 && print_kernel) {
- fprintf(stderr, "root privileges needed to subscribe to kernel events\n");
- goto out;
- }
-
/* set signal handlers */
memset(&act, 0x00, sizeof(struct sigaction));
act.sa_handler = (void (*)(int)) sig_handler;
@@ -130,7 +125,7 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[])
printf("monitor will print the received events for:\n");
if (print_udev) {
- udev_monitor = udev_monitor_new_from_socket(udev, "@/org/kernel/udev/monitor");
+ udev_monitor = udev_monitor_new_from_netlink(udev, UDEV_MONITOR_UDEV);
if (udev_monitor == NULL) {
rc = 1;
goto out;
@@ -142,8 +137,9 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[])
printf("UDEV - the event which udev sends out after rule processing\n");
}
if (print_kernel) {
- kernel_monitor = udev_monitor_new_from_netlink(udev);
+ kernel_monitor = udev_monitor_new_from_netlink(udev, UDEV_MONITOR_KERNEL);
if (kernel_monitor == NULL) {
+ fprintf(stderr, "unable to subscribe to kernel events\n");
rc = 3;
goto out;
}
diff --git a/udev/udevd.c b/udev/udevd.c
index 291655ef00..d9de26ea6c 100644
--- a/udev/udevd.c
+++ b/udev/udevd.c
@@ -195,7 +195,6 @@ static void event_fork(struct udev_event *event)
switch (pid) {
case 0:
/* child */
- udev_monitor_unref(kernel_monitor);
udev_ctrl_unref(udev_ctrl);
logging_close();
logging_init("udevd-event");
@@ -235,6 +234,9 @@ static void event_fork(struct udev_event *event)
udev_device_update_db(event->dev);
}
+ /* send processed event back to the kernel netlink socket */
+ udev_monitor_send_device(kernel_monitor, event->dev);
+
info(event->udev, "seq %llu exit with %i\n", udev_device_get_seqnum(event->dev), err);
logging_close();
if (err != 0)
@@ -811,7 +813,7 @@ int main(int argc, char *argv[])
goto exit;
}
- kernel_monitor = udev_monitor_new_from_netlink(udev);
+ kernel_monitor = udev_monitor_new_from_netlink(udev, UDEV_MONITOR_KERNEL);
if (kernel_monitor == NULL || udev_monitor_enable_receiving(kernel_monitor) < 0) {
fprintf(stderr, "error initializing netlink socket\n");
err(udev, "error initializing netlink socket\n");