X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-rtnl%2Fsd-rtnl.c;h=a45ca5e9f57370528836a1fc8aa6be862e8cc124;hb=6d0b55c272ea31d025e8b3c311cea8cda0bfefd7;hp=b91d08012ad78aaf52a621fcf59691be876e2a7c;hpb=66269b05cf31ef5d8f83a7150c314bf35ee8a35e;p=elogind.git diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c index b91d08012..a45ca5e9f 100644 --- a/src/libsystemd/sd-rtnl/sd-rtnl.c +++ b/src/libsystemd/sd-rtnl/sd-rtnl.c @@ -94,52 +94,83 @@ static int rtnl_compute_groups_ap(uint32_t *_groups, unsigned n_groups, va_list return 0; } -int sd_rtnl_open(sd_rtnl **ret, unsigned n_groups, ...) { +static int rtnl_open_fd_ap(sd_rtnl **ret, int fd, unsigned n_groups, va_list ap) { _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; - va_list ap; socklen_t addrlen; int r, one = 1; assert_return(ret, -EINVAL); + assert_return(fd >= 0, -EINVAL); r = sd_rtnl_new(&rtnl); if (r < 0) return r; - rtnl->fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE); - if (rtnl->fd < 0) - return -errno; - - r = setsockopt(rtnl->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); + r = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); if (r < 0) return -errno; - r = setsockopt(rtnl->fd, SOL_NETLINK, NETLINK_PKTINFO, &one, sizeof(one)); + r = setsockopt(fd, SOL_NETLINK, NETLINK_PKTINFO, &one, sizeof(one)); if (r < 0) return -errno; - va_start(ap, n_groups); r = rtnl_compute_groups_ap(&rtnl->sockaddr.nl.nl_groups, n_groups, ap); - va_end(ap); if (r < 0) return r; addrlen = sizeof(rtnl->sockaddr); - r = bind(rtnl->fd, &rtnl->sockaddr.sa, addrlen); + r = bind(fd, &rtnl->sockaddr.sa, addrlen); if (r < 0) return -errno; - r = getsockname(rtnl->fd, &rtnl->sockaddr.sa, &addrlen); + r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen); if (r < 0) return r; + rtnl->fd = fd; + *ret = rtnl; rtnl = NULL; return 0; } +int sd_rtnl_open_fd(sd_rtnl **ret, int fd, unsigned n_groups, ...) { + va_list ap; + int r; + + va_start(ap, n_groups); + r = rtnl_open_fd_ap(ret, fd, n_groups, ap); + va_end(ap); + + return r; +} + +int sd_rtnl_open(sd_rtnl **ret, unsigned n_groups, ...) { + va_list ap; + int fd, r; + + fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE); + if (fd < 0) + return -errno; + + va_start(ap, n_groups); + r = rtnl_open_fd_ap(ret, fd, n_groups, ap); + va_end(ap); + + if (r < 0) { + safe_close(fd); + return r; + } + + return 0; +} + +int sd_rtnl_inc_rcvbuf(const sd_rtnl *const rtnl, const int size) { + return fd_inc_rcvbuf(rtnl->fd, size); +} + sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) { assert_return(rtnl, NULL); assert_return(!rtnl_pid_changed(rtnl), NULL); @@ -473,7 +504,7 @@ static usec_t calc_elapse(uint64_t usec) { static int rtnl_poll(sd_rtnl *rtnl, bool need_more, uint64_t timeout_usec) { struct pollfd p[1] = {}; struct timespec ts; - usec_t m = (usec_t) -1; + usec_t m = USEC_INFINITY; int r, e; assert(rtnl); @@ -485,7 +516,7 @@ static int rtnl_poll(sd_rtnl *rtnl, bool need_more, uint64_t timeout_usec) { if (need_more) /* Caller wants more data, and doesn't care about * what's been read or any other timeouts. */ - return e |= POLLIN; + e |= POLLIN; else { usec_t until; /* Caller wants to process if there is something to @@ -557,7 +588,7 @@ int sd_rtnl_call_async(sd_rtnl *nl, assert_return(callback, -EINVAL); assert_return(!rtnl_pid_changed(nl), -ECHILD); - r = hashmap_ensure_allocated(&nl->reply_callbacks, uint64_hash_func, uint64_compare_func); + r = hashmap_ensure_allocated(&nl->reply_callbacks, &uint64_hash_ops); if (r < 0) return r; @@ -680,7 +711,7 @@ int sd_rtnl_call(sd_rtnl *rtnl, if (r < 0) return r; if (r > 0) - /* receieved message, so try to process straight away */ + /* received message, so try to process straight away */ continue; if (timeout > 0) { @@ -697,6 +728,8 @@ int sd_rtnl_call(sd_rtnl *rtnl, r = rtnl_poll(rtnl, true, left); if (r < 0) return r; + else if (r == 0) + return -ETIMEDOUT; r = dispatch_wqueue(rtnl); if (r < 0) @@ -859,6 +892,10 @@ int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { if (r < 0) goto fail; + r = sd_event_source_set_description(rtnl->io_event_source, "rtnl-receive-message"); + if (r < 0) + goto fail; + r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback); if (r < 0) goto fail; @@ -871,10 +908,18 @@ int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { if (r < 0) goto fail; + r = sd_event_source_set_description(rtnl->time_event_source, "rtnl-timer"); + if (r < 0) + goto fail; + r = sd_event_add_exit(rtnl->event, &rtnl->exit_event_source, exit_callback, rtnl); if (r < 0) goto fail; + r = sd_event_source_set_description(rtnl->exit_event_source, "rtnl-exit"); + if (r < 0) + goto fail; + return 0; fail: