Decode direction/id/state/status information. This will be used by 'nftables monitor trace' to print a packets conntrack state. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- include/libnftnl/trace.h | 4 ++ include/linux/netfilter/nf_tables.h | 2 + src/trace.c | 78 +++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/include/libnftnl/trace.h b/include/libnftnl/trace.h index 18ab0c3baef7..5d66b50b2d31 100644 --- a/include/libnftnl/trace.h +++ b/include/libnftnl/trace.h @@ -28,6 +28,10 @@ enum nftnl_trace_attr { NFTNL_TRACE_VERDICT, NFTNL_TRACE_NFPROTO, NFTNL_TRACE_POLICY, + NFTNL_TRACE_CT_DIRECTION, + NFTNL_TRACE_CT_ID, + NFTNL_TRACE_CT_STATE, + NFTNL_TRACE_CT_STATUS, __NFTNL_TRACE_MAX, }; #define NFTNL_TRACE_MAX (__NFTNL_TRACE_MAX - 1) diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 49c944e78463..5a00ec9a4879 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -1837,6 +1837,7 @@ enum nft_xfrm_keys { * @NFTA_TRACE_MARK: nfmark (NLA_U32) * @NFTA_TRACE_NFPROTO: nf protocol processed (NLA_U32) * @NFTA_TRACE_POLICY: policy that decided fate of packet (NLA_U32) + * @NFTA_TRACE_CT: connection tracking information (NLA_NESTED: nft_ct_keys) */ enum nft_trace_attributes { NFTA_TRACE_UNSPEC, @@ -1857,6 +1858,7 @@ enum nft_trace_attributes { NFTA_TRACE_NFPROTO, NFTA_TRACE_POLICY, NFTA_TRACE_PAD, + NFTA_TRACE_CT, __NFTA_TRACE_MAX }; #define NFTA_TRACE_MAX (__NFTA_TRACE_MAX - 1) diff --git a/src/trace.c b/src/trace.c index f7eb45ed6704..a218289ceb25 100644 --- a/src/trace.c +++ b/src/trace.c @@ -44,6 +44,12 @@ struct nftnl_trace { uint32_t policy; uint16_t iiftype; uint16_t oiftype; + struct { + uint16_t dir; + uint32_t id; + uint32_t state; + uint32_t status; + } ct; uint32_t flags; }; @@ -85,6 +91,7 @@ static int nftnl_trace_parse_attr_cb(const struct nlattr *attr, void *data) case __NFTA_TRACE_MAX: break; case NFTA_TRACE_VERDICT: + case NFTA_TRACE_CT: if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) abi_breakage(); break; @@ -190,6 +197,18 @@ const void *nftnl_trace_get_data(const struct nftnl_trace *trace, case NFTNL_TRACE_POLICY: *data_len = sizeof(uint32_t); return &trace->policy; + case NFTNL_TRACE_CT_DIRECTION: + *data_len = sizeof(uint16_t); + return &trace->ct.dir; + case NFTNL_TRACE_CT_ID: + *data_len = sizeof(uint32_t); + return &trace->ct.id; + case NFTNL_TRACE_CT_STATE: + *data_len = sizeof(uint32_t); + return &trace->ct.state; + case NFTNL_TRACE_CT_STATUS: + *data_len = sizeof(uint32_t); + return &trace->ct.status; case __NFTNL_TRACE_MAX: break; } @@ -321,6 +340,61 @@ static int nftnl_trace_parse_verdict(const struct nlattr *attr, return 0; } +static int nftnl_trace_parse_ct_cb(const struct nlattr *attr, void *data) +{ + int type = mnl_attr_get_type(attr); + const struct nlattr **tb = data; + + switch (type) { + case NFT_CT_DIRECTION: + if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) + abi_breakage(); + tb[type] = attr; + break; + case NFT_CT_STATE: + case NFT_CT_STATUS: + case NFT_CT_ID: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + tb[type] = attr; + break; + } + + return MNL_CB_OK; +} + +static int nftnl_trace_parse_ct(const struct nlattr *attr, + struct nftnl_trace *t) +{ + struct nlattr *tb[NFT_CT_MAX+1] = {}; + + if (mnl_attr_parse_nested(attr, nftnl_trace_parse_ct_cb, tb) < 0) + return -1; + + if (tb[NFT_CT_DIRECTION]) { + t->ct.dir = mnl_attr_get_u8(tb[NFT_CT_DIRECTION]); + t->flags |= (1 << NFTNL_TRACE_CT_DIRECTION); + } + + if (tb[NFT_CT_ID]) { + /* NFT_CT_ID is expected to be in big endian */ + t->ct.id = mnl_attr_get_u32(tb[NFT_CT_ID]); + t->flags |= (1 << NFTNL_TRACE_CT_ID); + } + + if (tb[NFT_CT_STATE]) { + t->ct.state = ntohl(mnl_attr_get_u32(tb[NFT_CT_STATE])); + t->flags |= (1 << NFTNL_TRACE_CT_STATE); + } + + if (tb[NFT_CT_STATUS]) { + t->ct.status = ntohl(mnl_attr_get_u32(tb[NFT_CT_STATUS])); + t->flags |= (1 << NFTNL_TRACE_CT_STATUS); + } + + return 0; +} + EXPORT_SYMBOL(nftnl_trace_nlmsg_parse); int nftnl_trace_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_trace *t) { @@ -419,5 +493,9 @@ int nftnl_trace_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_trace *t) t->flags |= (1 << NFTNL_TRACE_MARK); } + if (tb[NFTA_TRACE_CT] && + nftnl_trace_parse_ct(tb[NFTA_TRACE_CT], t) < 0) + return -1; + return 0; } -- 2.49.0