#define NFT_NLATTR_LOC_MAX 32
struct nlerr_loc {
+ uint32_t seqnum;
uint32_t offset;
const struct location *location;
};
enum cmd_ops op;
enum cmd_obj obj;
struct handle handle;
- uint32_t seqnum;
+ uint32_t seqnum_from;
+ uint32_t seqnum_to;
union {
void *data;
struct expr *expr;
cmd->attr = xrealloc(cmd->attr, sizeof(struct nlerr_loc) * cmd->attr_array_len);
}
+ cmd->attr[cmd->num_attrs].seqnum = nlh->nlmsg_seq;
cmd->attr[cmd->num_attrs].offset = nlh->nlmsg_len;
cmd->attr[cmd->num_attrs].location = loc;
cmd->num_attrs++;
uint32_t i;
for (i = 0; i < cmd->num_attrs; i++) {
- if (cmd->attr[i].offset == err->offset)
+ if (cmd->attr[i].seqnum == err->seqnum &&
+ cmd->attr[i].offset == err->offset)
loc = cmd->attr[i].location;
}
batch_seqnum = mnl_batch_begin(ctx.batch, mnl_seqnum_inc(&seqnum));
list_for_each_entry(cmd, cmds, list) {
- ctx.seqnum = cmd->seqnum = mnl_seqnum_inc(&seqnum);
+ ctx.seqnum = cmd->seqnum_from = mnl_seqnum_inc(&seqnum);
ret = do_command(&ctx, cmd);
if (ret < 0) {
netlink_io_error(&ctx, &cmd->location,
strerror(errno));
goto out;
}
+ seqnum = cmd->seqnum_to = ctx.seqnum;
+ mnl_seqnum_inc(&seqnum);
num_cmds++;
}
if (!nft->check)
cmd = list_first_entry(cmds, struct cmd, list);
list_for_each_entry_from(cmd, cmds, list) {
- last_seqnum = cmd->seqnum;
- if (err->seqnum == cmd->seqnum ||
+ last_seqnum = cmd->seqnum_to;
+ if ((err->seqnum >= cmd->seqnum_from &&
+ err->seqnum <= cmd->seqnum_to) ||
err->seqnum == batch_seqnum) {
nft_cmd_error(&ctx, cmd, err);
errno = err->err;
- if (err->seqnum == cmd->seqnum) {
+ if (err->seqnum >= cmd->seqnum_from ||
+ err->seqnum <= cmd->seqnum_to) {
mnl_err_list_free(err);
break;
}
static int mnl_nft_setelem_batch(const struct nftnl_set *nls, struct cmd *cmd,
struct nftnl_batch *batch,
enum nf_tables_msg_types msg_type,
- unsigned int flags, uint32_t seqnum,
+ unsigned int flags, uint32_t *seqnum,
const struct expr *set,
struct netlink_ctx *ctx)
{
next:
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), msg_type,
nftnl_set_get_u32(nls, NFTNL_SET_FAMILY),
- flags, seqnum);
+ flags, *seqnum);
if (nftnl_set_is_set(nls, NFTNL_SET_TABLE)) {
mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE,
if (mnl_nft_attr_nest_overflow(nlh, nest1, nest2)) {
mnl_attr_nest_end(nlh, nest1);
mnl_nft_batch_continue(batch);
+ mnl_seqnum_inc(seqnum);
goto next;
}
}
netlink_dump_set(nls, ctx);
err = mnl_nft_setelem_batch(nls, cmd, ctx->batch, NFT_MSG_NEWSETELEM,
- flags, ctx->seqnum, expr, ctx);
+ flags, &ctx->seqnum, expr, ctx);
nftnl_set_free(nls);
return err;
msg_type = NFT_MSG_DESTROYSETELEM;
err = mnl_nft_setelem_batch(nls, cmd, ctx->batch, msg_type, 0,
- ctx->seqnum, init, ctx);
+ &ctx->seqnum, init, ctx);
nftnl_set_free(nls);
return err;
cur = json_cmd_assoc_list;
json_cmd_assoc_list = cur->next;
- key = cur->cmd->seqnum % CMD_ASSOC_HSIZE;
+ key = cur->cmd->seqnum_from % CMD_ASSOC_HSIZE;
hlist_add_head(&cur->hnode, &json_cmd_assoc_hash[key]);
}
key = seqnum % CMD_ASSOC_HSIZE;
hlist_for_each_entry(cur, n, &json_cmd_assoc_hash[key], hnode) {
- if (cur->cmd->seqnum == seqnum)
+ if (cur->cmd->seqnum_from == seqnum)
return cur->json;
}