diff options
-rw-r--r-- | src/libsystemd/sd-rtnl/rtnl-message.c | 4 | ||||
-rw-r--r-- | src/libsystemd/sd-rtnl/rtnl-types.c | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-rtnl/sd-rtnl.c | 43 |
3 files changed, 32 insertions, 16 deletions
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c index 5a719003ac..c938471fe3 100644 --- a/src/libsystemd/sd-rtnl/rtnl-message.c +++ b/src/libsystemd/sd-rtnl/rtnl-message.c @@ -1554,7 +1554,9 @@ int socket_read_message(sd_rtnl *rtnl) { /* finished reading multi-part message */ done = true; - continue; + /* if first is not defined, put NLMSG_DONE into the receive queue. */ + if (first) + continue; } /* check that we support this message type */ diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c index e21c898668..bf7278fe44 100644 --- a/src/libsystemd/sd-rtnl/rtnl-types.c +++ b/src/libsystemd/sd-rtnl/rtnl-types.c @@ -411,6 +411,7 @@ static const NLTypeSystem rtnl_neigh_type_system = { }; static const NLType rtnl_types[RTM_MAX + 1] = { + [NLMSG_DONE] = { .type = NLA_META, .size = 0 }, [NLMSG_ERROR] = { .type = NLA_META, .size = sizeof(struct nlmsgerr) }, [RTM_NEWLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, [RTM_DELLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c index 50162c3ee9..40dea1252f 100644 --- a/src/libsystemd/sd-rtnl/sd-rtnl.c +++ b/src/libsystemd/sd-rtnl/sd-rtnl.c @@ -421,8 +421,9 @@ static int process_timeout(sd_rtnl *rtnl) { } static int process_reply(sd_rtnl *rtnl, sd_rtnl_message *m) { - struct reply_callback *c; + _cleanup_free_ struct reply_callback *c = NULL; uint64_t serial; + uint16_t type; int r; assert(rtnl); @@ -436,12 +437,17 @@ static int process_reply(sd_rtnl *rtnl, sd_rtnl_message *m) { if (c->timeout != 0) prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx); + r = sd_rtnl_message_get_type(m, &type); + if (r < 0) + return 0; + + if (type == NLMSG_DONE) + m = NULL; + r = c->callback(rtnl, m, c->userdata); if (r < 0) log_debug_errno(r, "sd-rtnl: callback failed: %m"); - free(c); - return 1; } @@ -702,7 +708,6 @@ int sd_rtnl_call(sd_rtnl *rtnl, sd_rtnl_message **ret) { usec_t timeout; uint32_t serial; - unsigned i = 0; int r; assert_return(rtnl, -EINVAL); @@ -717,36 +722,44 @@ int sd_rtnl_call(sd_rtnl *rtnl, for (;;) { usec_t left; + unsigned i; - while (i < rtnl->rqueue_size) { - sd_rtnl_message *incoming; + for (i = 0; i < rtnl->rqueue_size; i++) { uint32_t received_serial; - incoming = rtnl->rqueue[i]; - received_serial = rtnl_message_get_serial(incoming); + received_serial = rtnl_message_get_serial(rtnl->rqueue[i]); if (received_serial == serial) { + _cleanup_rtnl_message_unref_ sd_rtnl_message *incoming = NULL; + uint16_t type; + + incoming = rtnl->rqueue[i]; + /* found a match, remove from rqueue and return it */ memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1, sizeof(sd_rtnl_message*) * (rtnl->rqueue_size - i - 1)); rtnl->rqueue_size--; r = sd_rtnl_message_get_errno(incoming); - if (r < 0) { - sd_rtnl_message_unref(incoming); + if (r < 0) + return r; + + r = sd_rtnl_message_get_type(incoming, &type); + if (r < 0) return r; + + if (type == NLMSG_DONE) { + *ret = NULL; + return 0; } if (ret) { *ret = incoming; - } else - sd_rtnl_message_unref(incoming); + incoming = NULL; + } return 1; } - - /* Try to read more, right away */ - i ++; } r = socket_read_message(rtnl); |