conntrack event notifiers for nf_conntrack
Subsystems (2)
PATCH 1/1 conntrack event notifiers for nf_conntrack
Hi,
I've ported the conntrack event notification API[1] to nf_conntrack. Anyway, I'll try to keep a updated version for ip_conntrack (which won't be ever merged into the mainline) since it's useful for Krisztian Kovacs' ct_sync works.
Expect more patches that port my lastest posted stuff to nf_conntrack soon.
References:
[1] https://lists.netfilter.org/pipermail/netfilter-devel/2004-November/017453.html
--
Pablo
include/linux/netfilter.h +1 -1
@@ -21,7 +21,7 @@#define NF_MAX_VERDICT NF_REPEAT/* Generic cache responses from hook functions. -<= 0x2000 is used for protocol-flags. */ +<= 0x2000 is reserved for conntrack event cache. */ #define NFC_UNKNOWN 0x4000#define NFC_ALTERED 0x8000
include/linux/netfilter/nf_conntrack_core.h +6 -4
@@ -55,11 +55,13 @@/* Confirm a connection: returns NF_DROP if packet must be dropped. */ static inline int nf_conntrack_confirm (struct sk_buff *skb) { -if (skb->nfct - && !is_confirmed ((struct nf_conn *)skb->nfct)) -return __nf_conntrack_confirm (skb); +int ret =NF_ACCEPT ; -return NF_ACCEPT ; +if (skb->nfct && !is_confirmed ((struct nf_conn *)skb->nfct)) + ret =__nf_conntrack_confirm (skb); +nf_conntrack_deliver_cached_events (skb); + +return ret; }extern void __nf_conntrack_attach (struct sk_buff *nskb,struct sk_buff *skb);
include/linux/netfilter/nf_conntrack.h +109 -1
134 lines not on this page · raw message
include/linux/netfilter/nf_conntrack_helper.h +1 -1
@@ -33,7 +33,7 @@/* Function to call when data passes; return verdict, or -1 to invalidate. */ -int (*help)(const struct sk_buff *skb, +int (*help)(struct sk_buff *skb,unsigned int dataoff,struct nf_conn *ct,enum nf_conntrack_info conntrackinfo);
include/linux/netfilter/nf_conntrack_protocol.h +1 -1
@@ -48,7 +48,7 @@/* Returns verdict for packet, or -1 for invalid. */ int (*packet)(struct nf_conn *conntrack, - const struct sk_buff *skb, + struct sk_buff *skb, unsigned int dataoff, enum nf_conntrack_info ctinfo, int pf,
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +1 -0
@@ -113,6 +113,7 @@ }else {atomic_inc (&ct->proto.icmp.count);nf_ct_refresh_acct (ct, ctinfo, skb, nf_ct_icmpv6_timeout); +nf_conntrack_event_cache (NFCT_PROTOINFO_VOLATILE , skb); }return NF_ACCEPT ;
net/netfilter/Kconfig +10 -0
@@ -65,4 +65,26 @@ To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_EVENTS + bool "Connection tracking events" + depends on NF_CONNTRACK + help + If this option is enabled, the connection tracking code will + provide a notifier chain that can be used by other kernel code + to get notified about changes in the connection tracking state. + + IF unsure, say `N'. + endmenu
net/netfilter/nf_conntrack_core.c +26 -4
@@ -41,6 +41,7 @@#include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/socket.h> +#include <linux/notifier.h> /* This rwlock protects the main hash table, protocol/helper/expected registrations, conntrack timers*/
@@ -80,6 +81,10 @@struct nf_conn nf_conntrack_untracked;unsigned int nf_ct_log_invalid; +#ifdef CONFIG_NF_CONNTRACK_EVENTS +struct notifier_block *nf_conntrack_chain; +#endif /* CONFIG_NF_CONNTRACK_EVENTS */ + DEFINE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat);EXPORT_PER_CPU_SYMBOL (nf_conntrack_stat);
@@ -505,6 +510,8 @@NF_CT_ASSERT (atomic_read (&nfct->use) ==0 );NF_CT_ASSERT (!timer_pending (&ct->timeout)); +set_bit (NF_S_DESTROYED_BIT , &ct->status); +/* To make sure we don't get any weird locking issues here: * destroy_conntrack() MUST NOT be called with a write lock * to nf_conntrack_lock!!! -HW */
@@ -550,7 +557,7 @@ {struct nf_conn *ct = (void *)ul_conntrack; - +nf_conntrack_event (NFCT_DESTROY , ct);WRITE_LOCK (&nf_conntrack_lock);/* Inside lock so preempt is disabled on module removal path. * Otherwise we can get spurious warnings. */
@@ -664,6 +671,15 @@set_bit (NF_S_CONFIRMED_BIT , &ct->status);WRITE_UNLOCK (&nf_conntrack_lock);NF_CT_STAT_INC (insert); +if (ct->helper) +nf_conntrack_event_cache (NFCT_HELPER , skb); +#ifdef CONFIG_NF_NAT_NEEDED +/* I Know, NAT isn't implemented yet */ +if (ct->nat.info.initialized) +nf_conntrack_event_cache (NFCT_NATINFO , skb); +#endif +nf_conntrack_event_cache (master_ct (ct) ? +NFCT_RELATED :NFCT_NEW , skb);return NF_ACCEPT ; }
@@ -960,6 +976,8 @@return ret; } +nf_conntrack_event_cache_init (*pskb); + proto =nf_ct_find_proto ((u_int16_t )pf, protonum);DEBUGP ("protonum = %u\n" , protonum);
@@ -1012,8 +1030,10 @@return NF_ACCEPT ; } } -if (set_reply) -set_bit (NF_S_SEEN_REPLY_BIT , &ct->status); +if (set_reply && !test_bit (NF_S_SEEN_REPLY_BIT , &ct->status)) { +set_bit (NF_S_SEEN_REPLY_BIT , &ct->status); +nf_conntrack_event_cache (NFCT_STATUS , *pskb); + }return ret; }
@@ -1321,6 +1341,7 @@if (i->ctrack->helper == me) {/* Get rid of any expected. */ remove_expectations (i->ctrack,0 ); +nf_conntrack_event (NFCT_HELPER , i->ctrack);/* And *then* set helper to NULL */ i->ctrack->helper =NULL ; }
@@ -1363,7 +1384,7 @@/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */ void nf_ct_refresh_acct (struct nf_conn *ct,enum nf_conntrack_info ctinfo, -const struct sk_buff *skb, +struct sk_buff *skb,unsigned long extra_jiffies) {NF_CT_ASSERT (ct->timeout.data == (unsigned long )ct);
@@ -1378,6 +1399,7 @@if (del_timer (&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies;add_timer (&ct->timeout); +nf_conntrack_event_cache (NFCT_REFRESH , skb); }ct_add_counters (ct, ctinfo, skb);WRITE_UNLOCK (&nf_conntrack_lock);
net/netfilter/nf_conntrack_ftp.c +2 -1
@@ -385,7 +385,7 @@return 1 ; } -static int help (const struct sk_buff *skb, +static int help (struct sk_buff *skb,unsigned int protoff,struct nf_conn *ct,enum nf_conntrack_info ctinfo)
@@ -441,6 +441,7 @@ ct_ftp_info->seq_aft_nl[dir] =ntohl (th->seq) + datalen; ct_ftp_info->seq_aft_nl_set[dir] =1 ; +nf_conntrack_event_cache (NFCT_HELPINFO_VOLATILE , skb); } }
net/netfilter/nf_conntrack_proto_generic.c +1 -1
@@ -54,7 +54,7 @@/* Returns verdict for packet, or -1 for invalid. */ static int packet(struct nf_conn *conntrack, - const struct sk_buff *skb, + struct sk_buff *skb, unsigned int dataoff, enum nf_conntrack_info ctinfo, int pf,
net/netfilter/nf_conntrack_proto_sctp.c +3 -1
@@ -316,7 +316,7 @@/* Returns verdict for packet, or -1 for invalid. */ static int sctp_packet(struct nf_conn *conntrack, - const struct sk_buff *skb, + struct sk_buff *skb, unsigned int dataoff, enum nf_conntrack_info ctinfo, int pf,
@@ -412,6 +412,8 @@ conntrack->proto.sctp.vtag[NF_CT_DIR_ORIGINAL ] = ih->init_tag; } +if (oldsctpstate != newconntrack) +nf_conntrack_event_cache (NFCT_PROTOINFO , skb); conntrack->proto.sctp.state = newconntrack;WRITE_UNLOCK (&sctp_lock); }
net/netfilter/nf_conntrack_proto_tcp.c +5 -1
@@ -875,7 +875,7 @@/* Returns verdict for packet, or -1 for invalid. */ static int tcp_packet(struct nf_conn *conntrack, - const struct sk_buff *skb, + struct sk_buff *skb, unsigned int dataoff, enum nf_conntrack_info ctinfo, int pf,
@@ -995,6 +995,10 @@ ? nf_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];WRITE_UNLOCK (&tcp_lock); +nf_conntrack_event_cache (NFCT_PROTOINFO_VOLATILE , skb); +if (new_state != old_state) +nf_conntrack_event_cache (NFCT_PROTOINFO , skb); +if (!test_bit (NF_S_SEEN_REPLY_BIT , &conntrack->status)) {/* If only reply is a RST, we can consider ourselves not to have an established connection: this is a fairly common
net/netfilter/nf_conntrack_proto_udp.c +5 -1
@@ -71,7 +71,7 @@/* Returns verdict for packet, and may modify conntracktype */ static int udp_packet(struct nf_conn *conntrack, - const struct sk_buff *skb, + struct sk_buff *skb, unsigned int dataoff, enum nf_conntrack_info ctinfo, int pf,
@@ -84,6 +84,10 @@ nf_ct_udp_timeout_stream);/* Also, more likely to be important, and not a probe */ set_bit (NF_S_ASSURED_BIT , &conntrack->status); +if (!test_bit (NF_S_ASSURED_BIT , &conntrack->status)) { +set_bit (NF_S_ASSURED_BIT , &conntrack->status); +nf_conntrack_event_cache (NFCT_STATUS , skb); + } }else nf_ct_refresh_acct (conntrack, ctinfo, skb, nf_ct_udp_timeout);
net/netfilter/nf_conntrack_standalone.c +5 -0
@@ -787,6 +787,11 @@ { } +#ifdef CONFIG_NF_CONNTRACK_EVENTS +EXPORT_SYMBOL (nf_conntrack_chain); +EXPORT_SYMBOL (nf_conntrack_register_notifier); +EXPORT_SYMBOL (nf_conntrack_unregister_notifier); +#endif EXPORT_SYMBOL (nf_conntrack_l3proto_register);EXPORT_SYMBOL (nf_conntrack_l3proto_unregister);EXPORT_SYMBOL (nf_conntrack_protocol_register);