Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nft_ct: allow to set ctnetlink event types of a connection

By default the kernel emits all ctnetlink events for a connection.
This allows to select the types of events to generate.

This can be used to e.g. only send DESTROY events but no NEW/UPDATE ones
and will work even if sysctl net.netfilter.nf_conntrack_events is set to 0.

This was already possible via iptables' CT target, but the nft version has
the advantage that it can also be used with already-established conntracks.

The added nf_ct_is_template() check isn't a bug fix as we only support
mark and labels (and unlike ecache the conntrack core doesn't copy those).

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
694a0055 ab8bc7ed

+26 -1
+2
include/uapi/linux/netfilter/nf_tables.h
··· 901 901 * @NFT_CT_BYTES: conntrack bytes 902 902 * @NFT_CT_AVGPKT: conntrack average bytes per packet 903 903 * @NFT_CT_ZONE: conntrack zone 904 + * @NFT_CT_EVENTMASK: ctnetlink events to be generated for this conntrack 904 905 */ 905 906 enum nft_ct_keys { 906 907 NFT_CT_STATE, ··· 922 921 NFT_CT_BYTES, 923 922 NFT_CT_AVGPKT, 924 923 NFT_CT_ZONE, 924 + NFT_CT_EVENTMASK, 925 925 }; 926 926 927 927 /**
+24 -1
net/netfilter/nft_ct.c
··· 264 264 struct nf_conn *ct; 265 265 266 266 ct = nf_ct_get(skb, &ctinfo); 267 - if (ct == NULL) 267 + if (ct == NULL || nf_ct_is_template(ct)) 268 268 return; 269 269 270 270 switch (priv->key) { ··· 283 283 &regs->data[priv->sreg], 284 284 NF_CT_LABELS_MAX_SIZE / sizeof(u32)); 285 285 break; 286 + #endif 287 + #ifdef CONFIG_NF_CONNTRACK_EVENTS 288 + case NFT_CT_EVENTMASK: { 289 + struct nf_conntrack_ecache *e = nf_ct_ecache_find(ct); 290 + u32 ctmask = regs->data[priv->sreg]; 291 + 292 + if (e) { 293 + if (e->ctmask != ctmask) 294 + e->ctmask = ctmask; 295 + break; 296 + } 297 + 298 + if (ctmask && !nf_ct_is_confirmed(ct)) 299 + nf_ct_ecache_ext_add(ct, ctmask, 0, GFP_ATOMIC); 300 + break; 301 + } 286 302 #endif 287 303 default: 288 304 break; ··· 553 537 return -ENOMEM; 554 538 nft_ct_pcpu_template_refcnt++; 555 539 len = sizeof(u16); 540 + break; 541 + #endif 542 + #ifdef CONFIG_NF_CONNTRACK_EVENTS 543 + case NFT_CT_EVENTMASK: 544 + if (tb[NFTA_CT_DIRECTION]) 545 + return -EINVAL; 546 + len = sizeof(u32); 556 547 break; 557 548 #endif 558 549 default: