summaryrefslogtreecommitdiffstats
path: root/iptables/nft.c
diff options
context:
space:
mode:
Diffstat (limited to 'iptables/nft.c')
-rw-r--r--iptables/nft.c357
1 files changed, 152 insertions, 205 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index e3b07e03..6cb03a0d 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -61,10 +61,8 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
int ret;
char buf[MNL_SOCKET_BUFFER_SIZE];
- if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0) {
- perror("mnl_socket_send");
+ if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0)
return -1;
- }
ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
while (ret > 0) {
@@ -142,6 +140,18 @@ static void mnl_nft_set_sndbuffer(const struct mnl_socket *nl)
nlbuffsiz = newbuffsiz;
}
+static void mnl_nft_batch_reset(void)
+{
+ struct batch_page *batch_page, *next;
+
+ list_for_each_entry_safe(batch_page, next, &batch_page_list, head) {
+ list_del(&batch_page->head);
+ free(batch_page->batch);
+ free(batch_page);
+ batch_num_pages--;
+ }
+}
+
static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl)
{
static const struct sockaddr_nl snl = {
@@ -154,12 +164,12 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl)
.msg_iov = iov,
.msg_iovlen = batch_num_pages,
};
- struct batch_page *batch_page, *next;
- int i = 0;
+ struct batch_page *batch_page;
+ int i = 0, ret;
mnl_nft_set_sndbuffer(nl);
- list_for_each_entry_safe(batch_page, next, &batch_page_list, head) {
+ list_for_each_entry(batch_page, &batch_page_list, head) {
iov[i].iov_base = mnl_nlmsg_batch_head(batch_page->batch);
iov[i].iov_len = mnl_nlmsg_batch_size(batch_page->batch);
i++;
@@ -169,26 +179,14 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl)
mnl_nlmsg_batch_size(batch_page->batch),
sizeof(struct nfgenmsg));
#endif
- list_del(&batch_page->head);
- free(batch_page->batch);
- free(batch_page);
- batch_num_pages--;
}
- return sendmsg(mnl_socket_get_fd(nl), &msg, 0);
-}
+ ret = sendmsg(mnl_socket_get_fd(nl), &msg, 0);
+ mnl_nft_batch_reset();
-static int cb_err(const struct nlmsghdr *nlh, void *data)
-{
- /* We can provide better error reporting than iptables-restore */
- errno = EINVAL;
- return MNL_CB_ERROR;
+ return ret;
}
-static mnl_cb_t cb_ctl_array[NLMSG_MIN_TYPE] = {
- [NLMSG_ERROR] = cb_err,
-};
-
static int mnl_nft_batch_talk(struct nft_handle *h)
{
int ret, fd = mnl_socket_get_fd(h->nl);
@@ -201,78 +199,59 @@ static int mnl_nft_batch_talk(struct nft_handle *h)
int err = 0;
ret = mnl_nft_socket_sendmsg(h->nl);
- if (ret == -1) {
- perror("mnl_socket_sendmsg");
+ if (ret == -1)
return -1;
- }
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
/* receive and digest all the acknowledgments from the kernel. */
ret = select(fd+1, &readfds, NULL, NULL, &tv);
- if (ret == -1) {
- perror("select");
+ if (ret == -1)
return -1;
- }
+
while (ret > 0 && FD_ISSET(fd, &readfds)) {
ret = mnl_socket_recvfrom(h->nl, rcv_buf, sizeof(rcv_buf));
- if (ret == -1) {
- perror("mnl_socket_recvfrom");
+ if (ret == -1)
return -1;
- }
- ret = mnl_cb_run2(rcv_buf, ret, 0, h->portid,
- NULL, NULL, cb_ctl_array,
- MNL_ARRAY_SIZE(cb_ctl_array));
- /* Continue on error, make sure we get all acknoledgments */
- if (ret == -1)
+ ret = mnl_cb_run(rcv_buf, ret, 0, h->portid, NULL, NULL);
+ /* Annotate first error and continue, make sure we get all
+ * acknoledgments.
+ */
+ if (!err && ret == -1)
err = errno;
ret = select(fd+1, &readfds, NULL, NULL, &tv);
- if (ret == -1) {
- perror("select");
+ if (ret == -1)
return -1;
- }
+
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
}
+ errno = err;
return err ? -1 : 0;
}
-static void mnl_nft_batch_put(struct mnl_nlmsg_batch *batch, int type,
- uint32_t seq)
+static void mnl_nft_batch_begin(struct mnl_nlmsg_batch *batch, uint32_t seq)
{
- struct nlmsghdr *nlh;
- struct nfgenmsg *nfg;
-
- nlh = mnl_nlmsg_put_header(mnl_nlmsg_batch_current(batch));
- nlh->nlmsg_type = type;
- nlh->nlmsg_flags = NLM_F_REQUEST;
- nlh->nlmsg_seq = seq;
-
- nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
- nfg->nfgen_family = AF_INET;
- nfg->version = NFNETLINK_V0;
- nfg->res_id = NFNL_SUBSYS_NFTABLES;
-
+ nft_batch_begin(mnl_nlmsg_batch_current(batch), seq);
if (!mnl_nlmsg_batch_next(batch))
mnl_nft_batch_page_add(batch);
}
-static void mnl_nft_batch_begin(struct mnl_nlmsg_batch *batch, uint32_t seq)
-{
- mnl_nft_batch_put(batch, NFNL_MSG_BATCH_BEGIN, seq);
-}
-
static void mnl_nft_batch_end(struct mnl_nlmsg_batch *batch, uint32_t seq)
{
- mnl_nft_batch_put(batch, NFNL_MSG_BATCH_END, seq);
+ nft_batch_end(mnl_nlmsg_batch_current(batch), seq);
+ if (!mnl_nlmsg_batch_next(batch))
+ mnl_nft_batch_page_add(batch);
}
enum obj_update_type {
NFT_COMPAT_TABLE_ADD,
NFT_COMPAT_CHAIN_ADD,
+ NFT_COMPAT_CHAIN_USER_ADD,
+ NFT_COMPAT_CHAIN_USER_DEL,
NFT_COMPAT_CHAIN_UPDATE,
NFT_COMPAT_RULE_APPEND,
NFT_COMPAT_RULE_INSERT,
@@ -539,7 +518,7 @@ static int nft_table_builtin_add(struct nft_handle *h,
return ret;
}
-struct nft_chain *
+static struct nft_chain *
nft_chain_builtin_alloc(struct builtin_table *table,
struct builtin_chain *chain, int policy)
{
@@ -582,12 +561,13 @@ int nft_chain_add(struct nft_handle *h, struct nft_chain *c, uint16_t flags)
return mnl_talk(h, nlh, NULL, NULL);
}
-void nft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
- struct builtin_chain *chain, int policy)
+static void nft_chain_builtin_add(struct nft_handle *h,
+ struct builtin_table *table,
+ struct builtin_chain *chain)
{
struct nft_chain *c;
- c = nft_chain_builtin_alloc(table, chain, policy);
+ c = nft_chain_builtin_alloc(table, chain, NF_ACCEPT);
if (c == NULL)
return;
@@ -598,7 +578,7 @@ void nft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
}
/* find if built-in table already exists */
-struct builtin_table *
+static struct builtin_table *
nft_table_builtin_find(struct nft_handle *h, const char *table)
{
int i;
@@ -619,7 +599,7 @@ nft_table_builtin_find(struct nft_handle *h, const char *table)
}
/* find if built-in chain already exists */
-struct builtin_chain *
+static struct builtin_chain *
nft_chain_builtin_find(struct builtin_table *t, const char *chain)
{
int i;
@@ -635,30 +615,28 @@ nft_chain_builtin_find(struct builtin_table *t, const char *chain)
return found ? &t->chains[i] : NULL;
}
-static void
-__nft_chain_builtin_init(struct nft_handle *h,
- struct builtin_table *table, const char *chain,
- int policy)
+static void nft_chain_builtin_init(struct nft_handle *h,
+ struct builtin_table *table)
{
- int i, default_policy;
+ int i;
+ struct nft_chain_list *list = nft_chain_dump(h);
+ struct nft_chain *c;
- /* Initialize all built-in chains. Exception, for e one received as
- * parameter, set the default policy as requested.
- */
+ /* Initialize built-in chains if they don't exist yet */
for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) {
- if (chain && strcmp(table->chains[i].name, chain) == 0)
- default_policy = policy;
- else
- default_policy = NF_ACCEPT;
- nft_chain_builtin_add(h, table, &table->chains[i],
- default_policy);
+ c = nft_chain_list_find(list, table->name,
+ table->chains[i].name);
+ if (c != NULL)
+ continue;
+
+ nft_chain_builtin_add(h, table, &table->chains[i]);
}
+
+ nft_chain_list_free(list);
}
-int
-nft_chain_builtin_init(struct nft_handle *h, const char *table,
- const char *chain, int policy)
+static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
{
int ret = 0;
struct builtin_table *t;
@@ -673,7 +651,7 @@ nft_chain_builtin_init(struct nft_handle *h, const char *table,
if (errno == EEXIST)
goto out;
}
- __nft_chain_builtin_init(h, t, chain, policy);
+ nft_chain_builtin_init(h, t);
out:
return ret;
}
@@ -732,15 +710,12 @@ err:
int nft_init(struct nft_handle *h, struct builtin_table *t)
{
h->nl = mnl_socket_open(NETLINK_NETFILTER);
- if (h->nl == NULL) {
- perror("mnl_socket_open");
+ if (h->nl == NULL)
return -1;
- }
- if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
- perror("mnl_socket_bind");
+ if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0)
return -1;
- }
+
h->portid = mnl_socket_get_portid(h->nl);
h->tables = t;
@@ -1019,7 +994,7 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
- nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
+ nft_xt_builtin_init(h, table);
nft_fn = nft_rule_append;
@@ -1074,15 +1049,11 @@ static int nft_chain_list_cb(const struct nlmsghdr *nlh, void *data)
struct nft_chain_list *list = data;
c = nft_chain_alloc();
- if (c == NULL) {
- perror("OOM");
+ if (c == NULL)
goto err;
- }
- if (nft_chain_nlmsg_parse(nlh, c) < 0) {
- perror("nft_rule_nlmsg_parse");
+ if (nft_chain_nlmsg_parse(nlh, c) < 0)
goto out;
- }
nft_chain_list_add_tail(c, list);
@@ -1180,15 +1151,11 @@ static int nft_rule_list_cb(const struct nlmsghdr *nlh, void *data)
struct nft_rule_list *list = data;
r = nft_rule_alloc();
- if (r == NULL) {
- perror("OOM");
+ if (r == NULL)
goto err;
- }
- if (nft_rule_nlmsg_parse(nlh, r) < 0) {
- perror("nft_rule_nlmsg_parse");
+ if (nft_rule_nlmsg_parse(nlh, r) < 0)
goto out;
- }
nft_rule_list_add_tail(r, list);
@@ -1328,14 +1295,14 @@ err:
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
{
- char buf[MNL_SOCKET_BUFFER_SIZE];
- struct nlmsghdr *nlh;
struct nft_chain *c;
int ret;
+ nft_fn = nft_chain_user_add;
+
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
- nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
+ nft_xt_builtin_init(h, table);
c = nft_chain_alloc();
if (c == NULL)
@@ -1344,12 +1311,19 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
- NLM_F_ACK|NLM_F_EXCL, h->seq);
- nft_chain_nlmsg_build_payload(nlh, c);
- nft_chain_free(c);
+ if (h->batch_support) {
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
+ } else {
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
- ret = mnl_talk(h, nlh, NULL, NULL);
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
+ h->family,
+ NLM_F_ACK|NLM_F_EXCL, h->seq);
+ nft_chain_nlmsg_build_payload(nlh, c);
+ nft_chain_free(c);
+ ret = mnl_talk(h, nlh, NULL, NULL);
+ }
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
@@ -1400,7 +1374,11 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl
if (chain != NULL && strcmp(chain, chain_name) != 0)
goto next;
- ret = __nft_chain_del(h, c);
+ if (h->batch_support)
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
+ else
+ ret = __nft_chain_del(h, c);
+
if (ret < 0)
break;
@@ -1414,11 +1392,14 @@ next:
nft_chain_list_iter_destroy(iter);
err:
- nft_chain_list_free(list);
+ if (!h->batch_support)
+ nft_chain_list_free(list);
/* chain not found */
- if (ret < 0 && deleted_ctr == 0)
+ if (deleted_ctr == 0) {
+ ret = -1;
errno = ENOENT;
+ }
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
@@ -1472,15 +1453,13 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
int nft_chain_user_rename(struct nft_handle *h,const char *chain,
const char *table, const char *newname)
{
- char buf[MNL_SOCKET_BUFFER_SIZE];
- struct nlmsghdr *nlh;
struct nft_chain *c;
uint64_t handle;
int ret;
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
- nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
+ nft_xt_builtin_init(h, table);
/* Find the old chain to be renamed */
c = nft_chain_find(h, table, chain);
@@ -1499,12 +1478,19 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname);
nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
- NLM_F_ACK, h->seq);
- nft_chain_nlmsg_build_payload(nlh, c);
- nft_chain_free(c);
+ if (h->batch_support) {
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
+ } else {
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
- ret = mnl_talk(h, nlh, NULL, NULL);
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
+ h->family, NLM_F_ACK, h->seq);
+ nft_chain_nlmsg_build_payload(nlh, c);
+ nft_chain_free(c);
+
+ ret = mnl_talk(h, nlh, NULL, NULL);
+ }
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
@@ -1516,15 +1502,11 @@ static int nft_table_list_cb(const struct nlmsghdr *nlh, void *data)
struct nft_table_list *list = data;
t = nft_table_alloc();
- if (t == NULL) {
- perror("OOM");
+ if (t == NULL)
goto err;
- }
- if (nft_table_nlmsg_parse(nlh, t) < 0) {
- perror("nft_rule_nlmsg_parse");
+ if (nft_table_nlmsg_parse(nlh, t) < 0)
goto out;
- }
nft_table_list_add_tail(t, list);
@@ -1804,7 +1786,7 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
- nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
+ nft_xt_builtin_init(h, table);
nft_fn = nft_rule_insert;
@@ -1890,50 +1872,6 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
return ret;
}
-static void
-print_header(unsigned int format, const char *chain, const char *pol,
- const struct xt_counters *counters, bool basechain, uint32_t refs)
-{
- printf("Chain %s", chain);
- if (basechain) {
- printf(" (policy %s", pol);
- if (!(format & FMT_NOCOUNTS)) {
- fputc(' ', stdout);
- xtables_print_num(counters->pcnt, (format|FMT_NOTABLE));
- fputs("packets, ", stdout);
- xtables_print_num(counters->bcnt, (format|FMT_NOTABLE));
- fputs("bytes", stdout);
- }
- printf(")\n");
- } else {
- printf(" (%u references)\n", refs);
- }
-
- if (format & FMT_LINENUMBERS)
- printf(FMT("%-4s ", "%s "), "num");
- if (!(format & FMT_NOCOUNTS)) {
- if (format & FMT_KILOMEGAGIGA) {
- printf(FMT("%5s ","%s "), "pkts");
- printf(FMT("%5s ","%s "), "bytes");
- } else {
- printf(FMT("%8s ","%s "), "pkts");
- printf(FMT("%10s ","%s "), "bytes");
- }
- }
- if (!(format & FMT_NOTARGET))
- printf(FMT("%-9s ","%s "), "target");
- fputs(" prot ", stdout);
- if (format & FMT_OPTIONS)
- fputs("opt", stdout);
- if (format & FMT_VIA) {
- printf(FMT(" %-6s ","%s "), "in");
- printf(FMT("%-6s ","%s "), "out");
- }
- printf(FMT(" %-19s ","%s "), "source");
- printf(FMT(" %-19s "," %s "), "destination");
- printf("\n");
-}
-
static int
__nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
int rulenum, unsigned int format,
@@ -2001,8 +1939,14 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
bool found = false;
/* If built-in chains don't exist for this table, create them */
- if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
- nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
+ if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) {
+ nft_xt_builtin_init(h, table);
+ /* Force table and chain creation, otherwise first iptables -L
+ * lists no table/chains.
+ */
+ if (!list_empty(&h->obj_list))
+ nft_commit(h);
+ }
ops = nft_family_ops_lookup(h->family);
@@ -2045,8 +1989,8 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (found)
printf("\n");
- print_header(format, chain_name, policy_name[policy],
- &ctrs, basechain, refs);
+ ops->print_header(format, chain_name, policy_name[policy],
+ &ctrs, basechain, refs);
__nft_rule_list(h, chain_name, table,
rulenum, format, ops->print_firewall);
@@ -2266,6 +2210,15 @@ static int nft_action(struct nft_handle *h, int action)
NLM_F_CREATE, seq++,
n->chain);
break;
+ case NFT_COMPAT_CHAIN_USER_ADD:
+ nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
+ NLM_F_EXCL, seq++,
+ n->chain);
+ break;
+ case NFT_COMPAT_CHAIN_USER_DEL:
+ nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
+ 0, seq++, n->chain);
+ break;
case NFT_COMPAT_CHAIN_UPDATE:
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
h->restore ?
@@ -2314,8 +2267,6 @@ static int nft_action(struct nft_handle *h, int action)
h->batch = mnl_nft_batch_page_add(h->batch);
ret = mnl_nft_batch_talk(h);
- if (ret < 0)
- perror("mnl_nft_batch_talk:");
mnl_nlmsg_batch_reset(h->batch);
@@ -2364,33 +2315,24 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt)
name, rev, type);
nl = mnl_socket_open(NETLINK_NETFILTER);
- if (nl == NULL) {
- perror("mnl_socket_open");
+ if (nl == NULL)
return 0;
- }
- if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
- perror("mnl_socket_bind");
+ if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
goto err;
- }
+
portid = mnl_socket_get_portid(nl);
- if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
- perror("mnl_socket_send");
+ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
goto err;
- }
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
- if (ret == -1) {
- perror("mnl_socket_recvfrom");
+ if (ret == -1)
goto err;
- }
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
- if (ret == -1) {
- perror("mnl_cb_run");
+ if (ret == -1)
goto err;
- }
err:
mnl_socket_close(nl);
@@ -2410,10 +2352,12 @@ const char *nft_strerror(int err)
{
{ nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
{ nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
+ { nft_chain_user_del, EBUSY, "Directory not empty" },
{ nft_chain_user_del, EMLINK,
"Can't delete chain with references left" },
{ nft_chain_user_add, EEXIST, "Chain already exists" },
{ nft_rule_add, E2BIG, "Index of insertion too big" },
+ { nft_rule_check, ENOENT, "Bad rule (does a matching rule exist in that chain?)" },
{ nft_rule_replace, E2BIG, "Index of replacement too big" },
{ nft_rule_delete_num, E2BIG, "Index of deletion too big" },
/* { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
@@ -2567,8 +2511,6 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
struct nft_chain_list *list;
struct nft_chain_list_iter *iter;
struct nft_chain *c;
- struct nlmsghdr *nlh;
- char buf[MNL_SOCKET_BUFFER_SIZE];
int ret = 0;
list = nft_chain_list_get(h);
@@ -2597,14 +2539,18 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
nft_chain_attr_unset(c, NFT_CHAIN_ATTR_HANDLE);
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
- h->family, NLM_F_ACK, h->seq);
-
- nft_chain_nlmsg_build_payload(nlh, c);
-
- ret = mnl_talk(h, nlh, NULL, NULL);
- if (ret < 0)
- perror("mnl_talk:nft_chain_zero_counters");
+ if (h->batch_support) {
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
+ } else {
+ struct nlmsghdr *nlh;
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
+ h->family, NLM_F_ACK,
+ h->seq);
+ nft_chain_nlmsg_build_payload(nlh, c);
+ ret = mnl_talk(h, nlh, NULL, NULL);
+ }
if (chain != NULL)
break;
@@ -2612,11 +2558,12 @@ next:
c = nft_chain_list_iter_next(iter);
}
+ if (!h->batch_support)
+ nft_chain_list_free(list);
+
nft_chain_list_iter_destroy(iter);
err:
- nft_chain_list_free(list);
-
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
}