]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/udev/udev-ctrl.c
tree-wide: make use of new relative time events in sd-event.h
[thirdparty/systemd.git] / src / udev / udev-ctrl.c
index cb36c7e537d41f1c7da4a91ce593e35c831bfc96..dafe3da2511b39ac55f701160277a3614f3adba6 100644 (file)
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/socket.h>
 #include <sys/un.h>
 #include <unistd.h>
 
+#include "sd-event.h"
+
 #include "alloc-util.h"
+#include "errno-util.h"
 #include "fd-util.h"
 #include "format-util.h"
 #include "io-util.h"
 /* wire protocol magic must match */
 #define UDEV_CTRL_MAGIC                                0xdead1dea
 
-enum udev_ctrl_msg_type {
-        UDEV_CTRL_UNKNOWN,
-        UDEV_CTRL_SET_LOG_LEVEL,
-        UDEV_CTRL_STOP_EXEC_QUEUE,
-        UDEV_CTRL_START_EXEC_QUEUE,
-        UDEV_CTRL_RELOAD,
-        UDEV_CTRL_SET_ENV,
-        UDEV_CTRL_SET_CHILDREN_MAX,
-        UDEV_CTRL_PING,
-        UDEV_CTRL_EXIT,
-};
-
 struct udev_ctrl_msg_wire {
         char version[16];
         unsigned magic;
         enum udev_ctrl_msg_type type;
-        union {
-                int intval;
-                char buf[256];
-        };
-};
-
-struct udev_ctrl_msg {
-        unsigned n_ref;
-        struct udev_ctrl_connection *conn;
-        struct udev_ctrl_msg_wire ctrl_msg_wire;
+        union udev_ctrl_msg_value value;
 };
 
 struct udev_ctrl {
         unsigned n_ref;
         int sock;
+        int sock_connect;
         union sockaddr_union saddr;
         socklen_t addrlen;
-        bool bound;
-        bool cleanup_socket;
-        bool connected;
-};
-
-struct udev_ctrl_connection {
-        unsigned n_ref;
-        struct udev_ctrl *uctrl;
-        int sock;
+        bool bound:1;
+        bool cleanup_socket:1;
+        bool connected:1;
+        bool maybe_disconnected:1;
+        sd_event *event;
+        sd_event_source *event_source;
+        sd_event_source *event_source_connect;
+        udev_ctrl_handler_t callback;
+        void *userdata;
 };
 
-struct udev_ctrl *udev_ctrl_new_from_fd(int fd) {
+int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd) {
+        _cleanup_close_ int sock = -1;
         struct udev_ctrl *uctrl;
         int r;
 
-        uctrl = new0(struct udev_ctrl, 1);
-        if (!uctrl)
-                return NULL;
-        uctrl->n_ref = 1;
+        assert(ret);
 
         if (fd < 0) {
-                uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
-                if (uctrl->sock < 0) {
-                        log_error_errno(errno, "Failed to create socket: %m");
-                        udev_ctrl_unref(uctrl);
-                        return NULL;
-                }
-        } else {
-                uctrl->bound = true;
-                uctrl->sock = fd;
+                sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
+                if (sock < 0)
+                        return log_error_errno(errno, "Failed to create socket: %m");
         }
 
+        uctrl = new(struct udev_ctrl, 1);
+        if (!uctrl)
+                return -ENOMEM;
+
+        *uctrl = (struct udev_ctrl) {
+                .n_ref = 1,
+                .sock = fd >= 0 ? fd : TAKE_FD(sock),
+                .sock_connect = -1,
+                .bound = fd >= 0,
+        };
+
         /*
          * FIXME: remove it as soon as we can depend on this:
          *   http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=90c6bd34f884cd9cee21f1d152baf6c18bcac949
@@ -108,45 +93,58 @@ struct udev_ctrl *udev_ctrl_new_from_fd(int fd) {
         };
 
         uctrl->addrlen = SOCKADDR_UN_LEN(uctrl->saddr.un);
-        return uctrl;
-}
 
-struct udev_ctrl *udev_ctrl_new(void) {
-        return udev_ctrl_new_from_fd(-1);
+        *ret = TAKE_PTR(uctrl);
+        return 0;
 }
 
 int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) {
-        int err;
-
-        if (!uctrl->bound) {
-                err = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen);
-                if (err < 0 && errno == EADDRINUSE) {
-                        (void) sockaddr_un_unlink(&uctrl->saddr.un);
-                        err = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen);
-                }
+        int r;
 
-                if (err < 0)
-                        return log_error_errno(errno, "Failed to bind socket: %m");
+        assert(uctrl);
 
-                err = listen(uctrl->sock, 0);
-                if (err < 0)
-                        return log_error_errno(errno, "Failed to listen: %m");
+        if (uctrl->bound)
+                return 0;
 
-                uctrl->bound = true;
-                uctrl->cleanup_socket = true;
+        r = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen);
+        if (r < 0 && errno == EADDRINUSE) {
+                (void) sockaddr_un_unlink(&uctrl->saddr.un);
+                r = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen);
         }
+
+        if (r < 0)
+                return log_error_errno(errno, "Failed to bind udev control socket: %m");
+
+        if (listen(uctrl->sock, 0) < 0)
+                return log_error_errno(errno, "Failed to listen udev control socket: %m");
+
+        uctrl->bound = true;
+        uctrl->cleanup_socket = true;
+
         return 0;
 }
 
+static void udev_ctrl_disconnect(struct udev_ctrl *uctrl) {
+        if (!uctrl)
+                return;
+
+        uctrl->event_source_connect = sd_event_source_unref(uctrl->event_source_connect);
+        uctrl->sock_connect = safe_close(uctrl->sock_connect);
+}
+
 static struct udev_ctrl *udev_ctrl_free(struct udev_ctrl *uctrl) {
         assert(uctrl);
 
+        udev_ctrl_disconnect(uctrl);
+
+        sd_event_source_unref(uctrl->event_source);
         safe_close(uctrl->sock);
+
+        sd_event_unref(uctrl->event);
         return mfree(uctrl);
 }
 
-DEFINE_PRIVATE_TRIVIAL_REF_FUNC(struct udev_ctrl, udev_ctrl);
-DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free);
+DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free);
 
 int udev_ctrl_cleanup(struct udev_ctrl *uctrl) {
         if (!uctrl)
@@ -156,272 +154,253 @@ int udev_ctrl_cleanup(struct udev_ctrl *uctrl) {
         return 0;
 }
 
-int udev_ctrl_get_fd(struct udev_ctrl *uctrl) {
-        if (!uctrl)
-                return -EINVAL;
-        return uctrl->sock;
+int udev_ctrl_attach_event(struct udev_ctrl *uctrl, sd_event *event) {
+        int r;
+
+        assert_return(uctrl, -EINVAL);
+        assert_return(!uctrl->event, -EBUSY);
+
+        if (event)
+                uctrl->event = sd_event_ref(event);
+        else {
+                r = sd_event_default(&uctrl->event);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+sd_event_source *udev_ctrl_get_event_source(struct udev_ctrl *uctrl) {
+        assert(uctrl);
+
+        return uctrl->event_source;
+}
+
+static void udev_ctrl_disconnect_and_listen_again(struct udev_ctrl *uctrl) {
+        udev_ctrl_disconnect(uctrl);
+        udev_ctrl_unref(uctrl);
+        (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_ON);
 }
 
-struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) {
-        struct udev_ctrl_connection *conn;
-        struct ucred ucred = {};
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl *, udev_ctrl_disconnect_and_listen_again);
+
+static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        _cleanup_(udev_ctrl_disconnect_and_listen_againp) struct udev_ctrl *uctrl = NULL;
+        struct udev_ctrl_msg_wire msg_wire;
+        struct iovec iov = IOVEC_MAKE(&msg_wire, sizeof(struct udev_ctrl_msg_wire));
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
+        struct msghdr smsg = {
+                .msg_iov = &iov,
+                .msg_iovlen = 1,
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
+        };
+        struct cmsghdr *cmsg;
+        struct ucred *cred;
+        ssize_t size;
+
+        assert(userdata);
+
+        /* When UDEV_CTRL_EXIT is received, manager unref udev_ctrl object.
+         * To avoid the object freed, let's increment the refcount. */
+        uctrl = udev_ctrl_ref(userdata);
+
+        size = next_datagram_size_fd(fd);
+        if (size < 0)
+                return log_error_errno(size, "Failed to get size of message: %m");
+        if (size == 0)
+                return 0; /* Client disconnects? */
+
+        size = recvmsg_safe(fd, &smsg, 0);
+        if (size == -EINTR)
+                return 0;
+        if (size < 0)
+                return log_error_errno(size, "Failed to receive ctrl message: %m");
+
+        cmsg_close_all(&smsg);
+
+        cmsg = CMSG_FIRSTHDR(&smsg);
+
+        if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
+                log_error("No sender credentials received, ignoring message");
+                return 0;
+        }
+
+        cred = (struct ucred *) CMSG_DATA(cmsg);
+
+        if (cred->uid != 0) {
+                log_error("Invalid sender uid "UID_FMT", ignoring message", cred->uid);
+                return 0;
+        }
+
+        if (msg_wire.magic != UDEV_CTRL_MAGIC) {
+                log_error("Message magic 0x%08x doesn't match, ignoring message", msg_wire.magic);
+                return 0;
+        }
+
+        if (msg_wire.type == _UDEV_CTRL_END_MESSAGES)
+                return 0;
+
+        if (uctrl->callback)
+                (void) uctrl->callback(uctrl, msg_wire.type, &msg_wire.value, uctrl->userdata);
+
+        /* Do not disconnect and wait for next message. */
+        uctrl = udev_ctrl_unref(uctrl);
+        return 0;
+}
+
+static int udev_ctrl_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        struct udev_ctrl *uctrl = userdata;
+        _cleanup_close_ int sock = -1;
+        struct ucred ucred;
         int r;
 
-        conn = new(struct udev_ctrl_connection, 1);
-        if (!conn)
-                return NULL;
-        conn->n_ref = 1;
-        conn->uctrl = uctrl;
-
-        conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
-        if (conn->sock < 0) {
-                if (errno != EINTR)
-                        log_error_errno(errno, "Failed to receive ctrl connection: %m");
-                goto err;
+        assert(uctrl);
+
+        sock = accept4(fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
+        if (sock < 0) {
+                if (ERRNO_IS_ACCEPT_AGAIN(errno))
+                        return 0;
+
+                return log_error_errno(errno, "Failed to accept ctrl connection: %m");
         }
 
         /* check peer credential of connection */
-        r = getpeercred(conn->sock, &ucred);
+        r = getpeercred(sock, &ucred);
         if (r < 0) {
                 log_error_errno(r, "Failed to receive credentials of ctrl connection: %m");
-                goto err;
+                return 0;
         }
+
         if (ucred.uid > 0) {
-                log_error("Sender uid="UID_FMT", message ignored", ucred.uid);
-                goto err;
+                log_error("Invalid sender uid "UID_FMT", closing connection", ucred.uid);
+                return 0;
         }
 
         /* enable receiving of the sender credentials in the messages */
-        r = setsockopt_int(conn->sock, SOL_SOCKET, SO_PASSCRED, true);
+        r = setsockopt_int(sock, SOL_SOCKET, SO_PASSCRED, true);
         if (r < 0)
-                log_warning_errno(r, "Failed to set SO_PASSCRED: %m");
+                log_warning_errno(r, "Failed to set SO_PASSCRED, ignoring: %m");
 
-        udev_ctrl_ref(uctrl);
-        return conn;
-err:
-        safe_close(conn->sock);
-        return mfree(conn);
-}
+        r = sd_event_add_io(uctrl->event, &uctrl->event_source_connect, sock, EPOLLIN, udev_ctrl_connection_event_handler, uctrl);
+        if (r < 0) {
+                log_error_errno(r, "Failed to create event source for udev control connection: %m");
+                return 0;
+        }
+
+        (void) sd_event_source_set_description(uctrl->event_source_connect, "udev-ctrl-connection");
 
-static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_connection *conn) {
-        assert(conn);
+        /* Do not accept multiple connection. */
+        (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_OFF);
 
-        safe_close(conn->sock);
-        udev_ctrl_unref(conn->uctrl);
-        return mfree(conn);
+        uctrl->sock_connect = TAKE_FD(sock);
+        return 0;
 }
 
-DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
+int udev_ctrl_start(struct udev_ctrl *uctrl, udev_ctrl_handler_t callback, void *userdata) {
+        int r;
+
+        assert(uctrl);
+
+        if (!uctrl->event) {
+                r = udev_ctrl_attach_event(uctrl, NULL);
+                if (r < 0)
+                        return r;
+        }
+
+        r = udev_ctrl_enable_receiving(uctrl);
+        if (r < 0)
+                return r;
+
+        uctrl->callback = callback;
+        uctrl->userdata = userdata;
+
+        r = sd_event_add_io(uctrl->event, &uctrl->event_source, uctrl->sock, EPOLLIN, udev_ctrl_event_handler, uctrl);
+        if (r < 0)
+                return r;
 
-static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) {
+        (void) sd_event_source_set_description(uctrl->event_source, "udev-ctrl");
+
+        return 0;
+}
+
+int udev_ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf) {
         struct udev_ctrl_msg_wire ctrl_msg_wire = {
                 .version = "udev-" STRINGIFY(PROJECT_VERSION),
                 .magic = UDEV_CTRL_MAGIC,
                 .type = type,
         };
 
+        if (uctrl->maybe_disconnected)
+                return -ENOANO; /* to distinguish this from other errors. */
+
         if (buf)
-                strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf);
+                strscpy(ctrl_msg_wire.value.buf, sizeof(ctrl_msg_wire.value.buf), buf);
         else
-                ctrl_msg_wire.intval = intval;
+                ctrl_msg_wire.value.intval = intval;
 
         if (!uctrl->connected) {
                 if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0)
                         return -errno;
                 uctrl->connected = true;
         }
+
         if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0)
                 return -errno;
 
-        /* wait for peer message handling or disconnect */
-        for (;;) {
-                struct pollfd pfd = {
-                        .fd = uctrl->sock,
-                        .events = POLLIN,
-                };
-                int r;
-
-                r = poll(&pfd, 1, timeout * MSEC_PER_SEC);
-                if (r < 0) {
-                        if (errno == EINTR)
-                                continue;
-                        return -errno;
-                }
-                if (r == 0)
-                        return -ETIMEDOUT;
-                if (pfd.revents & POLLERR)
-                        return -EIO;
-                return 0;
-        }
-}
+        if (type == UDEV_CTRL_EXIT)
+                uctrl->maybe_disconnected = true;
 
-int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout);
-}
-
-int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout);
-}
-
-int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout);
-}
-
-int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL, timeout);
-}
-
-int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout);
+        return 0;
 }
 
-int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout);
+static int udev_ctrl_wait_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        return sd_event_exit(sd_event_source_get_event(s), 0);
 }
 
-int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout);
-}
+int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *source_io = NULL, *source_timeout = NULL;
+        int r;
 
-int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout) {
-        return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout);
-}
+        assert(uctrl);
 
-struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) {
-        struct udev_ctrl_msg *uctrl_msg;
-        ssize_t size;
-        struct cmsghdr *cmsg;
-        struct iovec iov;
-        char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
-        struct msghdr smsg = {
-                .msg_iov = &iov,
-                .msg_iovlen = 1,
-                .msg_control = cred_msg,
-                .msg_controllen = sizeof(cred_msg),
-        };
-        struct ucred *cred;
+        if (uctrl->sock < 0)
+                return 0;
+        if (!uctrl->connected)
+                return 0;
 
-        uctrl_msg = new0(struct udev_ctrl_msg, 1);
-        if (!uctrl_msg)
-                return NULL;
-        uctrl_msg->n_ref = 1;
-        uctrl_msg->conn = conn;
-        udev_ctrl_connection_ref(conn);
-
-        /* wait for the incoming message */
-        for (;;) {
-                struct pollfd pfd[1];
-                int r;
-
-                pfd[0].fd = conn->sock;
-                pfd[0].events = POLLIN;
-
-                r = poll(pfd, 1, 10000);
-                if (r < 0) {
-                        if (errno == EINTR)
-                                continue;
-                        goto err;
-                } else if (r == 0) {
-                        log_error("Timeout waiting for ctrl message");
-                        goto err;
-                } else {
-                        if (!(pfd[0].revents & POLLIN)) {
-                                log_error("Invalid ctrl connection: %m");
-                                goto err;
-                        }
-                }
-
-                break;
+        if (!uctrl->maybe_disconnected) {
+                r = udev_ctrl_send(uctrl, _UDEV_CTRL_END_MESSAGES, 0, NULL);
+                if (r < 0)
+                        return r;
         }
 
-        iov = IOVEC_MAKE(&uctrl_msg->ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire));
+        if (timeout == 0)
+                return 0;
 
-        size = recvmsg(conn->sock, &smsg, 0);
-        if (size < 0) {
-                log_error_errno(errno, "Failed to receive ctrl message: %m");
-                goto err;
+        if (!uctrl->event) {
+                r = udev_ctrl_attach_event(uctrl, NULL);
+                if (r < 0)
+                        return r;
         }
 
-        cmsg_close_all(&smsg);
+        r = sd_event_add_io(uctrl->event, &source_io, uctrl->sock, EPOLLIN, udev_ctrl_wait_io_handler, NULL);
+        if (r < 0)
+                return r;
 
-        cmsg = CMSG_FIRSTHDR(&smsg);
+        (void) sd_event_source_set_description(source_io, "udev-ctrl-wait-io");
 
-        if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
-                log_error("No sender credentials received, ignoring message");
-                goto err;
-        }
-
-        cred = (struct ucred *) CMSG_DATA(cmsg);
+        if (timeout != USEC_INFINITY) {
+                r = sd_event_add_time_relative(
+                                uctrl->event, &source_timeout, clock_boottime_or_monotonic(),
+                                timeout,
+                                0, NULL, INT_TO_PTR(-ETIMEDOUT));
+                if (r < 0)
+                        return r;
 
-        if (cred->uid != 0) {
-                log_error("Sender uid="UID_FMT", ignoring message", cred->uid);
-                goto err;
+                (void) sd_event_source_set_description(source_timeout, "udev-ctrl-wait-timeout");
         }
 
-        if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) {
-                log_error("Message magic 0x%08x doesn't match, ignoring", uctrl_msg->ctrl_msg_wire.magic);
-                goto err;
-        }
-
-        return uctrl_msg;
-err:
-        udev_ctrl_msg_unref(uctrl_msg);
-        return NULL;
-}
-
-static struct udev_ctrl_msg *udev_ctrl_msg_free(struct udev_ctrl_msg *ctrl_msg) {
-        assert(ctrl_msg);
-
-        udev_ctrl_connection_unref(ctrl_msg->conn);
-        return mfree(ctrl_msg);
-}
-
-DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl_msg, udev_ctrl_msg, udev_ctrl_msg_free);
-
-int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL)
-                return ctrl_msg->ctrl_msg_wire.intval;
-        return -1;
-}
-
-int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_STOP_EXEC_QUEUE)
-                return 1;
-        return -1;
-}
-
-int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_START_EXEC_QUEUE)
-                return 1;
-        return -1;
-}
-
-int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_RELOAD)
-                return 1;
-        return -1;
-}
-
-const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_ENV)
-                return ctrl_msg->ctrl_msg_wire.buf;
-        return NULL;
-}
-
-int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_CHILDREN_MAX)
-                return ctrl_msg->ctrl_msg_wire.intval;
-        return -1;
-}
-
-int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_PING)
-                return 1;
-        return -1;
-}
-
-int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg) {
-        if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_EXIT)
-                return 1;
-        return -1;
+        return sd_event_loop(uctrl->event);
 }