udevd: get netlink socket from systemd
This commit is contained in:
@@ -8,4 +8,5 @@ DefaultDependencies=no
|
||||
[Service]
|
||||
Type=notify
|
||||
OOMScoreAdjust=-1000
|
||||
Restart=on-failure
|
||||
ExecStart=@sbindir@/udevd
|
||||
|
||||
@@ -4,3 +4,4 @@ DefaultDependencies=no
|
||||
|
||||
[Socket]
|
||||
ListenSequentialPacket=@/org/kernel/udev/udevd
|
||||
ListenNetlink=kobject-uevent 1
|
||||
|
||||
+18
-16
@@ -60,6 +60,7 @@ struct udev_ctrl {
|
||||
int sock;
|
||||
struct sockaddr_un saddr;
|
||||
socklen_t addrlen;
|
||||
bool bound;
|
||||
bool connected;
|
||||
};
|
||||
|
||||
@@ -81,7 +82,7 @@ static struct udev_ctrl *udev_ctrl_new(struct udev *udev)
|
||||
return uctrl;
|
||||
}
|
||||
|
||||
struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path)
|
||||
struct udev_ctrl *udev_ctrl_new_from_socket_fd(struct udev *udev, const char *socket_path, int fd)
|
||||
{
|
||||
struct udev_ctrl *uctrl;
|
||||
|
||||
@@ -89,11 +90,16 @@ struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socke
|
||||
if (uctrl == NULL)
|
||||
return NULL;
|
||||
|
||||
uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
|
||||
if (uctrl->sock < 0) {
|
||||
err(udev, "error getting socket: %m\n");
|
||||
udev_ctrl_unref(uctrl);
|
||||
return NULL;
|
||||
if (fd < 0) {
|
||||
uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
|
||||
if (uctrl->sock < 0) {
|
||||
err(udev, "error getting socket: %m\n");
|
||||
udev_ctrl_unref(uctrl);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
uctrl->bound = true;
|
||||
uctrl->sock = fd;
|
||||
}
|
||||
|
||||
uctrl->saddr.sun_family = AF_LOCAL;
|
||||
@@ -105,35 +111,31 @@ struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socke
|
||||
return uctrl;
|
||||
}
|
||||
|
||||
struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd)
|
||||
struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path)
|
||||
{
|
||||
struct udev_ctrl *uctrl;
|
||||
|
||||
uctrl = udev_ctrl_new(udev);
|
||||
if (uctrl == NULL)
|
||||
return NULL;
|
||||
uctrl->sock = fd;
|
||||
|
||||
return uctrl;
|
||||
return udev_ctrl_new_from_socket_fd(udev, socket_path, -1);
|
||||
}
|
||||
|
||||
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (uctrl->addrlen > 0) {
|
||||
if (!uctrl->bound) {
|
||||
err = bind(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen);
|
||||
if (err < 0) {
|
||||
err = -errno;
|
||||
err(uctrl->udev, "bind failed: %m\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = listen(uctrl->sock, 0);
|
||||
if (err < 0) {
|
||||
err = -errno;
|
||||
err(uctrl->udev, "listen failed: %m\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
uctrl->bound = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+59
-40
@@ -50,6 +50,7 @@ struct udev_monitor {
|
||||
socklen_t addrlen;
|
||||
struct udev_list_node filter_subsystem_list;
|
||||
struct udev_list_node filter_tag_list;
|
||||
bool bound;
|
||||
};
|
||||
|
||||
enum udev_monitor_netlink_group {
|
||||
@@ -155,6 +156,50 @@ struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char
|
||||
return udev_monitor;
|
||||
}
|
||||
|
||||
struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd)
|
||||
{
|
||||
struct udev_monitor *udev_monitor;
|
||||
unsigned int group;
|
||||
|
||||
if (udev == NULL)
|
||||
return NULL;
|
||||
|
||||
if (name == NULL)
|
||||
group = UDEV_MONITOR_NONE;
|
||||
else if (strcmp(name, "udev") == 0)
|
||||
group = UDEV_MONITOR_UDEV;
|
||||
else if (strcmp(name, "kernel") == 0)
|
||||
group = UDEV_MONITOR_KERNEL;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
udev_monitor = udev_monitor_new(udev);
|
||||
if (udev_monitor == NULL)
|
||||
return NULL;
|
||||
|
||||
if (fd < 0) {
|
||||
udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
|
||||
if (udev_monitor->sock == -1) {
|
||||
err(udev, "error getting socket: %m\n");
|
||||
free(udev_monitor);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
udev_monitor->bound = true;
|
||||
udev_monitor->sock = fd;
|
||||
}
|
||||
|
||||
udev_monitor->snl.nl_family = AF_NETLINK;
|
||||
udev_monitor->snl.nl_groups = group;
|
||||
|
||||
/* default destination for sending */
|
||||
udev_monitor->snl_destination.nl_family = AF_NETLINK;
|
||||
udev_monitor->snl_destination.nl_groups = UDEV_MONITOR_UDEV;
|
||||
|
||||
dbg(udev, "monitor %p created with NETLINK_KOBJECT_UEVENT (%u)\n", udev_monitor, group);
|
||||
return udev_monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* udev_monitor_new_from_netlink:
|
||||
* @udev: udev library context
|
||||
@@ -182,41 +227,7 @@ struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char
|
||||
**/
|
||||
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name)
|
||||
{
|
||||
struct udev_monitor *udev_monitor;
|
||||
unsigned int group;
|
||||
|
||||
if (udev == NULL)
|
||||
return NULL;
|
||||
|
||||
if (name == NULL)
|
||||
group = UDEV_MONITOR_NONE;
|
||||
else if (strcmp(name, "udev") == 0)
|
||||
group = UDEV_MONITOR_UDEV;
|
||||
else if (strcmp(name, "kernel") == 0)
|
||||
group = UDEV_MONITOR_KERNEL;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
udev_monitor = udev_monitor_new(udev);
|
||||
if (udev_monitor == NULL)
|
||||
return NULL;
|
||||
|
||||
udev_monitor->sock = socket(PF_NETLINK, SOCK_DGRAM|SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
|
||||
if (udev_monitor->sock == -1) {
|
||||
err(udev, "error getting socket: %m\n");
|
||||
free(udev_monitor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udev_monitor->snl.nl_family = AF_NETLINK;
|
||||
udev_monitor->snl.nl_groups = group;
|
||||
|
||||
/* default destination for sending */
|
||||
udev_monitor->snl_destination.nl_family = AF_NETLINK;
|
||||
udev_monitor->snl_destination.nl_groups = UDEV_MONITOR_UDEV;
|
||||
|
||||
dbg(udev, "monitor %p created with NETLINK_KOBJECT_UEVENT (%u)\n", udev_monitor, group);
|
||||
return udev_monitor;
|
||||
return udev_monitor_new_from_netlink_fd(udev, name, -1);
|
||||
}
|
||||
|
||||
static inline void bpf_stmt(struct sock_filter *inss, unsigned int *i,
|
||||
@@ -364,16 +375,24 @@ int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct
|
||||
*/
|
||||
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
const int on = 1;
|
||||
|
||||
if (udev_monitor->sun.sun_family != 0) {
|
||||
err = bind(udev_monitor->sock,
|
||||
(struct sockaddr *)&udev_monitor->sun, udev_monitor->addrlen);
|
||||
if (!udev_monitor->bound) {
|
||||
err = bind(udev_monitor->sock,
|
||||
(struct sockaddr *)&udev_monitor->sun, udev_monitor->addrlen);
|
||||
if (err == 0)
|
||||
udev_monitor->bound = true;
|
||||
}
|
||||
} else if (udev_monitor->snl.nl_family != 0) {
|
||||
udev_monitor_filter_update(udev_monitor);
|
||||
err = bind(udev_monitor->sock,
|
||||
(struct sockaddr *)&udev_monitor->snl, sizeof(struct sockaddr_nl));
|
||||
if (!udev_monitor->bound) {
|
||||
err = bind(udev_monitor->sock,
|
||||
(struct sockaddr *)&udev_monitor->snl, sizeof(struct sockaddr_nl));
|
||||
if (err == 0)
|
||||
udev_monitor->bound = true;
|
||||
}
|
||||
if (err == 0) {
|
||||
struct sockaddr_nl snl;
|
||||
socklen_t addrlen;
|
||||
|
||||
@@ -122,11 +122,12 @@ int udev_monitor_disconnect(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender);
|
||||
int udev_monitor_send_device(struct udev_monitor *udev_monitor,
|
||||
struct udev_monitor *destination, struct udev_device *udev_device);
|
||||
struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd);
|
||||
|
||||
/* libudev-ctrl.c - daemon runtime setup */
|
||||
struct udev_ctrl;
|
||||
struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path);
|
||||
struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd);
|
||||
struct udev_ctrl *udev_ctrl_new_from_socket_fd(struct udev *udev, const char *socket_path, int fd);
|
||||
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
|
||||
struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl);
|
||||
struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl);
|
||||
|
||||
+81
-17
@@ -1099,6 +1099,42 @@ static int convert_db(struct udev *udev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int systemd_fds(struct udev *udev, int *rctrl, int *rnetlink)
|
||||
{
|
||||
int ctrl = -1, netlink = -1;
|
||||
int fd, n;
|
||||
|
||||
n = sd_listen_fds(true);
|
||||
if (n <= 0)
|
||||
return -1;
|
||||
|
||||
for (fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) {
|
||||
if (sd_is_socket(fd, AF_LOCAL, SOCK_SEQPACKET, -1)) {
|
||||
if (ctrl >= 0)
|
||||
return -1;
|
||||
ctrl = fd;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1)) {
|
||||
if (netlink >= 0)
|
||||
return -1;
|
||||
netlink = fd;
|
||||
continue;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctrl < 0 || netlink < 0)
|
||||
return -1;
|
||||
|
||||
info(udev, "ctrl=%i netlink=%i\n", ctrl, netlink);
|
||||
*rctrl = ctrl;
|
||||
*rnetlink = netlink;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct udev *udev;
|
||||
@@ -1277,34 +1313,57 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* udevadm control socket */
|
||||
if (sd_listen_fds(true) == 1 && sd_is_socket(SD_LISTEN_FDS_START, AF_LOCAL, SOCK_SEQPACKET, -1))
|
||||
udev_ctrl = udev_ctrl_new_from_fd(udev, SD_LISTEN_FDS_START);
|
||||
else
|
||||
if (systemd_fds(udev, &fd_ctrl, &fd_netlink) >= 0) {
|
||||
/* get control and netlink socket from from systemd */
|
||||
udev_ctrl = udev_ctrl_new_from_socket_fd(udev, UDEV_CTRL_SOCK_PATH, fd_ctrl);
|
||||
if (udev_ctrl == NULL) {
|
||||
err(udev, "error taking over udev control socket");
|
||||
rc = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
monitor = udev_monitor_new_from_netlink_fd(udev, "kernel", fd_netlink);
|
||||
if (monitor == NULL) {
|
||||
err(udev, "error taking over netlink socket\n");
|
||||
rc = 3;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
/* open control and netlink socket */
|
||||
udev_ctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
|
||||
if (udev_ctrl == NULL) {
|
||||
fprintf(stderr, "error initializing udev control socket");
|
||||
err(udev, "error initializing udev control socket");
|
||||
rc = 1;
|
||||
if (udev_ctrl == NULL) {
|
||||
fprintf(stderr, "error initializing udev control socket");
|
||||
err(udev, "error initializing udev control socket");
|
||||
rc = 1;
|
||||
goto exit;
|
||||
}
|
||||
fd_ctrl = udev_ctrl_get_fd(udev_ctrl);
|
||||
|
||||
monitor = udev_monitor_new_from_netlink(udev, "kernel");
|
||||
if (monitor == NULL) {
|
||||
fprintf(stderr, "error initializing netlink socket\n");
|
||||
err(udev, "error initializing netlink socket\n");
|
||||
rc = 3;
|
||||
goto exit;
|
||||
}
|
||||
fd_netlink = udev_monitor_get_fd(monitor);
|
||||
}
|
||||
|
||||
if (udev_monitor_enable_receiving(monitor) < 0) {
|
||||
fprintf(stderr, "error binding netlink socket\n");
|
||||
err(udev, "error binding netlink socket\n");
|
||||
rc = 3;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (udev_ctrl_enable_receiving(udev_ctrl) < 0) {
|
||||
fprintf(stderr, "error binding udev control socket\n");
|
||||
err(udev, "error binding udev control socket\n");
|
||||
rc = 1;
|
||||
goto exit;
|
||||
}
|
||||
fd_ctrl = udev_ctrl_get_fd(udev_ctrl);
|
||||
|
||||
monitor = udev_monitor_new_from_netlink(udev, "kernel");
|
||||
if (monitor == NULL || udev_monitor_enable_receiving(monitor) < 0) {
|
||||
fprintf(stderr, "error initializing netlink socket\n");
|
||||
err(udev, "error initializing netlink socket\n");
|
||||
rc = 3;
|
||||
goto exit;
|
||||
}
|
||||
udev_monitor_set_receive_buffer_size(monitor, 128*1024*1024);
|
||||
fd_netlink = udev_monitor_get_fd(monitor);
|
||||
|
||||
if (daemonize) {
|
||||
pid_t pid;
|
||||
@@ -1428,18 +1487,23 @@ int main(int argc, char *argv[])
|
||||
memset(&ep_ctrl, 0, sizeof(struct epoll_event));
|
||||
ep_ctrl.events = EPOLLIN;
|
||||
ep_ctrl.data.fd = fd_ctrl;
|
||||
|
||||
memset(&ep_inotify, 0, sizeof(struct epoll_event));
|
||||
ep_inotify.events = EPOLLIN;
|
||||
ep_inotify.data.fd = fd_inotify;
|
||||
|
||||
memset(&ep_signal, 0, sizeof(struct epoll_event));
|
||||
ep_signal.events = EPOLLIN;
|
||||
ep_signal.data.fd = fd_signal;
|
||||
|
||||
memset(&ep_netlink, 0, sizeof(struct epoll_event));
|
||||
ep_netlink.events = EPOLLIN;
|
||||
ep_netlink.data.fd = fd_netlink;
|
||||
|
||||
memset(&ep_worker, 0, sizeof(struct epoll_event));
|
||||
ep_worker.events = EPOLLIN;
|
||||
ep_worker.data.fd = fd_worker;
|
||||
|
||||
fd_ep = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (fd_ep < 0) {
|
||||
err(udev, "error creating epoll fd: %m\n");
|
||||
|
||||
Reference in New Issue
Block a user