X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-rtnl%2Frtnl-message.c;h=3a24cb885f36a5d8b51d118f4ae6e5448fb806ac;hp=fc71ed90183c4547a2ccbf604c6651c09f595c88;hb=1403f45ab61d6f2026a3a7a06b52a536c1b7a3b3;hpb=e00d77ddd598ea6cbc2d512d143e9e4d98e62256 diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c index fc71ed901..3a24cb885 100644 --- a/src/libsystemd/sd-rtnl/rtnl-message.c +++ b/src/libsystemd/sd-rtnl/rtnl-message.c @@ -378,6 +378,8 @@ sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) { for (i = 0; i <= m->n_containers; i++) free(m->rta_offset_tb[i]); + sd_rtnl_message_unref(m->next); + free(m); } @@ -1078,6 +1080,8 @@ int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) { * On failure, a negative error code is returned. */ int socket_read_message(sd_rtnl *rtnl) { + _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL; + sd_rtnl_message *previous = NULL; _cleanup_free_ void *buffer = NULL; uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))]; struct iovec iov = {}; @@ -1146,6 +1150,10 @@ int socket_read_message(sd_rtnl *rtnl) { if (new_msg->nlmsg_type == NLMSG_NOOP) continue; + /* finished reading multi-part message */ + if (new_msg->nlmsg_type == NLMSG_DONE) + break; + /* check that we support this message type */ r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type); if (r < 0) { @@ -1173,21 +1181,30 @@ int socket_read_message(sd_rtnl *rtnl) { if (r < 0) return r; - r = rtnl_rqueue_make_room(rtnl); - if (r < 0) - return r; + if (!first) + first = m; + else { + assert(previous); - rtnl->rqueue[rtnl->rqueue_size ++] = m; + previous->next = m; + } + previous = m; m = NULL; + ret += new_msg->nlmsg_len; - /* reached end of multi-part message, or not a multi-part - message at all */ - if (new_msg->nlmsg_type == NLMSG_DONE || - !(new_msg->nlmsg_flags & NLM_F_MULTI)) + /* not a multi-part message, so stop reading*/ + if (!(new_msg->nlmsg_flags & NLM_F_MULTI)) break; } + r = rtnl_rqueue_make_room(rtnl); + if (r < 0) + return r; + + rtnl->rqueue[rtnl->rqueue_size ++] = first; + first = NULL; + return ret; } @@ -1249,3 +1266,9 @@ void rtnl_message_seal(sd_rtnl_message *m) { m->sealed = true; } + +sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) { + assert_return(m, NULL); + + return m->next; +}