diff options
author | Romain Bellan <romain.bellan@wifirst.fr> | 2020-01-29 10:47:18 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2023-09-14 13:15:44 +0200 |
commit | c2136262802f31cb19267dacf0c0fdecdea4ae16 (patch) | |
tree | d1eb985ab53162c084177c9d8199d620b2160a59 /src/conntrack | |
parent | 246dc83f653fbeddc4972391b6a542ffe24ce6a8 (diff) |
Adding NFCT_FILTER_DUMP_TUPLE in filter_dump_attr, using kernel CTA_FILTER API
Following kernel side new conntrack filtering API, this patch implements
userspace part. This patch:
* Update headers to get new flag value from kernel
* Use a conntrack struct to configure filtering
* Set netlink flags according to values set in conntrack struct
Signed-off-by: Romain Bellan <romain.bellan@wifirst.fr>
Signed-off-by: Florent Fourcot <florent.fourcot@wifirst.fr>
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/conntrack')
-rw-r--r-- | src/conntrack/api.c | 2 | ||||
-rw-r--r-- | src/conntrack/build_mnl.c | 72 | ||||
-rw-r--r-- | src/conntrack/filter_dump.c | 14 |
3 files changed, 84 insertions, 4 deletions
diff --git a/src/conntrack/api.c b/src/conntrack/api.c index 7f72d07..d27bad2 100644 --- a/src/conntrack/api.c +++ b/src/conntrack/api.c @@ -850,7 +850,7 @@ __build_query_ct(struct nfnl_subsys_handle *ssh, case NFCT_Q_DUMP_FILTER: nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC, NFNETLINK_V0); - __build_filter_dump(req, size, data); + assert(__build_filter_dump(req, size, data) == 0); break; case NFCT_Q_DUMP_FILTER_RESET: nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP, diff --git a/src/conntrack/build_mnl.c b/src/conntrack/build_mnl.c index af5d0e7..eb9fcbf 100644 --- a/src/conntrack/build_mnl.c +++ b/src/conntrack/build_mnl.c @@ -595,9 +595,53 @@ nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct) return 0; } +static uint32_t get_flags_from_ct(const struct nf_conntrack *ct, int family) +{ + uint32_t tuple_flags = 0; + + if (family == AF_INET) { + if (test_bit(ATTR_ORIG_IPV4_SRC, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_IP_SRC; + if (test_bit(ATTR_ORIG_IPV4_DST, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_IP_DST; + + if (test_bit(ATTR_ICMP_TYPE, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMP_TYPE; + if (test_bit(ATTR_ICMP_CODE, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMP_CODE; + if (test_bit(ATTR_ICMP_ID, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMP_ID; + } else if (family == AF_INET6) { + if (test_bit(ATTR_ORIG_IPV6_SRC, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_IP_SRC; + if (test_bit(ATTR_ORIG_IPV6_DST, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_IP_DST; + + if (test_bit(ATTR_ICMP_TYPE, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_TYPE; + if (test_bit(ATTR_ICMP_CODE, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_CODE; + if (test_bit(ATTR_ICMP_ID, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_ID; + } + + if (test_bit(ATTR_ORIG_ZONE, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_TUPLE_ZONE; + + if (test_bit(ATTR_ORIG_L4PROTO, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_NUM; + if (test_bit(ATTR_ORIG_PORT_SRC, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_SRC_PORT; + if (test_bit(ATTR_ORIG_PORT_DST, ct->head.set)) + tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_DST_PORT; + + return tuple_flags; +} + int nfct_nlmsg_build_filter(struct nlmsghdr *nlh, const struct nfct_filter_dump *filter_dump) { + bool l3num_changed = false; struct nfgenmsg *nfg; if (filter_dump->set & (1 << NFCT_FILTER_DUMP_MARK)) { @@ -607,12 +651,40 @@ int nfct_nlmsg_build_filter(struct nlmsghdr *nlh, if (filter_dump->set & (1 << NFCT_FILTER_DUMP_L3NUM)) { nfg = mnl_nlmsg_get_payload(nlh); nfg->nfgen_family = filter_dump->l3num; + l3num_changed = true; } if (filter_dump->set & (1 << NFCT_FILTER_DUMP_STATUS)) { mnl_attr_put_u32(nlh, CTA_STATUS, htonl(filter_dump->status.val)); mnl_attr_put_u32(nlh, CTA_STATUS_MASK, htonl(filter_dump->status.mask)); } + if (filter_dump->set & (1 << NFCT_FILTER_DUMP_TUPLE)) { + const struct nf_conntrack *ct = &filter_dump->ct; + struct nlattr *nest; + int ret; + + ret = nfct_nlmsg_build(nlh, ct); + if (ret == -1) + return -1; + nest = mnl_attr_nest_start(nlh, CTA_FILTER); + if (nest == NULL) + return -1; + + nfg = mnl_nlmsg_get_payload(nlh); + + if (test_bit(ATTR_ORIG_L3PROTO, ct->head.set)) { + if (l3num_changed && filter_dump->l3num != ct->head.orig.l3protonum) + return -1; + + nfg->nfgen_family = ct->head.orig.l3protonum; + } + + mnl_attr_put_u32(nlh, CTA_FILTER_ORIG_FLAGS, + get_flags_from_ct(&filter_dump->ct, + nfg->nfgen_family)); + mnl_attr_put_u32(nlh, CTA_FILTER_REPLY_FLAGS, 0); + mnl_attr_nest_end(nlh, nest); + } return 0; } diff --git a/src/conntrack/filter_dump.c b/src/conntrack/filter_dump.c index 9bf9296..5723a44 100644 --- a/src/conntrack/filter_dump.c +++ b/src/conntrack/filter_dump.c @@ -37,14 +37,22 @@ set_filter_dump_attr_family(struct nfct_filter_dump *filter_dump, filter_dump->l3num = *((uint8_t *)value); } +static void +set_filter_dump_attr_tuple(struct nfct_filter_dump *filter_dump, + const void *value) +{ + memcpy(&filter_dump->ct, value, sizeof(struct nf_conntrack)); +} + const set_filter_dump_attr set_filter_dump_attr_array[NFCT_FILTER_DUMP_MAX] = { [NFCT_FILTER_DUMP_MARK] = set_filter_dump_attr_mark, [NFCT_FILTER_DUMP_L3NUM] = set_filter_dump_attr_family, [NFCT_FILTER_DUMP_STATUS] = set_filter_dump_attr_status, + [NFCT_FILTER_DUMP_TUPLE] = set_filter_dump_attr_tuple, }; -void __build_filter_dump(struct nfnlhdr *req, size_t size, - const struct nfct_filter_dump *filter_dump) +int __build_filter_dump(struct nfnlhdr *req, size_t size, + const struct nfct_filter_dump *filter_dump) { - nfct_nlmsg_build_filter(&req->nlh, filter_dump); + return nfct_nlmsg_build_filter(&req->nlh, filter_dump); } |