All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira <pablo@eurodev.net>
To: Patrick McHardy <kaber@trash.net>
Cc: Harald Welte <laforge@netfilter.org>,
	Netfilter Development Mailinglist
	<netfilter-devel@lists.netfilter.org>
Subject: Re: [PATCH 2.6] connection tracking events
Date: Sat, 16 Oct 2004 20:21:28 +0200	[thread overview]
Message-ID: <417166A8.3050809@eurodev.net> (raw)
In-Reply-To: <41713F11.9020301@eurodev.net>

[-- Attachment #1: Type: text/plain, Size: 531 bytes --]

Pablo Neira wrote:

> Attached the lastest version, I'm having a look at Harald's now to see 
> I think that I can take something.


Based on Harald's patch, I've:

- renamed PROTOINFO/PROTOINFO_SOFT for PROTOINFO_VOLATILE/PROTOINFO, I 
like it.
- added SCTP events
- added some comments to the source code

Harald's patch is similar to mine but I've also added a new event for 
confirmed expectations (IPCT_RELATED) and the pickup bit which is useful 
for tcp connections to make them pick up missing information.

regards,
Pablo

[-- Attachment #2: notifier.patch --]
[-- Type: text/x-patch, Size: 12691 bytes --]

===== include/linux/netfilter_ipv4/ip_conntrack.h 1.27 vs edited =====
--- 1.27/include/linux/netfilter_ipv4/ip_conntrack.h	Sun Oct 10 21:44:23 2004
+++ edited/include/linux/netfilter_ipv4/ip_conntrack.h	Sat Oct 16 18:42:42 2004
@@ -47,6 +47,14 @@
 	/* Connection is confirmed: originating packet has left box */
 	IPS_CONFIRMED_BIT = 3,
 	IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
+
+	/* Connection is destroyed (removed from lists), can not be unset. */
+	IPS_DESTROYED_BIT = 4,
+	IPS_DESTROYED = (1 << IPS_DESTROYED_BIT),
+
+	/* Some protocol information is missing, pick it up. */
+	IPS_PICKUP_BIT = 5,
+	IPS_PICKUP = (1 << IPS_PICKUP_BIT),
 };
 
 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
@@ -290,6 +298,11 @@
 	return test_bit(IPS_CONFIRMED_BIT, &ct->status);
 }
 
+static inline int is_destroyed(struct ip_conntrack *ct)
+{
+	return test_bit(IPS_DESTROYED_BIT, &ct->status);
+}
+
 extern unsigned int ip_conntrack_htable_size;
  
 struct ip_conntrack_stat
@@ -313,6 +326,68 @@
 
 #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
 
+enum ip_conntrack_events
+{
+	IPCT_NEW,
+	IPCT_RELATED,
+	IPCT_DESTROY,
+	IPCT_STATUS,
+	IPCT_REFRESH,
+ 	IPCT_PROTOINFO,
+	IPCT_PROTOINFO_VOLATILE,
+ 	IPCT_HELPINFO,
+	IPCT_NATINFO,
+};
+
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+#include <linux/notifier.h>
+ 
+extern struct notifier_block *ip_conntrack_chain;
+DECLARE_PER_CPU(unsigned long, ip_conntrack_event_cache);
+ 
+static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
+{
+	return notifier_chain_register(&ip_conntrack_chain, nb);
+}
+
+static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
+{
+	return notifier_chain_unregister(&ip_conntrack_chain, nb);
+}
+
+static inline void ip_conntrack_event_cache_init(void)
+{
+	__get_cpu_var(ip_conntrack_event_cache) = 0UL;
+}
+
+static inline void ip_conntrack_cache_event(enum ip_conntrack_events event)
+{ 
+	__get_cpu_var(ip_conntrack_event_cache) |= 1 << event;
+}
+
+static inline void ip_conntrack_deliver_cached_events(struct ip_conntrack *ct)
+{
+	unsigned long events = __get_cpu_var(ip_conntrack_event_cache);
+ 
+	if (is_confirmed(ct) && !is_destroyed(ct) && events)
+		notifier_call_chain(&ip_conntrack_chain, events, ct);
+}
+ 
+static inline void ip_conntrack_event(enum ip_conntrack_events event,
+                                      struct ip_conntrack *ct)
+{
+	if (is_confirmed(ct) && !is_destroyed(ct))
+		notifier_call_chain(&ip_conntrack_chain, 1 << event, ct);
+}
+#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+static inline int ip_conntrack_register_notifier(void *nb) { return 0; }
+static inline int ip_conntrack_unregister_notifier(void *nb) { return 0; }
+static inline void ip_conntrack_event_cache_init(void) {}
+static inline void ip_conntrack_cache_event(enum ip_conntrack_events event) {}
+static inline void ip_conntrack_deliver_cached_events(struct ip_conntrack *ct) {}
+static inline void ip_conntrack_event(enum ip_conntrack_events event,
+                                      struct ip_conntrack *ct) {}
+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
 /* eg. PROVIDES_CONNTRACK(ftp); */
 #define PROVIDES_CONNTRACK(name)                        \
         int needs_ip_conntrack_##name;                  \
===== net/ipv4/netfilter/Kconfig 1.32 vs edited =====
--- 1.32/net/ipv4/netfilter/Kconfig	Sat Oct 16 17:53:47 2004
+++ edited/net/ipv4/netfilter/Kconfig	Sat Oct 16 18:56:12 2004
@@ -677,5 +677,15 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_CONNTRACK_EVENTS
+	bool "Connection tracking events"
+	depends on IP_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/ipv4/netfilter/ip_conntrack_proto_icmp.c 1.16 vs edited =====
--- 1.16/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	Sun Oct 10 21:44:20 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	Sat Oct 16 18:43:07 2004
@@ -102,6 +102,7 @@
 			ct->timeout.function((unsigned long)ct);
 	} else {
 		atomic_inc(&ct->proto.icmp.count);
+		ip_conntrack_cache_event(IPCT_PROTOINFO_VOLATILE);
 		ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
 	}
 
===== net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1.8 vs edited =====
--- 1.8/net/ipv4/netfilter/ip_conntrack_proto_sctp.c	Sun Sep 26 23:17:15 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_sctp.c	Sat Oct 16 18:55:30 2004
@@ -405,6 +405,8 @@
 		}
 
 		conntrack->proto.sctp.state = newconntrack;
+		if (oldsctpstate != newconntrack)
+			ip_conntrack_cache_event(IPCT_PROTOINFO);
 		WRITE_UNLOCK(&sctp_lock);
 	}
 
===== net/ipv4/netfilter/ip_conntrack_core.c 1.72 vs edited =====
--- 1.72/net/ipv4/netfilter/ip_conntrack_core.c	Sun Oct 10 21:44:21 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_core.c	Sat Oct 16 18:41:37 2004
@@ -37,6 +37,7 @@
 #include <linux/err.h>
 #include <linux/percpu.h>
 #include <linux/moduleparam.h>
+#include <linux/notifier.h>
 
 /* This rwlock protects the main hash table, protocol/helper/expected
    registrations, conntrack timers*/
@@ -76,6 +77,11 @@
 struct ip_conntrack ip_conntrack_untracked;
 unsigned int ip_ct_log_invalid;
 
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+struct notifier_block *ip_conntrack_chain;
+DEFINE_PER_CPU(unsigned long, ip_conntrack_event_cache);
+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+
 DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
 
 inline void 
@@ -330,6 +336,7 @@
 
 	CONNTRACK_STAT_INC(delete_list);
 
+	ip_conntrack_event(IPCT_DESTROY, ct);
 	WRITE_LOCK(&ip_conntrack_lock);
 	clean_from_lists(ct);
 	WRITE_UNLOCK(&ip_conntrack_lock);
@@ -437,6 +444,7 @@
 		atomic_inc(&ct->ct_general.use);
 		set_bit(IPS_CONFIRMED_BIT, &ct->status);
 		WRITE_UNLOCK(&ip_conntrack_lock);
+ 		ip_conntrack_event(master_ct(ct)? IPCT_RELATED : IPCT_NEW, ct);
 		CONNTRACK_STAT_INC(insert);
 		return NF_ACCEPT;
 	}
@@ -706,6 +714,8 @@
 	/* FIXME: Do this right please. --RR */
 	(*pskb)->nfcache |= NFC_UNKNOWN;
 
+	ip_conntrack_event_cache_init();
+
 /* Doesn't cover locally-generated broadcast, so not worth it. */
 #if 0
 	/* Ignore broadcast: no `connection'. */
@@ -767,8 +777,11 @@
 			return NF_ACCEPT;
 		}
 	}
-	if (set_reply)
+	if (set_reply && !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
 		set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
+		ip_conntrack_cache_event(IPCT_STATUS);
+	}
+	ip_conntrack_deliver_cached_events(ct);
 
 	return ret;
 }
@@ -1052,6 +1065,7 @@
 		remove_expectations(i->ctrack, 0);
 		/* And *then* set helper to NULL */
 		i->ctrack->helper = NULL;
+		ip_conntrack_event(IPCT_HELPINFO, i->ctrack);
 	}
 	return 0;
 }
@@ -1105,6 +1119,7 @@
 		if (del_timer(&ct->timeout)) {
 			ct->timeout.expires = jiffies + extra_jiffies;
 			add_timer(&ct->timeout);
+			ip_conntrack_cache_event(IPCT_REFRESH);
 		}
 		ct_add_counters(ct, ctinfo, skb);
 		WRITE_UNLOCK(&ip_conntrack_lock);
===== net/ipv4/netfilter/ip_conntrack_ftp.c 1.27 vs edited =====
--- 1.27/net/ipv4/netfilter/ip_conntrack_ftp.c	Sun Oct 10 21:44:22 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_ftp.c	Sat Oct 16 18:41:37 2004
@@ -300,6 +300,7 @@
 			ct_ftp_info->seq_aft_nl[dir] = 
 						ntohl(th->seq) + datalen;
 			ct_ftp_info->seq_aft_nl_set[dir] = 1;
+			ip_conntrack_cache_event(IPCT_HELPINFO);
 		}
 	}
 
===== net/ipv4/netfilter/ip_conntrack_standalone.c 1.51 vs edited =====
--- 1.51/net/ipv4/netfilter/ip_conntrack_standalone.c	Thu Oct  7 00:11:17 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_standalone.c	Sat Oct 16 18:41:37 2004
@@ -47,6 +47,9 @@
 
 extern atomic_t ip_conntrack_count;
 DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+DECLARE_PER_CPU(unsigned long, ip_conntrack_event_cache);
+#endif
 
 static int kill_proto(const struct ip_conntrack *i, void *data)
 {
@@ -875,6 +878,10 @@
 {
 }
 
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+EXPORT_PER_CPU_SYMBOL(ip_conntrack_event_cache);
+EXPORT_SYMBOL(ip_conntrack_chain);
+#endif
 EXPORT_SYMBOL(ip_conntrack_protocol_register);
 EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
 EXPORT_SYMBOL(invert_tuplepr);
===== net/ipv4/netfilter/ip_conntrack_proto_tcp.c 1.23 vs edited =====
--- 1.23/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	Mon Sep 13 02:00:29 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	Sat Oct 16 18:42:58 2004
@@ -823,6 +823,32 @@
 	return NF_ACCEPT;
 }
 
+static inline void
+pickup_connection(struct ip_conntrack *conntrack, struct iphdr *iph,
+		  struct tcphdr *th, const struct sk_buff *skb)
+{
+	/*
+	 * We are in the middle of a connection,
+	 * its history is lost for us.
+	 * Let's try to use the data from the packet.
+	 */
+	conntrack->proto.tcp.seen[0].td_end =
+		segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
+	conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
+	if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
+		conntrack->proto.tcp.seen[0].td_maxwin = 1;
+	conntrack->proto.tcp.seen[0].td_maxend =
+		conntrack->proto.tcp.seen[0].td_end + 
+		conntrack->proto.tcp.seen[0].td_maxwin;
+	conntrack->proto.tcp.seen[0].td_scale = 0;
+
+	/* We assume SACK. Should we assume window scaling too? */
+	conntrack->proto.tcp.seen[0].flags =
+	conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
+	conntrack->proto.tcp.seen[0].loose = 
+	conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
+}
+
 /* Returns verdict for packet, or -1 for invalid. */
 static int tcp_packet(struct ip_conntrack *conntrack,
 		      const struct sk_buff *skb,
@@ -838,6 +864,11 @@
 	th = skb_header_pointer(skb, iph->ihl * 4,
 				sizeof(_tcph), &_tcph);
 	BUG_ON(th == NULL);
+
+	if (test_bit(IPS_PICKUP_BIT, &conntrack->status)) {
+		pickup_connection(conntrack, iph, th, skb);
+		__clear_bit(IPS_PICKUP_BIT, &conntrack->status);
+	}
 	
 	WRITE_LOCK(&tcp_lock);
 	old_state = conntrack->proto.tcp.state;
@@ -944,6 +975,10 @@
 		  ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
 	WRITE_UNLOCK(&tcp_lock);
 
+	ip_conntrack_cache_event(IPCT_PROTOINFO_VOLATILE);
+	if (new_state != old_state)
+		ip_conntrack_cache_event(IPCT_PROTOINFO);
+
 	if (!test_bit(IPS_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
@@ -1014,29 +1049,8 @@
 	} else if (ip_ct_tcp_loose == 0) {
 		/* Don't try to pick up connections. */
 		return 0;
-	} else {
-		/*
-		 * We are in the middle of a connection,
-		 * its history is lost for us.
-		 * Let's try to use the data from the packet.
-		 */
-		conntrack->proto.tcp.seen[0].td_end =
-			segment_seq_plus_len(ntohl(th->seq), skb->len,
-					     iph, th);
-		conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
-		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
-			conntrack->proto.tcp.seen[0].td_maxwin = 1;
-		conntrack->proto.tcp.seen[0].td_maxend =
-			conntrack->proto.tcp.seen[0].td_end + 
-			conntrack->proto.tcp.seen[0].td_maxwin;
-		conntrack->proto.tcp.seen[0].td_scale = 0;
-
-		/* We assume SACK. Should we assume window scaling too? */
-		conntrack->proto.tcp.seen[0].flags =
-		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
-		conntrack->proto.tcp.seen[0].loose = 
-		conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
-	}
+	} else 
+		pickup_connection(conntrack, iph, th, skb);
     
 	conntrack->proto.tcp.seen[1].td_end = 0;
 	conntrack->proto.tcp.seen[1].td_maxend = 0;
===== net/ipv4/netfilter/ip_conntrack_proto_udp.c 1.18 vs edited =====
--- 1.18/net/ipv4/netfilter/ip_conntrack_proto_udp.c	Sun Oct 10 21:44:22 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_udp.c	Sat Oct 16 18:41:37 2004
@@ -73,7 +73,10 @@
 		ip_ct_refresh_acct(conntrack, ctinfo, skb, 
 				   ip_ct_udp_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
-		set_bit(IPS_ASSURED_BIT, &conntrack->status);
+		if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)) {
+			set_bit(IPS_ASSURED_BIT, &conntrack->status);
+			ip_conntrack_cache_event(IPCT_STATUS);
+		}
 	} else
 		ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
 
===== net/ipv4/netfilter/ip_nat_core.c 1.48 vs edited =====
--- 1.48/net/ipv4/netfilter/ip_nat_core.c	Sun Oct 10 21:44:22 2004
+++ edited/net/ipv4/netfilter/ip_nat_core.c	Sat Oct 16 18:41:37 2004
@@ -607,6 +607,7 @@
 			   IP_NAT_MANIP_SRC, inv_tuple.src });
 		IP_NF_ASSERT(info->num_manips <= IP_NAT_MAX_MANIPS);
 	}
+	ip_conntrack_event(IPCT_NATINFO, conntrack);
 
 	/* If there's a helper, assign it; based on new tuple. */
 	if (!conntrack->master)

      reply	other threads:[~2004-10-16 18:21 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-15 17:54 [PATCH 2.6] connection tracking events Harald Welte
2004-10-16 13:21 ` Patrick McHardy
2004-10-16 15:07   ` Harald Welte
2004-10-16 15:20     ` Patrick McHardy
2004-10-16 15:32       ` Pablo Neira
2004-10-16 18:21         ` Pablo Neira [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=417166A8.3050809@eurodev.net \
    --to=pablo@eurodev.net \
    --cc=kaber@trash.net \
    --cc=laforge@netfilter.org \
    --cc=netfilter-devel@lists.netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.