summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/rtnl.c30
-rw-r--r--lib/struct.c9
2 files changed, 27 insertions, 12 deletions
diff --git a/lib/rtnl.c b/lib/rtnl.c
index d4cf8b3..1691377 100644
--- a/lib/rtnl.c
+++ b/lib/rtnl.c
@@ -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);
diff --git a/lib/struct.c b/lib/struct.c
index 5d301db..bd418b2 100644
--- a/lib/struct.c
+++ b/lib/struct.c
@@ -2182,17 +2182,17 @@ overflow:
static uc_value_t *
uc_pack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff)
{
+ size_t ncode, arg, off;
formatcode_t *code;
- size_t ncode, off;
uc_string_t *buf;
ssize_t size, n;
const void *p;
- for (ncode = 0, code = &state->codes[0], off = 0;
+ for (ncode = 0, code = &state->codes[0], arg = argoff, off = 0;
ncode < state->ncodes;
code = &state->codes[++ncode]) {
if (code->fmtdef->format == '*') {
- uc_value_t *v = uc_fn_arg(argoff + ncode);
+ uc_value_t *v = uc_fn_arg(arg++);
if (ucv_type(v) != UC_STRING)
continue;
@@ -2204,6 +2204,9 @@ uc_pack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff)
else
off += code->size;
}
+ else {
+ arg += code->repeat;
+ }
}
buf = xalloc(sizeof(*buf) + state->size + off + 1);