summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2016-12-13 23:51:33 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2016-12-14 00:07:34 +0100
commit8bd99f2fca7e8210771e0b3cb97ce7dbb3cb494d (patch)
tree2e3b3d70c6027c91015e13dac6d70f21858c131e
parentcd326af6d46b725c99fa8017a294c51876e486f7 (diff)
mnl: don't send empty set elements netlink message to kernel
The following command: # nft --debug=mnl add rule x y flow table xyz { ip saddr timeout 30s counter } breaks with EINVAL. The following netlink message is causing the problem: ... ---------------- ------------------ | 0000000044 | | message length | | 02572 | R--- | | type | flags | | 0000000004 | | sequence number| | 0000000000 | | port ID | ---------------- ------------------ | 02 00 00 00 | | extra header | |00008|--|00002| |len |flags| type| | 78 79 7a 00 | | data | x y z |00008|--|00004| |len |flags| type| | 00 00 00 01 | | data | |00006|--|00001| |len |flags| type| | 78 00 00 00 | | data | x ---------------- ------------------ ... This is incorrect since this describes no elements at all, so it is useless. Add upfront check before iterating over the list of set elements so the netlink message is not placed in the batch. This patch also adds a set so flow tables are minimally covered. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/mnl.c14
-rw-r--r--tests/py/ip/flowtable.t5
-rw-r--r--tests/py/ip/flowtable.t.payload7
3 files changed, 21 insertions, 5 deletions
diff --git a/src/mnl.c b/src/mnl.c
index 137ecf0d..d107015c 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -825,19 +825,21 @@ int mnl_nft_setelem_add(struct mnl_socket *nf_sock, struct nftnl_set *nls,
char buf[NFT_NLMSG_MAXSIZE];
struct nlmsghdr *nlh;
struct nftnl_set_elems_iter *iter;
- int ret, err;
+ int ret, err = 0;
iter = nftnl_set_elems_iter_create(nls);
if (iter == NULL)
memory_allocation_error();
- do {
+ while (nftnl_set_elems_iter_cur(iter)) {
nlh = nftnl_set_elem_nlmsg_build_hdr(buf, NFT_MSG_NEWSETELEM,
nftnl_set_get_u32(nls, NFTNL_SET_FAMILY),
NLM_F_CREATE | NLM_F_ACK | flags, seq);
ret = nftnl_set_elems_nlmsg_build_payload_iter(nlh, iter);
err = nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
- } while (ret > 0 && err >= 0);
+ if (ret <= 0 || err < 0)
+ break;
+ }
nftnl_set_elems_iter_destroy(iter);
@@ -879,13 +881,15 @@ static int mnl_nft_setelem_batch(struct nftnl_set *nls,
if (iter == NULL)
memory_allocation_error();
- do {
+ while (nftnl_set_elems_iter_cur(iter)) {
nlh = nftnl_set_elem_nlmsg_build_hdr(nftnl_batch_buffer(batch),
cmd, nftnl_set_get_u32(nls, NFTNL_SET_FAMILY),
NLM_F_CREATE | flags, seqnum);
ret = nftnl_set_elems_nlmsg_build_payload_iter(nlh, iter);
mnl_nft_batch_continue();
- } while (ret > 0);
+ if (ret <= 0)
+ break;
+ }
nftnl_set_elems_iter_destroy(iter);
diff --git a/tests/py/ip/flowtable.t b/tests/py/ip/flowtable.t
new file mode 100644
index 00000000..aea57c32
--- /dev/null
+++ b/tests/py/ip/flowtable.t
@@ -0,0 +1,5 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip;input
+
+flow table xyz { ip saddr timeout 30s counter packets 0 bytes 0};ok
diff --git a/tests/py/ip/flowtable.t.payload b/tests/py/ip/flowtable.t.payload
new file mode 100644
index 00000000..ffadfd25
--- /dev/null
+++ b/tests/py/ip/flowtable.t.payload
@@ -0,0 +1,7 @@
+# flow table xyz { ip saddr timeout 30s counter packets 0 bytes 0}
+xyz test-ip 31
+xyz test-ip 0
+ip test-ip input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ dynset update reg_key 1 set xyz timeout 30000ms expr [ counter pkts 0 bytes 0 ] ]
+