1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-11 09:18:07 +03:00

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.
This commit is contained in:
Kay Sievers 2009-03-29 04:24:39 +02:00
parent 241e5a21f9
commit 116254097a
6 changed files with 37 additions and 26 deletions

View File

@ -15,9 +15,9 @@ AC_PREFIX_DEFAULT([/usr])
test "$prefix" = NONE && test "$exec_prefix" = NONE && exec_prefix=
dnl /* libudev version */
LIBUDEV_LT_CURRENT=1
LIBUDEV_LT_REVISION=1
LIBUDEV_LT_AGE=1
LIBUDEV_LT_CURRENT=2
LIBUDEV_LT_REVISION=0
LIBUDEV_LT_AGE=2
AC_SUBST(LIBUDEV_LT_CURRENT)
AC_SUBST(LIBUDEV_LT_REVISION)
AC_SUBST(LIBUDEV_LT_AGE)

View File

@ -2,7 +2,3 @@
# run a command on remove events
ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}"
# event to be catched by udevmonitor
RUN+="socket:@/org/kernel/udev/monitor"

View File

@ -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;
if (udev_monitor->sun.sun_family != 0) {
count = sendto(udev_monitor->sock,
buf, len, 0,
(struct sockaddr *)&udev_monitor->sun, udev_monitor->addrlen);
(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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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");