X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Flibsystemd%2Fsd-rtnl%2Fsd-rtnl.c;h=b91d08012ad78aaf52a621fcf59691be876e2a7c;hb=e80af1bdddbc7a51191e29b0c841e8dcafe7b1cc;hp=8650f550f7d1f6bcb40b3e34d51894501c73488e;hpb=4e996881b2a24390b534d84aa89ba70401cc7e69;p=elogind.git diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c index 8650f550f..b91d08012 100644 --- a/src/libsystemd/sd-rtnl/sd-rtnl.c +++ b/src/libsystemd/sd-rtnl/sd-rtnl.c @@ -22,6 +22,7 @@ #include #include +#include "missing.h" #include "macro.h" #include "util.h" #include "hashmap.h" @@ -75,8 +76,27 @@ static bool rtnl_pid_changed(sd_rtnl *rtnl) { return rtnl->original_pid != getpid(); } -int sd_rtnl_open(sd_rtnl **ret, uint32_t groups) { +static int rtnl_compute_groups_ap(uint32_t *_groups, unsigned n_groups, va_list ap) { + uint32_t groups = 0; + unsigned i; + + for (i = 0; i < n_groups; i++) { + unsigned group; + + group = va_arg(ap, unsigned); + assert_return(group < 32, -EINVAL); + + groups |= group ? (1 << (group - 1)) : 0; + } + + *_groups = groups; + + return 0; +} + +int sd_rtnl_open(sd_rtnl **ret, unsigned n_groups, ...) { _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; + va_list ap; socklen_t addrlen; int r, one = 1; @@ -90,10 +110,19 @@ int sd_rtnl_open(sd_rtnl **ret, uint32_t groups) { if (rtnl->fd < 0) return -errno; - if (setsockopt(rtnl->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) + r = setsockopt(rtnl->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); + if (r < 0) return -errno; - rtnl->sockaddr.nl.nl_groups = groups; + r = setsockopt(rtnl->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); @@ -203,8 +232,10 @@ int sd_rtnl_send(sd_rtnl *nl, } } else { /* append to queue */ - if (nl->wqueue_size >= RTNL_WQUEUE_MAX) + if (nl->wqueue_size >= RTNL_WQUEUE_MAX) { + log_debug("rtnl: exhausted the write queue size (%d)", RTNL_WQUEUE_MAX); return -ENOBUFS; + } if (!GREEDY_REALLOC(nl->wqueue, nl->wqueue_allocated, nl->wqueue_size + 1)) return -ENOMEM; @@ -221,8 +252,10 @@ int sd_rtnl_send(sd_rtnl *nl, int rtnl_rqueue_make_room(sd_rtnl *rtnl) { assert(rtnl); - if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX) + if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX) { + log_debug("rtnl: exhausted the read queue size (%d)", RTNL_RQUEUE_MAX); return -ENOBUFS; + } if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_allocated, rtnl->rqueue_size + 1)) return -ENOMEM; @@ -233,8 +266,10 @@ int rtnl_rqueue_make_room(sd_rtnl *rtnl) { int rtnl_rqueue_partial_make_room(sd_rtnl *rtnl) { assert(rtnl); - if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX) + if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX) { + log_debug("rtnl: exhausted the partial read queue size (%d)", RTNL_RQUEUE_MAX); return -ENOBUFS; + } if (!GREEDY_REALLOC(rtnl->rqueue_partial, rtnl->rqueue_partial_allocated, rtnl->rqueue_partial_size + 1))