diff options
Diffstat (limited to 'lib/rtnl.c')
-rw-r--r-- | lib/rtnl.c | 30 |
1 files changed, 21 insertions, 9 deletions
@@ -1345,10 +1345,13 @@ uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsiz if (!tb) return false; - if (buflen > headsize) - nla_parse(tb, maxattr, buf + headsize, buflen - headsize, NULL); - else + if (buflen > headsize) { + if (maxattr) + nla_parse(tb, maxattr, buf + headsize, buflen - headsize, NULL); + } + else { structlen = buflen; + } for (i = 0; i < nattrs; i++) { if (attrs[i].attr == 0 && (uintptr_t)attrs[i].auxdata >= structlen) @@ -3088,10 +3091,7 @@ cb_reply(struct nl_msg *msg, void *arg) } } - if (hdr->nlmsg_flags & NLM_F_MULTI) - s->state = STATE_CONTINUE; - else - s->state = STATE_REPLIED; + s->state = STATE_CONTINUE; return NL_SKIP; } @@ -3122,6 +3122,7 @@ uc_nl_request(uc_vm_t *vm, size_t nargs) int enable = 1, err; struct nl_msg *msg; struct nl_cb *cb; + void *buf; size_t i; if (ucv_type(cmd) != UC_INTEGER || ucv_int64_get(cmd) < 0 || @@ -3169,7 +3170,17 @@ uc_nl_request(uc_vm_t *vm, size_t nargs) err_return(NLE_NOMEM, NULL); if (st.spec) { - nlmsg_reserve(msg, st.spec->headsize, 0); + if (st.spec->headsize) { + buf = nlmsg_reserve(msg, st.spec->headsize, 0); + + if (!buf) { + nlmsg_free(msg); + + return NULL; + } + + memset(buf, 0, st.spec->headsize); + } if (!uc_nl_parse_attrs(msg, NLMSG_DATA(nlmsg_hdr(msg)), st.spec->attrs, st.spec->nattrs, vm, payload)) { nlmsg_free(msg); @@ -3187,6 +3198,7 @@ uc_nl_request(uc_vm_t *vm, size_t nargs) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_reply, &st); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_done, &st); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_done, &st); nl_cb_err(cb, NL_CB_CUSTOM, cb_error, &st); nl_send_auto_complete(sock, msg); @@ -3200,7 +3212,7 @@ uc_nl_request(uc_vm_t *vm, size_t nargs) st.state = STATE_ERROR; } } - while (st.state == STATE_CONTINUE); + while (st.state < STATE_REPLIED); nlmsg_free(msg); nl_cb_put(cb); |