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:
parent
241e5a21f9
commit
116254097a
@ -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)
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user