summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/cmd.h7
-rw-r--r--include/mnl.h13
-rw-r--r--include/netlink.h20
-rw-r--r--include/rule.h9
-rw-r--r--src/Makefile.am1
-rw-r--r--src/libnftables.c23
-rw-r--r--src/mnl.c190
-rw-r--r--src/monitor.c3
-rw-r--r--src/rule.c8
9 files changed, 218 insertions, 56 deletions
diff --git a/include/cmd.h b/include/cmd.h
new file mode 100644
index 00000000..27fa6087
--- /dev/null
+++ b/include/cmd.h
@@ -0,0 +1,7 @@
+#ifndef _NFT_CMD_H_
+#define _NFT_CMD_H_
+
+void nft_cmd_error(struct netlink_ctx *ctx, struct cmd *cmd,
+ struct mnl_err *err);
+
+#endif
diff --git a/include/mnl.h b/include/mnl.h
index eeba7379..07669957 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -16,6 +16,7 @@ struct mnl_err {
struct list_head head;
int err;
uint32_t seqnum;
+ uint32_t offset;
};
void mnl_err_list_free(struct mnl_err *err);
@@ -28,7 +29,7 @@ void mnl_batch_end(struct nftnl_batch *batch, uint32_t seqnum);
int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
uint32_t num_cmds);
-int mnl_nft_rule_add(struct netlink_ctx *ctx, const struct cmd *cmd,
+int mnl_nft_rule_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags);
int mnl_nft_rule_del(struct netlink_ctx *ctx, const struct cmd *cmd);
int mnl_nft_rule_replace(struct netlink_ctx *ctx, const struct cmd *cmd);
@@ -38,7 +39,7 @@ struct nftnl_rule_list *mnl_nft_rule_dump(struct netlink_ctx *ctx,
int mnl_nft_chain_add(struct netlink_ctx *ctx, const struct cmd *cmd,
unsigned int flags);
-int mnl_nft_chain_del(struct netlink_ctx *ctx, const struct cmd *cmd);
+int mnl_nft_chain_del(struct netlink_ctx *ctx, struct cmd *cmd);
int mnl_nft_chain_rename(struct netlink_ctx *ctx, const struct cmd *cmd,
const struct chain *chain);
@@ -47,14 +48,14 @@ struct nftnl_chain_list *mnl_nft_chain_dump(struct netlink_ctx *ctx,
int mnl_nft_table_add(struct netlink_ctx *ctx, const struct cmd *cmd,
unsigned int flags);
-int mnl_nft_table_del(struct netlink_ctx *ctx, const struct cmd *cmd);
+int mnl_nft_table_del(struct netlink_ctx *ctx, struct cmd *cmd);
struct nftnl_table_list *mnl_nft_table_dump(struct netlink_ctx *ctx,
int family);
int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
unsigned int flags);
-int mnl_nft_set_del(struct netlink_ctx *ctx, const struct cmd *cmd);
+int mnl_nft_set_del(struct netlink_ctx *ctx, struct cmd *cmd);
struct nftnl_set_list *mnl_nft_set_dump(struct netlink_ctx *ctx, int family,
const char *table);
@@ -73,14 +74,14 @@ struct nftnl_obj_list *mnl_nft_obj_dump(struct netlink_ctx *ctx, int family,
bool dump, bool reset);
int mnl_nft_obj_add(struct netlink_ctx *ctx, const struct cmd *cmd,
unsigned int flags);
-int mnl_nft_obj_del(struct netlink_ctx *ctx, const struct cmd *cmd, int type);
+int mnl_nft_obj_del(struct netlink_ctx *ctx, struct cmd *cmd, int type);
struct nftnl_flowtable_list *
mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table);
int mnl_nft_flowtable_add(struct netlink_ctx *ctx, const struct cmd *cmd,
unsigned int flags);
-int mnl_nft_flowtable_del(struct netlink_ctx *ctx, const struct cmd *cmd);
+int mnl_nft_flowtable_del(struct netlink_ctx *ctx, struct cmd *cmd);
int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
struct output_ctx *octx,
diff --git a/include/netlink.h b/include/netlink.h
index d02533ec..c2eb8949 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -16,6 +16,22 @@
#define MAX_REGS (1 + NFT_REG32_15 - NFT_REG32_00)
+#ifndef NETLINK_EXT_ACK
+#define NETLINK_EXT_ACK 11
+
+enum nlmsgerr_attrs {
+ NLMSGERR_ATTR_UNUSED,
+ NLMSGERR_ATTR_MSG,
+ NLMSGERR_ATTR_OFFS,
+ NLMSGERR_ATTR_COOKIE,
+
+ __NLMSGERR_ATTR_MAX,
+ NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
+};
+#define NLM_F_CAPPED 0x100 /* request was capped */
+#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
+#endif
+
struct netlink_parse_ctx {
struct list_head *msgs;
struct table *table;
@@ -176,6 +192,10 @@ struct netlink_mon_handler {
extern int netlink_monitor(struct netlink_mon_handler *monhandler,
struct mnl_socket *nf_sock);
+struct netlink_cb_data {
+ struct netlink_ctx *nl_ctx;
+ struct list_head *err_list;
+};
int netlink_echo_callback(const struct nlmsghdr *nlh, void *data);
struct ruleset_parse {
diff --git a/include/rule.h b/include/rule.h
index c232221e..ced63f3e 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -635,6 +635,8 @@ struct monitor {
struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event);
void monitor_free(struct monitor *m);
+#define NFT_NLATTR_LOC_MAX 8
+
/**
* struct cmd - command statement
*
@@ -666,6 +668,11 @@ struct cmd {
struct markup *markup;
struct obj *object;
};
+ struct {
+ uint16_t offset;
+ struct location *location;
+ } attr[NFT_NLATTR_LOC_MAX];
+ int num_attrs;
const void *arg;
};
@@ -678,6 +685,8 @@ extern struct cmd *cmd_alloc_obj_ct(enum cmd_ops op, int type,
const struct location *loc, struct obj *obj);
extern void cmd_free(struct cmd *cmd);
+void cmd_add_loc(struct cmd *cmd, uint16_t offset, struct location *loc);
+
#include <payload.h>
#include <expression.h>
diff --git a/src/Makefile.am b/src/Makefile.am
index 740c21f2..9142ab44 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ libnftables_la_SOURCES = \
rule.c \
statement.c \
cache.c \
+ cmd.c \
datatype.c \
expression.c \
evaluate.c \
diff --git a/src/libnftables.c b/src/libnftables.c
index cd2fcf2f..eaa4736c 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -17,6 +17,25 @@
#include <stdlib.h>
#include <string.h>
+static void nft_error(struct netlink_ctx *ctx, struct cmd *cmd,
+ struct mnl_err *err)
+{
+ struct location *loc = NULL;
+ int i;
+
+ for (i = 0; i < cmd->num_attrs; i++) {
+ if (!cmd->attr[i].offset)
+ break;
+ if (cmd->attr[i].offset == err->offset)
+ loc = cmd->attr[i].location;
+ }
+ if (!loc)
+ loc = &cmd->location;
+
+ netlink_io_error(ctx, loc, "Could not process rule: %s",
+ strerror(err->err));
+}
+
static int nft_netlink(struct nft_ctx *nft,
struct list_head *cmds, struct list_head *msgs,
struct mnl_socket *nf_sock)
@@ -68,9 +87,7 @@ static int nft_netlink(struct nft_ctx *nft,
list_for_each_entry(cmd, cmds, list) {
if (err->seqnum == cmd->seqnum ||
err->seqnum == batch_seqnum) {
- netlink_io_error(&ctx, &cmd->location,
- "Could not process rule: %s",
- strerror(err->err));
+ nft_error(&ctx, cmd, err);
errno = err->err;
if (err->seqnum == cmd->seqnum) {
mnl_err_list_free(err);
diff --git a/src/mnl.c b/src/mnl.c
index 340380ba..ee82db80 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -37,6 +37,7 @@
struct mnl_socket *nft_mnl_socket_open(void)
{
struct mnl_socket *nf_sock;
+ int one = 1;
nf_sock = mnl_socket_open(NETLINK_NETFILTER);
if (!nf_sock)
@@ -45,6 +46,8 @@ struct mnl_socket *nft_mnl_socket_open(void)
if (fcntl(mnl_socket_get_fd(nf_sock), F_SETFL, O_NONBLOCK))
netlink_init_error();
+ mnl_socket_setsockopt(nf_sock, NETLINK_EXT_ACK, &one, sizeof(one));
+
return nf_sock;
}
@@ -204,11 +207,13 @@ void mnl_batch_reset(struct nftnl_batch *batch)
}
static void mnl_err_list_node_add(struct list_head *err_list, int error,
- int seqnum)
+ int seqnum, uint32_t offset,
+ const char *errmsg)
{
struct mnl_err *err = xmalloc(sizeof(struct mnl_err));
err->seqnum = seqnum;
+ err->offset = offset;
err->err = error;
list_add_tail(&err->head, err_list);
}
@@ -305,6 +310,61 @@ static ssize_t mnl_nft_socket_sendmsg(struct netlink_ctx *ctx,
return sendmsg(mnl_socket_get_fd(ctx->nft->nf_sock), msg, 0);
}
+static int err_attr_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ uint16_t type;
+
+ if (mnl_attr_type_valid(attr, NLMSGERR_ATTR_MAX) < 0)
+ return MNL_CB_ERROR;
+
+ type = mnl_attr_get_type(attr);
+ switch (type) {
+ case NLMSGERR_ATTR_OFFS:
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+ return MNL_CB_ERROR;
+ break;
+ }
+
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static int mnl_batch_extack_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct netlink_cb_data *cb_data = data;
+ struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
+ const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
+ unsigned int hlen = sizeof(*err);
+ const char *msg = NULL;
+ uint32_t off = 0;
+ int errval;
+
+ if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
+ return MNL_CB_ERROR;
+
+ if (err->error < 0)
+ errval = -err->error;
+ else
+ errval = err->error;
+
+ if (errval == 0)
+ return MNL_CB_STOP;
+
+ if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
+ hlen += mnl_nlmsg_get_payload_len(&err->msg);
+
+ if (mnl_attr_parse(nlh, hlen, err_attr_cb, tb) != MNL_CB_OK)
+ return MNL_CB_ERROR;
+
+ if (tb[NLMSGERR_ATTR_OFFS])
+ off = mnl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
+
+ mnl_err_list_node_add(cb_data->err_list, errval,
+ nlh->nlmsg_seq, off, msg);
+ return MNL_CB_ERROR;
+}
+
#define NFT_MNL_ECHO_RCVBUFF_DEFAULT (MNL_SOCKET_BUFFER_SIZE * 1024)
int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
@@ -326,6 +386,13 @@ int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
unsigned int rcvbufsiz;
size_t batch_size;
fd_set readfds;
+ static mnl_cb_t cb_ctl_array[NLMSG_MIN_TYPE] = {
+ [NLMSG_ERROR] = mnl_batch_extack_cb,
+ };
+ struct netlink_cb_data cb_data = {
+ .err_list = err_list,
+ .nl_ctx = ctx,
+ };
mnl_set_sndbuffer(ctx->nft->nf_sock, ctx->batch);
@@ -361,18 +428,15 @@ int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
if (ret == -1)
return -1;
- ret = mnl_cb_run(rcv_buf, ret, 0, portid, &netlink_echo_callback, ctx);
/* Continue on error, make sure we get all acknowledgments */
- if (ret == -1) {
- struct nlmsghdr *nlh = (struct nlmsghdr *)rcv_buf;
-
- mnl_err_list_node_add(err_list, errno, nlh->nlmsg_seq);
- }
+ ret = mnl_cb_run2(rcv_buf, ret, 0, portid,
+ netlink_echo_callback, &cb_data,
+ cb_ctl_array, MNL_ARRAY_SIZE(cb_ctl_array));
}
return 0;
}
-int mnl_nft_rule_add(struct netlink_ctx *ctx, const struct cmd *cmd,
+int mnl_nft_rule_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags)
{
struct rule *rule = cmd->rule;
@@ -385,8 +449,6 @@ int mnl_nft_rule_add(struct netlink_ctx *ctx, const struct cmd *cmd,
memory_allocation_error();
nftnl_rule_set_u32(nlr, NFTNL_RULE_FAMILY, h->family);
- nftnl_rule_set_str(nlr, NFTNL_RULE_TABLE, h->table.name);
- nftnl_rule_set_str(nlr, NFTNL_RULE_CHAIN, h->chain.name);
if (h->position.id)
nftnl_rule_set_u64(nlr, NFTNL_RULE_POSITION, h->position.id);
if (h->rule_id)
@@ -399,6 +461,12 @@ int mnl_nft_rule_add(struct netlink_ctx *ctx, const struct cmd *cmd,
NFT_MSG_NEWRULE,
cmd->handle.family,
NLM_F_CREATE | flags, ctx->seqnum);
+
+ cmd_add_loc(cmd, nlh->nlmsg_len, &h->table.location);
+ mnl_attr_put_strz(nlh, NFTA_RULE_TABLE, h->table.name);
+ cmd_add_loc(cmd, nlh->nlmsg_len, &h->chain.location);
+ mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, h->chain.name);
+
nftnl_rule_nlmsg_build_payload(nlh, nlr);
nftnl_rule_free(nlr);
@@ -624,7 +692,7 @@ int mnl_nft_chain_rename(struct netlink_ctx *ctx, const struct cmd *cmd,
return 0;
}
-int mnl_nft_chain_del(struct netlink_ctx *ctx, const struct cmd *cmd)
+int mnl_nft_chain_del(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct nftnl_chain *nlc;
struct nlmsghdr *nlh;
@@ -634,18 +702,23 @@ int mnl_nft_chain_del(struct netlink_ctx *ctx, const struct cmd *cmd)
memory_allocation_error();
nftnl_chain_set_u32(nlc, NFTNL_CHAIN_FAMILY, cmd->handle.family);
- nftnl_chain_set_str(nlc, NFTNL_CHAIN_TABLE, cmd->handle.table.name);
- if (cmd->handle.chain.name)
- nftnl_chain_set_str(nlc, NFTNL_CHAIN_NAME,
- cmd->handle.chain.name);
- else if (cmd->handle.handle.id)
- nftnl_chain_set_u64(nlc, NFTNL_CHAIN_HANDLE,
- cmd->handle.handle.id);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_DELCHAIN,
cmd->handle.family,
0, ctx->seqnum);
+
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
+ mnl_attr_put_strz(nlh, NFTA_CHAIN_TABLE, cmd->handle.table.name);
+ if (cmd->handle.chain.name) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.chain.location);
+ mnl_attr_put_strz(nlh, NFTA_CHAIN_NAME, cmd->handle.chain.name);
+ } else if (cmd->handle.handle.id) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.handle.location);
+ mnl_attr_put_u64(nlh, NFTA_CHAIN_HANDLE,
+ htobe64(cmd->handle.handle.id));
+ }
+
nftnl_chain_nlmsg_build_payload(nlh, nlc);
nftnl_chain_free(nlc);
@@ -734,7 +807,7 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, const struct cmd *cmd,
return 0;
}
-int mnl_nft_table_del(struct netlink_ctx *ctx, const struct cmd *cmd)
+int mnl_nft_table_del(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct nftnl_table *nlt;
struct nlmsghdr *nlh;
@@ -744,17 +817,20 @@ int mnl_nft_table_del(struct netlink_ctx *ctx, const struct cmd *cmd)
memory_allocation_error();
nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, cmd->handle.family);
- if (cmd->handle.table.name)
- nftnl_table_set_str(nlt, NFTNL_TABLE_NAME,
- cmd->handle.table.name);
- else if (cmd->handle.handle.id)
- nftnl_table_set_u64(nlt, NFTNL_TABLE_HANDLE,
- cmd->handle.handle.id);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_DELTABLE,
cmd->handle.family,
0, ctx->seqnum);
+
+ if (cmd->handle.table.name) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
+ mnl_attr_put_strz(nlh, NFTA_TABLE_NAME, cmd->handle.table.name);
+ } else if (cmd->handle.handle.id) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.handle.location);
+ mnl_attr_put_u64(nlh, NFTA_TABLE_NAME,
+ htobe64(cmd->handle.handle.id));
+ }
nftnl_table_nlmsg_build_payload(nlh, nlt);
nftnl_table_free(nlt);
@@ -930,7 +1006,7 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
return 0;
}
-int mnl_nft_set_del(struct netlink_ctx *ctx, const struct cmd *cmd)
+int mnl_nft_set_del(struct netlink_ctx *ctx, struct cmd *cmd)
{
const struct handle *h = &cmd->handle;
struct nftnl_set *nls;
@@ -941,16 +1017,23 @@ int mnl_nft_set_del(struct netlink_ctx *ctx, const struct cmd *cmd)
memory_allocation_error();
nftnl_set_set_u32(nls, NFTNL_SET_FAMILY, h->family);
- nftnl_set_set_str(nls, NFTNL_SET_TABLE, h->table.name);
- if (h->set.name)
- nftnl_set_set_str(nls, NFTNL_SET_NAME, h->set.name);
- else if (h->handle.id)
- nftnl_set_set_u64(nls, NFTNL_SET_HANDLE, h->handle.id);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_DELSET,
h->family,
0, ctx->seqnum);
+
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
+ mnl_attr_put_strz(nlh, NFTA_SET_TABLE, cmd->handle.table.name);
+ if (h->set.name) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.set.location);
+ mnl_attr_put_strz(nlh, NFTA_SET_NAME, cmd->handle.set.name);
+ } else if (h->handle.id) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.handle.location);
+ mnl_attr_put_u64(nlh, NFTA_SET_HANDLE,
+ htobe64(cmd->handle.handle.id));
+ }
+
nftnl_set_nlmsg_build_payload(nlh, nls);
nftnl_set_free(nls);
@@ -1115,7 +1198,7 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, const struct cmd *cmd,
return 0;
}
-int mnl_nft_obj_del(struct netlink_ctx *ctx, const struct cmd *cmd, int type)
+int mnl_nft_obj_del(struct netlink_ctx *ctx, struct cmd *cmd, int type)
{
struct nftnl_obj *nlo;
struct nlmsghdr *nlh;
@@ -1125,16 +1208,24 @@ int mnl_nft_obj_del(struct netlink_ctx *ctx, const struct cmd *cmd, int type)
memory_allocation_error();
nftnl_obj_set_u32(nlo, NFTNL_OBJ_FAMILY, cmd->handle.family);
- nftnl_obj_set_str(nlo, NFTNL_OBJ_TABLE, cmd->handle.table.name);
nftnl_obj_set_u32(nlo, NFTNL_OBJ_TYPE, type);
- if (cmd->handle.obj.name)
- nftnl_obj_set_str(nlo, NFTNL_OBJ_NAME, cmd->handle.obj.name);
- else if (cmd->handle.handle.id)
- nftnl_obj_set_u64(nlo, NFTNL_OBJ_HANDLE, cmd->handle.handle.id);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_DELOBJ, cmd->handle.family,
0, ctx->seqnum);
+
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
+ mnl_attr_put_strz(nlh, NFTA_OBJ_TABLE, cmd->handle.table.name);
+
+ if (cmd->handle.obj.name) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.obj.location);
+ mnl_attr_put_strz(nlh, NFTA_OBJ_NAME, cmd->handle.obj.name);
+ } else if (cmd->handle.handle.id) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.handle.location);
+ mnl_attr_put_u64(nlh, NFTA_OBJ_HANDLE,
+ htobe64(cmd->handle.handle.id));
+ }
+
nftnl_obj_nlmsg_build_payload(nlh, nlo);
nftnl_obj_free(nlo);
@@ -1493,7 +1584,7 @@ int mnl_nft_flowtable_add(struct netlink_ctx *ctx, const struct cmd *cmd,
return 0;
}
-int mnl_nft_flowtable_del(struct netlink_ctx *ctx, const struct cmd *cmd)
+int mnl_nft_flowtable_del(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct nftnl_flowtable *flo;
struct nlmsghdr *nlh;
@@ -1504,18 +1595,25 @@ int mnl_nft_flowtable_del(struct netlink_ctx *ctx, const struct cmd *cmd)
nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_FAMILY,
cmd->handle.family);
- nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE,
- cmd->handle.table.name);
- if (cmd->handle.flowtable.name)
- nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME,
- cmd->handle.flowtable.name);
- else if (cmd->handle.handle.id)
- nftnl_flowtable_set_u64(flo, NFTNL_FLOWTABLE_HANDLE,
- cmd->handle.handle.id);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_DELFLOWTABLE, cmd->handle.family,
0, ctx->seqnum);
+
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
+ mnl_attr_put_strz(nlh, NFTA_FLOWTABLE_TABLE, cmd->handle.table.name);
+
+ if (cmd->handle.flowtable.name) {
+ cmd_add_loc(cmd, nlh->nlmsg_len,
+ &cmd->handle.flowtable.location);
+ mnl_attr_put_strz(nlh, NFTA_FLOWTABLE_NAME,
+ cmd->handle.flowtable.name);
+ } else if (cmd->handle.handle.id) {
+ cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.handle.location);
+ mnl_attr_put_u64(nlh, NFTA_FLOWTABLE_HANDLE,
+ htobe64(cmd->handle.handle.id));
+ }
+
nftnl_flowtable_nlmsg_build_payload(nlh, flo);
nftnl_flowtable_free(flo);
diff --git a/src/monitor.c b/src/monitor.c
index 142cc929..bb269c02 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -906,7 +906,8 @@ static int netlink_events_cb(const struct nlmsghdr *nlh, void *data)
int netlink_echo_callback(const struct nlmsghdr *nlh, void *data)
{
- struct netlink_ctx *ctx = data;
+ struct netlink_cb_data *nl_cb_data = data;
+ struct netlink_ctx *ctx = nl_cb_data->nl_ctx;
struct netlink_mon_handler echo_monh = {
.format = NFTNL_OUTPUT_DEFAULT,
.ctx = ctx,
diff --git a/src/rule.c b/src/rule.c
index 337a66bb..9307dad5 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1377,6 +1377,14 @@ struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
return cmd;
}
+void cmd_add_loc(struct cmd *cmd, uint16_t offset, struct location *loc)
+{
+ assert(cmd->num_attrs < NFT_NLATTR_LOC_MAX);
+ cmd->attr[cmd->num_attrs].offset = offset;
+ cmd->attr[cmd->num_attrs].location = loc;
+ cmd->num_attrs++;
+}
+
void nft_cmd_expand(struct cmd *cmd)
{
struct list_head new_cmds;