All of lore.kernel.org
 help / color / mirror / Atom feed
* [NETFILTER 00/33]: Netfilter Update
@ 2006-11-29  2:08 Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 01/33]: nf_conntrack: split out expectation handling Patrick McHardy
                   ` (33 more replies)
  0 siblings, 34 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

Hi Dave,

following is a large netfilter update for 2.6.20. It contains some
cleanup of the nf_conntrack code and nf_conntrack sysctl/proc
compatibility with ip_conntrack, which both move a lot of code
around. Besides that there are some small enhancements for
nfnetlink_queue, nfnetlink_log and ctnetlink, a port of the hashlimit
match to xtables, a new NFLOG target for using the address family
independant nfnetlink_log mechanism, a set of patches to clean up
the SIP helper and fix multiple issues with the NAT helper, and a
few assorted fixes.

These patches contain all NAT unrelated parts from my nf_nat tree,
which is now down to about 10 patches adding NAT support and
ports of all helpers. I hope to get them ready for submission within
a week.

Please apply, thanks.

PS: You can (hopefully) also pull these changes from
http://people.netfilter.org/~kaber/nf-2.6.20.git


 include/linux/netfilter.h                             |   10 
 include/linux/netfilter/Kbuild                        |    2 
 include/linux/netfilter/nfnetlink_log.h               |    2 
 include/linux/netfilter/nfnetlink_queue.h             |    1 
 include/linux/netfilter/xt_NFLOG.h                    |   18 
 include/linux/netfilter/xt_hashlimit.h                |   40 
 include/linux/netfilter_bridge/ebt_nat.h              |    1 
 include/linux/netfilter_bridge/ebtables.h             |    4 
 include/linux/netfilter_ipv4/ip_conntrack.h           |    2 
 include/linux/netfilter_ipv4/ip_conntrack_sip.h       |   36 
 include/linux/netfilter_ipv4/ipt_LOG.h                |    2 
 include/linux/netfilter_ipv4/ipt_hashlimit.h          |   42 
 include/linux/netfilter_ipv6/ip6t_LOG.h               |    2 
 include/net/netfilter/ipv4/nf_conntrack_ipv4.h        |    7 
 include/net/netfilter/ipv6/nf_conntrack_ipv6.h        |   25 
 include/net/netfilter/nf_conntrack.h                  |  135 ---
 include/net/netfilter/nf_conntrack_core.h             |   20 
 include/net/netfilter/nf_conntrack_ecache.h           |   95 ++
 include/net/netfilter/nf_conntrack_expect.h           |   74 +
 include/net/netfilter/nf_conntrack_helper.h           |   20 
 include/net/netfilter/nf_conntrack_l3proto.h          |   15 
 include/net/netfilter/nf_conntrack_l4proto.h          |  146 +++
 include/net/netfilter/nf_conntrack_protocol.h         |  129 ---
 net/Kconfig                                           |    2 
 net/bridge/netfilter/ebt_mark.c                       |    6 
 net/bridge/netfilter/ebt_snat.c                       |   27 
 net/ipv4/netfilter/Kconfig                            |   25 
 net/ipv4/netfilter/Makefile                           |    6 
 net/ipv4/netfilter/ip_conntrack_amanda.c              |    9 
 net/ipv4/netfilter/ip_conntrack_core.c                |    8 
 net/ipv4/netfilter/ip_conntrack_ftp.c                 |    8 
 net/ipv4/netfilter/ip_conntrack_helper_h323.c         |  164 ++-
 net/ipv4/netfilter/ip_conntrack_helper_pptp.c         |   33 
 net/ipv4/netfilter/ip_conntrack_irc.c                 |   12 
 net/ipv4/netfilter/ip_conntrack_netlink.c             |   61 -
 net/ipv4/netfilter/ip_conntrack_proto_gre.c           |    2 
 net/ipv4/netfilter/ip_conntrack_sip.c                 |  126 +-
 net/ipv4/netfilter/ip_conntrack_standalone.c          |    6 
 net/ipv4/netfilter/ip_conntrack_tftp.c                |    6 
 net/ipv4/netfilter/ip_nat_amanda.c                    |    9 
 net/ipv4/netfilter/ip_nat_ftp.c                       |    9 
 net/ipv4/netfilter/ip_nat_helper_h323.c               |   58 -
 net/ipv4/netfilter/ip_nat_helper_pptp.c               |   29 
 net/ipv4/netfilter/ip_nat_irc.c                       |    9 
 net/ipv4/netfilter/ip_nat_sip.c                       |  223 ++---
 net/ipv4/netfilter/ip_nat_tftp.c                      |    9 
 net/ipv4/netfilter/ipt_CLUSTERIP.c                    |   25 
 net/ipv4/netfilter/ipt_LOG.c                          |    9 
 net/ipv4/netfilter/ipt_hashlimit.c                    |  733 -----------------
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c        |  156 +--
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c |  412 +++++++++
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c          |   54 +
 net/ipv6/netfilter/ip6_queue.c                        |    2 
 net/ipv6/netfilter/ip6t_LOG.c                         |    9 
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c        |   99 --
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c        |   38 
 net/netfilter/Kconfig                                 |   25 
 net/netfilter/Makefile                                |   13 
 net/netfilter/core.c                                  |    4 
 net/netfilter/nf_conntrack_core.c                     |  620 +-------------
 net/netfilter/nf_conntrack_ecache.c                   |   93 ++
 net/netfilter/nf_conntrack_expect.c                   |  370 ++++++++
 net/netfilter/nf_conntrack_ftp.c                      |   12 
 net/netfilter/nf_conntrack_helper.c                   |  158 +++
 net/netfilter/nf_conntrack_l3proto_generic.c          |    7 
 net/netfilter/nf_conntrack_netlink.c                  |  118 +-
 net/netfilter/nf_conntrack_proto.c                    |  486 ++++++++++-
 net/netfilter/nf_conntrack_proto_generic.c            |   47 +
 net/netfilter/nf_conntrack_proto_sctp.c               |  195 ++--
 net/netfilter/nf_conntrack_proto_tcp.c                |  262 +++++-
 net/netfilter/nf_conntrack_proto_udp.c                |   82 +
 net/netfilter/nf_conntrack_standalone.c               |  385 --------
 net/netfilter/nf_sysctl.c                             |  134 +++
 net/netfilter/nfnetlink_log.c                         |   19 
 net/netfilter/nfnetlink_queue.c                       |    8 
 net/netfilter/xt_CONNMARK.c                           |    3 
 net/netfilter/xt_NFLOG.c                              |   86 ++
 net/netfilter/xt_hashlimit.c                          |  772 ++++++++++++++++++
 78 files changed, 4310 insertions(+), 2801 deletions(-)

Bart De Schuymer:
      [NETFILTER]: ebtables: add --snap-arp option

Eric Leblond:
      [NETFILTER]: nfnetlink_queue: allow changing queue length through netlink

Martin Josefsson:
      [NETFILTER]: nf_conntrack: split out expectation handling
      [NETFILTER]: nf_conntrack: split out helper handling
      [NETFILTER]: nf_conntrack: split out the event cache
      [NETFILTER]: nf_conntrack: split out protocol handling
      [NETFILTER]: More __read_mostly annotations
      [NETFILTER]: nf_conntrack: rename struct nf_conntrack_protocol
      [NETFILTER]: nf_conntrack: more sanity checks in protocol registration/unregistration
      [NETFILTER]: nf_conntrack: remove ASSERT_{READ,WRITE}_LOCK
      [NETFILTER]: nf_conntrack: minor __nf_ct_refresh_acct() whitespace cleanup
      [NETFILTER]: nf_conntrack: remove unused struct list_head from protocols
      [NETFILTER]: nf_conntrack: reduce timer updates in __nf_ct_refresh_acct()

Pablo Neira Ayuso:
      [NETFILTER]: ctnetlink: check for status attribute existence on conntrack creation
      [NETFILTER]: ctnetlink: rework conntrack fields dumping logic on events
      [NETFILTER]: remove the reference to ipchains from Kconfig

Patrick McHardy:
      [NETFILTER]: nf_conntrack_ftp: fix missing helper mask initilization
      [NETFILTER]: nf_conntrack: move extern declaration to header files
      [NETFILTER]: nf_conntrack: automatic sysctl registation for conntrack protocols
      [NETFILTER]: nf_conntrack: move conntrack protocol sysctls to individual modules
      [NETFILTER]: nf_conntrack: sysctl compatibility with old connection tracking
      [NETFILTER]: nf_conntrack: /proc compatibility with old connection tracking
      [NETFILTER]: ip_conntrack: fix NAT helper unload races
      [NETFILTER]: sip conntrack: minor cleanup
      [NETFILTER]: sip conntrack: do case insensitive SIP header search
      [NETFILTER]: sip conntrack: make header shortcuts optional
      [NETFILTER]: sip conntrack: better NAT handling
      [NETFILTER]: nfnetlink_log: remove useless prefix length limitation
      [NETFILTER]: x_tables: add port of hashlimit match for IPv4 and IPv6
      [NETFILTER]: x_tables: add NFLOG target
      [NETFILTER]: remove remaining ASSERT_{READ,WRITE}_LOCK
      [NETFILTER]: Fix PROC_FS=n warnings

Yasuyuki Kozakai:
      [NETFILTER]: conntrack: add '_get' to {ip, nf}_conntrack_expect_find

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [NETFILTER 01/33]: nf_conntrack: split out expectation handling
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 02/33]: nf_conntrack: split out helper handling Patrick McHardy
                   ` (32 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: split out expectation handling

This patch splits out expectation handling into its own file
nf_conntrack_expect.c

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit e6d24133099d38b61f8974caa935b683ec6b3027
tree 45425d105fd2b8fea787dc0536a6c0dc6747ccd4
parent 6392f566a12559393b3f61d63e597acadd87a254
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:12:27 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:12:27 +0100

 include/net/netfilter/nf_conntrack.h        |   49 ----
 include/net/netfilter/nf_conntrack_core.h   |    7 +
 include/net/netfilter/nf_conntrack_expect.h |   72 +++++
 include/net/netfilter/nf_conntrack_helper.h |   10 -
 net/netfilter/Makefile                      |    2 
 net/netfilter/nf_conntrack_core.c           |  265 --------------------
 net/netfilter/nf_conntrack_expect.c         |  365 +++++++++++++++++++++++++++
 net/netfilter/nf_conntrack_ftp.c            |    1 
 net/netfilter/nf_conntrack_netlink.c        |    1 
 net/netfilter/nf_conntrack_standalone.c     |   81 ------
 10 files changed, 452 insertions(+), 401 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 1fbd819..9d2581f 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -124,44 +124,6 @@ #endif
 	char data[0];
 };
 
-struct nf_conntrack_expect
-{
-	/* Internal linked list (global expectation list) */
-	struct list_head list;
-
-	/* We expect this tuple, with the following mask */
-	struct nf_conntrack_tuple tuple, mask;
- 
-	/* Function to call after setup and insertion */
-	void (*expectfn)(struct nf_conn *new,
-			 struct nf_conntrack_expect *this);
-
-	/* The conntrack of the master connection */
-	struct nf_conn *master;
-
-	/* Timer function; deletes the expectation. */
-	struct timer_list timeout;
-
-	/* Usage count. */
-	atomic_t use;
-
-	/* Unique ID */
-	unsigned int id;
-
-	/* Flags */
-	unsigned int flags;
-
-#ifdef CONFIG_NF_NAT_NEEDED
-	/* This is the original per-proto part, used to map the
-	 * expected connection the way the recipient expects. */
-	union nf_conntrack_manip_proto saved_proto;
-	/* Direction relative to the master connection. */
-	enum ip_conntrack_dir dir;
-#endif
-};
-
-#define NF_CT_EXPECT_PERMANENT 0x1
-
 static inline struct nf_conn *
 nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash)
 {
@@ -208,16 +170,6 @@ __nf_conntrack_find(const struct nf_conn
 
 extern void nf_conntrack_hash_insert(struct nf_conn *ct);
 
-extern struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
-
-extern struct nf_conntrack_expect *
-nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
-
-extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
-
-extern void nf_ct_remove_expectations(struct nf_conn *ct);
-
 extern void nf_conntrack_flush(void);
 
 extern struct nf_conntrack_helper *
@@ -295,6 +247,7 @@ #define NF_CT_STAT_INC(count) (__get_cpu
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 #include <linux/notifier.h>
 #include <linux/interrupt.h>
+#include <net/netfilter/nf_conntrack_expect.h>
 
 struct nf_conntrack_ecache {
 	struct nf_conn *ct;
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index da25452..84a8e01 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -13,6 +13,8 @@ #ifndef _NF_CONNTRACK_CORE_H
 #define _NF_CONNTRACK_CORE_H
 
 #include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_protocol.h>
 
 /* This header is used to share core functionality between the
    standalone connection tracking module, and the compatibility layer's use
@@ -70,6 +72,11 @@ static inline int nf_conntrack_confirm(s
 
 extern void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb);
 
+int
+print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
+	    struct nf_conntrack_l3proto *l3proto,
+	    struct nf_conntrack_protocol *proto);
+
 extern struct list_head *nf_conntrack_hash;
 extern struct list_head nf_conntrack_expect_list;
 extern rwlock_t nf_conntrack_lock ;
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
new file mode 100644
index 0000000..5aa483e
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -0,0 +1,72 @@
+/*
+ * connection tracking expectations.
+ */
+
+#ifndef _NF_CONNTRACK_EXPECT_H
+#define _NF_CONNTRACK_EXPECT_H
+#include <net/netfilter/nf_conntrack.h>
+
+extern struct list_head nf_conntrack_expect_list;
+extern kmem_cache_t *nf_conntrack_expect_cachep;
+extern struct file_operations exp_file_ops;
+
+struct nf_conntrack_expect
+{
+	/* Internal linked list (global expectation list) */
+	struct list_head list;
+
+	/* We expect this tuple, with the following mask */
+	struct nf_conntrack_tuple tuple, mask;
+
+	/* Function to call after setup and insertion */
+	void (*expectfn)(struct nf_conn *new,
+			 struct nf_conntrack_expect *this);
+
+	/* The conntrack of the master connection */
+	struct nf_conn *master;
+
+	/* Timer function; deletes the expectation. */
+	struct timer_list timeout;
+
+	/* Usage count. */
+	atomic_t use;
+
+	/* Unique ID */
+	unsigned int id;
+
+	/* Flags */
+	unsigned int flags;
+
+#ifdef CONFIG_NF_NAT_NEEDED
+	/* This is the original per-proto part, used to map the
+	 * expected connection the way the recipient expects. */
+	union nf_conntrack_manip_proto saved_proto;
+	/* Direction relative to the master connection. */
+	enum ip_conntrack_dir dir;
+#endif
+};
+
+#define NF_CT_EXPECT_PERMANENT 0x1
+
+
+struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+find_expectation(const struct nf_conntrack_tuple *tuple);
+
+void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
+void nf_ct_remove_expectations(struct nf_conn *ct);
+void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
+
+/* Allocate space for an expectation: this is mandatory before calling
+   nf_conntrack_expect_related.  You will have to call put afterwards. */
+struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me);
+void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
+int nf_conntrack_expect_related(struct nf_conntrack_expect *expect);
+
+#endif /*_NF_CONNTRACK_EXPECT_H*/
+
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 86ec817..3cbd13e 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -40,14 +40,4 @@ struct nf_conntrack_helper
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
 
-/* Allocate space for an expectation: this is mandatory before calling
-   nf_conntrack_expect_related.  You will have to call put afterwards. */
-extern struct nf_conntrack_expect *
-nf_conntrack_expect_alloc(struct nf_conn *master);
-extern void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
-
-/* Add an expected connection: can have more than one per connection */
-extern int nf_conntrack_expect_related(struct nf_conntrack_expect *exp);
-extern void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
-
 #endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a74be49..d33b9ac 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,5 +1,5 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
-nf_conntrack-objs	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-objs	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index de0567b..72fbae4 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -55,6 +55,7 @@ #define ASSERT_WRITE_LOCK(x)
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
@@ -72,21 +73,19 @@ DEFINE_RWLOCK(nf_conntrack_lock);
 atomic_t nf_conntrack_count = ATOMIC_INIT(0);
 
 void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
-LIST_HEAD(nf_conntrack_expect_list);
 struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
 struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
 static LIST_HEAD(helpers);
 unsigned int nf_conntrack_htable_size __read_mostly = 0;
 int nf_conntrack_max __read_mostly;
 struct list_head *nf_conntrack_hash __read_mostly;
-static kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
 struct nf_conn nf_conntrack_untracked;
 unsigned int nf_ct_log_invalid __read_mostly;
 static LIST_HEAD(unconfirmed);
 static int nf_conntrack_vmalloc __read_mostly;
 
 static unsigned int nf_conntrack_next_id;
-static unsigned int nf_conntrack_expect_next_id;
+
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
 ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
@@ -438,103 +437,6 @@ nf_ct_invert_tuple(struct nf_conntrack_t
 	return protocol->invert_tuple(inverse, orig);
 }
 
-/* nf_conntrack_expect helper functions */
-void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
-{
-	struct nf_conn_help *master_help = nfct_help(exp->master);
-
-	NF_CT_ASSERT(master_help);
-	ASSERT_WRITE_LOCK(&nf_conntrack_lock);
-	NF_CT_ASSERT(!timer_pending(&exp->timeout));
-
-	list_del(&exp->list);
-	NF_CT_STAT_INC(expect_delete);
-	master_help->expecting--;
-	nf_conntrack_expect_put(exp);
-}
-
-static void expectation_timed_out(unsigned long ul_expect)
-{
-	struct nf_conntrack_expect *exp = (void *)ul_expect;
-
-	write_lock_bh(&nf_conntrack_lock);
-	nf_ct_unlink_expect(exp);
-	write_unlock_bh(&nf_conntrack_lock);
-	nf_conntrack_expect_put(exp);
-}
-
-struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
-{
-	struct nf_conntrack_expect *i;
-	
-	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
-		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
-			return i;
-	}
-	return NULL;
-}
-
-/* Just find a expectation corresponding to a tuple. */
-struct nf_conntrack_expect *
-nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
-{
-	struct nf_conntrack_expect *i;
-	
-	read_lock_bh(&nf_conntrack_lock);
-	i = __nf_conntrack_expect_find(tuple);
-	if (i)
-		atomic_inc(&i->use);
-	read_unlock_bh(&nf_conntrack_lock);
-
-	return i;
-}
-
-/* If an expectation for this connection is found, it gets delete from
- * global list then returned. */
-static struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple)
-{
-	struct nf_conntrack_expect *i;
-
-	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
-	/* If master is not in hash table yet (ie. packet hasn't left
-	   this machine yet), how can other end know about expected?
-	   Hence these are not the droids you are looking for (if
-	   master ct never got confirmed, we'd hold a reference to it
-	   and weird things would happen to future packets). */
-		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
-		    && nf_ct_is_confirmed(i->master)) {
-			if (i->flags & NF_CT_EXPECT_PERMANENT) {
-				atomic_inc(&i->use);
-				return i;
-			} else if (del_timer(&i->timeout)) {
-				nf_ct_unlink_expect(i);
-				return i;
-			}
-		}
-	}
-	return NULL;
-}
-
-/* delete all expectations for this conntrack */
-void nf_ct_remove_expectations(struct nf_conn *ct)
-{
-	struct nf_conntrack_expect *i, *tmp;
-	struct nf_conn_help *help = nfct_help(ct);
-
-	/* Optimization: most connection never expect any others. */
-	if (!help || help->expecting == 0)
-		return;
-
-	list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
-		if (i->master == ct && del_timer(&i->timeout)) {
-			nf_ct_unlink_expect(i);
-			nf_conntrack_expect_put(i);
- 		}
-	}
-}
-
 static void
 clean_from_lists(struct nf_conn *ct)
 {
@@ -1133,169 +1035,6 @@ int nf_ct_invert_tuplepr(struct nf_connt
 						     orig->dst.protonum));
 }
 
-/* Would two expected things clash? */
-static inline int expect_clash(const struct nf_conntrack_expect *a,
-			       const struct nf_conntrack_expect *b)
-{
-	/* Part covered by intersection of masks must be unequal,
-	   otherwise they clash */
-	struct nf_conntrack_tuple intersect_mask;
-	int count;
-
-	intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num;
-	intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
-	intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all;
-	intersect_mask.dst.protonum = a->mask.dst.protonum
-					& b->mask.dst.protonum;
-
-	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-		intersect_mask.src.u3.all[count] =
-			a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
-	}
-
-	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-		intersect_mask.dst.u3.all[count] =
-			a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count];
-	}
-
-	return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
-}
-
-static inline int expect_matches(const struct nf_conntrack_expect *a,
-				 const struct nf_conntrack_expect *b)
-{
-	return a->master == b->master
-		&& nf_ct_tuple_equal(&a->tuple, &b->tuple)
-		&& nf_ct_tuple_equal(&a->mask, &b->mask);
-}
-
-/* Generally a bad idea to call this: could have matched already. */
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
-{
-	struct nf_conntrack_expect *i;
-
-	write_lock_bh(&nf_conntrack_lock);
-	/* choose the the oldest expectation to evict */
-	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
-		if (expect_matches(i, exp) && del_timer(&i->timeout)) {
-			nf_ct_unlink_expect(i);
-			write_unlock_bh(&nf_conntrack_lock);
-			nf_conntrack_expect_put(i);
-			return;
-		}
-	}
-	write_unlock_bh(&nf_conntrack_lock);
-}
-
-/* We don't increase the master conntrack refcount for non-fulfilled
- * conntracks. During the conntrack destruction, the expectations are
- * always killed before the conntrack itself */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
-{
-	struct nf_conntrack_expect *new;
-
-	new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC);
-	if (!new) {
-		DEBUGP("expect_related: OOM allocating expect\n");
-		return NULL;
-	}
-	new->master = me;
-	atomic_set(&new->use, 1);
-	return new;
-}
-
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
-{
-	if (atomic_dec_and_test(&exp->use))
-		kmem_cache_free(nf_conntrack_expect_cachep, exp);
-}
-
-static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
-{
-	struct nf_conn_help *master_help = nfct_help(exp->master);
-
-	atomic_inc(&exp->use);
-	master_help->expecting++;
-	list_add(&exp->list, &nf_conntrack_expect_list);
-
-	init_timer(&exp->timeout);
-	exp->timeout.data = (unsigned long)exp;
-	exp->timeout.function = expectation_timed_out;
-	exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
-	add_timer(&exp->timeout);
-
-	exp->id = ++nf_conntrack_expect_next_id;
-	atomic_inc(&exp->use);
-	NF_CT_STAT_INC(expect_create);
-}
-
-/* Race with expectations being used means we could have none to find; OK. */
-static void evict_oldest_expect(struct nf_conn *master)
-{
-	struct nf_conntrack_expect *i;
-
-	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
-		if (i->master == master) {
-			if (del_timer(&i->timeout)) {
-				nf_ct_unlink_expect(i);
-				nf_conntrack_expect_put(i);
-			}
-			break;
-		}
-	}
-}
-
-static inline int refresh_timer(struct nf_conntrack_expect *i)
-{
-	struct nf_conn_help *master_help = nfct_help(i->master);
-
-	if (!del_timer(&i->timeout))
-		return 0;
-
-	i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
-	add_timer(&i->timeout);
-	return 1;
-}
-
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
-{
-	struct nf_conntrack_expect *i;
-	struct nf_conn *master = expect->master;
-	struct nf_conn_help *master_help = nfct_help(master);
-	int ret;
-
-	NF_CT_ASSERT(master_help);
-
-	DEBUGP("nf_conntrack_expect_related %p\n", related_to);
-	DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple);
-	DEBUGP("mask:  "); NF_CT_DUMP_TUPLE(&expect->mask);
-
-	write_lock_bh(&nf_conntrack_lock);
-	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
-		if (expect_matches(i, expect)) {
-			/* Refresh timer: if it's dying, ignore.. */
-			if (refresh_timer(i)) {
-				ret = 0;
-				goto out;
-			}
-		} else if (expect_clash(i, expect)) {
-			ret = -EBUSY;
-			goto out;
-		}
-	}
-	/* Will be over limit? */
-	if (master_help->helper->max_expected &&
-	    master_help->expecting >= master_help->helper->max_expected)
-		evict_oldest_expect(master);
-
-	nf_conntrack_expect_insert(expect);
-	nf_conntrack_expect_event(IPEXP_NEW, expect);
-	ret = 0;
-out:
-	write_unlock_bh(&nf_conntrack_lock);
-	return ret;
-}
-
 int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
 	int ret;
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
new file mode 100644
index 0000000..076e678
--- /dev/null
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -0,0 +1,365 @@
+/* Expectation handling for nf_conntrack. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/kernel.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+LIST_HEAD(nf_conntrack_expect_list);
+kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
+DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
+static unsigned int nf_conntrack_expect_next_id;
+
+/* nf_conntrack_expect helper functions */
+void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+{
+	struct nf_conn_help *master_help = nfct_help(exp->master);
+
+	NF_CT_ASSERT(master_help);
+	NF_CT_ASSERT(!timer_pending(&exp->timeout));
+
+	list_del(&exp->list);
+	NF_CT_STAT_INC(expect_delete);
+	master_help->expecting--;
+	nf_conntrack_expect_put(exp);
+}
+
+static void expectation_timed_out(unsigned long ul_expect)
+{
+	struct nf_conntrack_expect *exp = (void *)ul_expect;
+
+	write_lock_bh(&nf_conntrack_lock);
+	nf_ct_unlink_expect(exp);
+	write_unlock_bh(&nf_conntrack_lock);
+	nf_conntrack_expect_put(exp);
+}
+
+struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_expect *i;
+
+	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
+			return i;
+	}
+	return NULL;
+}
+
+/* Just find a expectation corresponding to a tuple. */
+struct nf_conntrack_expect *
+nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_expect *i;
+
+	read_lock_bh(&nf_conntrack_lock);
+	i = __nf_conntrack_expect_find(tuple);
+	if (i)
+		atomic_inc(&i->use);
+	read_unlock_bh(&nf_conntrack_lock);
+
+	return i;
+}
+
+/* If an expectation for this connection is found, it gets delete from
+ * global list then returned. */
+struct nf_conntrack_expect *
+find_expectation(const struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_expect *i;
+
+	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+	/* If master is not in hash table yet (ie. packet hasn't left
+	   this machine yet), how can other end know about expected?
+	   Hence these are not the droids you are looking for (if
+	   master ct never got confirmed, we'd hold a reference to it
+	   and weird things would happen to future packets). */
+		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
+		    && nf_ct_is_confirmed(i->master)) {
+			if (i->flags & NF_CT_EXPECT_PERMANENT) {
+				atomic_inc(&i->use);
+				return i;
+			} else if (del_timer(&i->timeout)) {
+				nf_ct_unlink_expect(i);
+				return i;
+			}
+		}
+	}
+	return NULL;
+}
+
+/* delete all expectations for this conntrack */
+void nf_ct_remove_expectations(struct nf_conn *ct)
+{
+	struct nf_conntrack_expect *i, *tmp;
+	struct nf_conn_help *help = nfct_help(ct);
+
+	/* Optimization: most connection never expect any others. */
+	if (!help || help->expecting == 0)
+		return;
+
+	list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
+		if (i->master == ct && del_timer(&i->timeout)) {
+			nf_ct_unlink_expect(i);
+			nf_conntrack_expect_put(i);
+ 		}
+	}
+}
+
+/* Would two expected things clash? */
+static inline int expect_clash(const struct nf_conntrack_expect *a,
+			       const struct nf_conntrack_expect *b)
+{
+	/* Part covered by intersection of masks must be unequal,
+	   otherwise they clash */
+	struct nf_conntrack_tuple intersect_mask;
+	int count;
+
+	intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num;
+	intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
+	intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all;
+	intersect_mask.dst.protonum = a->mask.dst.protonum
+					& b->mask.dst.protonum;
+
+	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
+		intersect_mask.src.u3.all[count] =
+			a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
+	}
+
+	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
+		intersect_mask.dst.u3.all[count] =
+			a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count];
+	}
+
+	return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
+}
+
+static inline int expect_matches(const struct nf_conntrack_expect *a,
+				 const struct nf_conntrack_expect *b)
+{
+	return a->master == b->master
+		&& nf_ct_tuple_equal(&a->tuple, &b->tuple)
+		&& nf_ct_tuple_equal(&a->mask, &b->mask);
+}
+
+/* Generally a bad idea to call this: could have matched already. */
+void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
+{
+	struct nf_conntrack_expect *i;
+
+	write_lock_bh(&nf_conntrack_lock);
+	/* choose the the oldest expectation to evict */
+	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
+		if (expect_matches(i, exp) && del_timer(&i->timeout)) {
+			nf_ct_unlink_expect(i);
+			write_unlock_bh(&nf_conntrack_lock);
+			nf_conntrack_expect_put(i);
+			return;
+		}
+	}
+	write_unlock_bh(&nf_conntrack_lock);
+}
+
+/* We don't increase the master conntrack refcount for non-fulfilled
+ * conntracks. During the conntrack destruction, the expectations are
+ * always killed before the conntrack itself */
+struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
+{
+	struct nf_conntrack_expect *new;
+
+	new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC);
+	if (!new)
+		return NULL;
+
+	new->master = me;
+	atomic_set(&new->use, 1);
+	return new;
+}
+
+void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
+{
+	if (atomic_dec_and_test(&exp->use))
+		kmem_cache_free(nf_conntrack_expect_cachep, exp);
+}
+
+static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
+{
+	struct nf_conn_help *master_help = nfct_help(exp->master);
+
+	atomic_inc(&exp->use);
+	master_help->expecting++;
+	list_add(&exp->list, &nf_conntrack_expect_list);
+
+	init_timer(&exp->timeout);
+	exp->timeout.data = (unsigned long)exp;
+	exp->timeout.function = expectation_timed_out;
+	exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
+	add_timer(&exp->timeout);
+
+	exp->id = ++nf_conntrack_expect_next_id;
+	atomic_inc(&exp->use);
+	NF_CT_STAT_INC(expect_create);
+}
+
+/* Race with expectations being used means we could have none to find; OK. */
+static void evict_oldest_expect(struct nf_conn *master)
+{
+	struct nf_conntrack_expect *i;
+
+	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
+		if (i->master == master) {
+			if (del_timer(&i->timeout)) {
+				nf_ct_unlink_expect(i);
+				nf_conntrack_expect_put(i);
+			}
+			break;
+		}
+	}
+}
+
+static inline int refresh_timer(struct nf_conntrack_expect *i)
+{
+	struct nf_conn_help *master_help = nfct_help(i->master);
+
+	if (!del_timer(&i->timeout))
+		return 0;
+
+	i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
+	add_timer(&i->timeout);
+	return 1;
+}
+
+int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
+{
+	struct nf_conntrack_expect *i;
+	struct nf_conn *master = expect->master;
+	struct nf_conn_help *master_help = nfct_help(master);
+	int ret;
+
+	NF_CT_ASSERT(master_help);
+
+	write_lock_bh(&nf_conntrack_lock);
+	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+		if (expect_matches(i, expect)) {
+			/* Refresh timer: if it's dying, ignore.. */
+			if (refresh_timer(i)) {
+				ret = 0;
+				goto out;
+			}
+		} else if (expect_clash(i, expect)) {
+			ret = -EBUSY;
+			goto out;
+		}
+	}
+	/* Will be over limit? */
+	if (master_help->helper->max_expected &&
+	    master_help->expecting >= master_help->helper->max_expected)
+		evict_oldest_expect(master);
+
+	nf_conntrack_expect_insert(expect);
+	nf_conntrack_expect_event(IPEXP_NEW, expect);
+	ret = 0;
+out:
+	write_unlock_bh(&nf_conntrack_lock);
+	return ret;
+}
+
+#ifdef CONFIG_PROC_FS
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct list_head *e = &nf_conntrack_expect_list;
+	loff_t i;
+
+	/* strange seq_file api calls stop even if we fail,
+	 * thus we need to grab lock since stop unlocks */
+	read_lock_bh(&nf_conntrack_lock);
+
+	if (list_empty(e))
+		return NULL;
+
+	for (i = 0; i <= *pos; i++) {
+		e = e->next;
+		if (e == &nf_conntrack_expect_list)
+			return NULL;
+	}
+	return e;
+}
+
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct list_head *e = v;
+
+	++*pos;
+	e = e->next;
+
+	if (e == &nf_conntrack_expect_list)
+		return NULL;
+
+	return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
+	read_unlock_bh(&nf_conntrack_lock);
+}
+
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+	struct nf_conntrack_expect *expect = v;
+
+	if (expect->timeout.function)
+		seq_printf(s, "%ld ", timer_pending(&expect->timeout)
+			   ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
+	else
+		seq_printf(s, "- ");
+	seq_printf(s, "l3proto = %u proto=%u ",
+		   expect->tuple.src.l3num,
+		   expect->tuple.dst.protonum);
+	print_tuple(s, &expect->tuple,
+		    __nf_ct_l3proto_find(expect->tuple.src.l3num),
+		    __nf_ct_proto_find(expect->tuple.src.l3num,
+				       expect->tuple.dst.protonum));
+	return seq_putc(s, '\n');
+}
+
+static struct seq_operations exp_seq_ops = {
+	.start = exp_seq_start,
+	.next = exp_seq_next,
+	.stop = exp_seq_stop,
+	.show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &exp_seq_ops);
+}
+
+struct file_operations exp_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = exp_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+#endif /* CONFIG_PROC_FS */
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 0c17a5b..503fabf 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -26,6 +26,7 @@ #include <net/checksum.h>
 #include <net/tcp.h>
 
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <linux/netfilter/nf_conntrack_ftp.h>
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index cfb35fd..c3d53d9 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -35,6 +35,7 @@ #include <linux/notifier.h>
 #include <linux/netfilter.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 5954f67..72643d3 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -36,6 +36,7 @@ #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 
 #if 0
@@ -66,7 +67,7 @@ static int kill_proto(struct nf_conn *i,
 }
 
 #ifdef CONFIG_PROC_FS
-static int
+int
 print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
 	    struct nf_conntrack_l3proto *l3proto,
 	    struct nf_conntrack_protocol *proto)
@@ -258,84 +259,6 @@ static struct file_operations ct_file_op
 	.release = seq_release_private,
 };
 
-/* expects */
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
-{
-	struct list_head *e = &nf_conntrack_expect_list;
-	loff_t i;
-
-	/* strange seq_file api calls stop even if we fail,
-	 * thus we need to grab lock since stop unlocks */
-	read_lock_bh(&nf_conntrack_lock);
-
-	if (list_empty(e))
-		return NULL;
-
-	for (i = 0; i <= *pos; i++) {
-		e = e->next;
-		if (e == &nf_conntrack_expect_list)
-			return NULL;
-	}
-	return e;
-}
-
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-	struct list_head *e = v;
-
-	++*pos;
-	e = e->next;
-
-	if (e == &nf_conntrack_expect_list)
-		return NULL;
-
-	return e;
-}
-
-static void exp_seq_stop(struct seq_file *s, void *v)
-{
-	read_unlock_bh(&nf_conntrack_lock);
-}
-
-static int exp_seq_show(struct seq_file *s, void *v)
-{
-	struct nf_conntrack_expect *expect = v;
-
-	if (expect->timeout.function)
-		seq_printf(s, "%ld ", timer_pending(&expect->timeout)
-			   ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
-	else
-		seq_printf(s, "- ");
-	seq_printf(s, "l3proto = %u proto=%u ",
-		   expect->tuple.src.l3num,
-		   expect->tuple.dst.protonum);
-	print_tuple(s, &expect->tuple,
-		    __nf_ct_l3proto_find(expect->tuple.src.l3num),
-		    __nf_ct_proto_find(expect->tuple.src.l3num,
-				       expect->tuple.dst.protonum));
-	return seq_putc(s, '\n');
-}
-
-static struct seq_operations exp_seq_ops = {
-	.start = exp_seq_start,
-	.next = exp_seq_next,
-	.stop = exp_seq_stop,
-	.show = exp_seq_show
-};
-
-static int exp_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &exp_seq_ops);
-}
-
-static struct file_operations exp_file_ops = {
-	.owner   = THIS_MODULE,
-	.open    = exp_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release
-};
-
 static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	int cpu;

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 02/33]: nf_conntrack: split out helper handling
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 01/33]: nf_conntrack: split out expectation handling Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 03/33]: nf_conntrack: split out the event cache Patrick McHardy
                   ` (31 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: split out helper handling

This patch splits out handling of helpers into its own file
nf_conntrack_helper.c

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 19dfaa08934591045aee3699c74e9deffbfd5587
tree d9fb510af394bd0950e31b7eeaac74b54abea67c
parent e6d24133099d38b61f8974caa935b683ec6b3027
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:12:47 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:12:47 +0100

 include/net/netfilter/nf_conntrack_core.h   |    2 
 include/net/netfilter/nf_conntrack_helper.h |   10 ++
 net/netfilter/Makefile                      |    2 
 net/netfilter/nf_conntrack_core.c           |  120 ---------------------
 net/netfilter/nf_conntrack_helper.c         |  151 +++++++++++++++++++++++++++
 5 files changed, 165 insertions(+), 120 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 84a8e01..bf8d300 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -80,4 +80,6 @@ print_tuple(struct seq_file *s, const st
 extern struct list_head *nf_conntrack_hash;
 extern struct list_head nf_conntrack_expect_list;
 extern rwlock_t nf_conntrack_lock ;
+extern struct list_head unconfirmed;
+
 #endif /* _NF_CONNTRACK_CORE_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 3cbd13e..fbba9e8 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -37,6 +37,16 @@ struct nf_conntrack_helper
 	int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
 };
 
+extern struct nf_conntrack_helper *
+__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple);
+
+extern struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
+
+extern struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name);
+
+extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
 
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index d33b9ac..2363764 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,5 +1,5 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
-nf_conntrack-objs	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-objs	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 72fbae4..cf6face 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -75,13 +75,12 @@ atomic_t nf_conntrack_count = ATOMIC_INI
 void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
 struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
 struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
-static LIST_HEAD(helpers);
 unsigned int nf_conntrack_htable_size __read_mostly = 0;
 int nf_conntrack_max __read_mostly;
 struct list_head *nf_conntrack_hash __read_mostly;
 struct nf_conn nf_conntrack_untracked;
 unsigned int nf_ct_log_invalid __read_mostly;
-static LIST_HEAD(unconfirmed);
+LIST_HEAD(unconfirmed);
 static int nf_conntrack_vmalloc __read_mostly;
 
 static unsigned int nf_conntrack_next_id;
@@ -696,46 +695,6 @@ static int early_drop(struct list_head *
 	return dropped;
 }
 
-static struct nf_conntrack_helper *
-__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
-{
-	struct nf_conntrack_helper *h;
-
-	list_for_each_entry(h, &helpers, list) {
-		if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
-			return h;
-	}
-	return NULL;
-}
-
-struct nf_conntrack_helper *
-nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
-{
-	struct nf_conntrack_helper *helper;
-
-	/* need nf_conntrack_lock to assure that helper exists until
-	 * try_module_get() is called */
-	read_lock_bh(&nf_conntrack_lock);
-
-	helper = __nf_ct_helper_find(tuple);
-	if (helper) {
-		/* need to increase module usage count to assure helper will
-		 * not go away while the caller is e.g. busy putting a
-		 * conntrack in the hash that uses the helper */
-		if (!try_module_get(helper->me))
-			helper = NULL;
-	}
-
-	read_unlock_bh(&nf_conntrack_lock);
-
-	return helper;
-}
-
-void nf_ct_helper_put(struct nf_conntrack_helper *helper)
-{
-	module_put(helper->me);
-}
-
 static struct nf_conn *
 __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
 		     const struct nf_conntrack_tuple *repl,
@@ -1035,83 +994,6 @@ int nf_ct_invert_tuplepr(struct nf_connt
 						     orig->dst.protonum));
 }
 
-int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
-{
-	int ret;
-	BUG_ON(me->timeout == 0);
-
-	ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
-					  sizeof(struct nf_conn)
-					  + sizeof(struct nf_conn_help)
-					  + __alignof__(struct nf_conn_help));
-	if (ret < 0) {
-		printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n");
-		return ret;
-	}
-	write_lock_bh(&nf_conntrack_lock);
-	list_add(&me->list, &helpers);
-	write_unlock_bh(&nf_conntrack_lock);
-
-	return 0;
-}
-
-struct nf_conntrack_helper *
-__nf_conntrack_helper_find_byname(const char *name)
-{
-	struct nf_conntrack_helper *h;
-
-	list_for_each_entry(h, &helpers, list) {
-		if (!strcmp(h->name, name))
-			return h;
-	}
-
-	return NULL;
-}
-
-static inline void unhelp(struct nf_conntrack_tuple_hash *i,
-			  const struct nf_conntrack_helper *me)
-{
-	struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
-	struct nf_conn_help *help = nfct_help(ct);
-
-	if (help && help->helper == me) {
-		nf_conntrack_event(IPCT_HELPER, ct);
-		help->helper = NULL;
-	}
-}
-
-void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
-{
-	unsigned int i;
-	struct nf_conntrack_tuple_hash *h;
-	struct nf_conntrack_expect *exp, *tmp;
-
-	/* Need write lock here, to delete helper. */
-	write_lock_bh(&nf_conntrack_lock);
-	list_del(&me->list);
-
-	/* Get rid of expectations */
-	list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
-		struct nf_conn_help *help = nfct_help(exp->master);
-		if (help->helper == me && del_timer(&exp->timeout)) {
-			nf_ct_unlink_expect(exp);
-			nf_conntrack_expect_put(exp);
-		}
-	}
-
-	/* Get rid of expecteds, set helpers to NULL. */
-	list_for_each_entry(h, &unconfirmed, list)
-		unhelp(h, me);
-	for (i = 0; i < nf_conntrack_htable_size; i++) {
-		list_for_each_entry(h, &nf_conntrack_hash[i], list)
-			unhelp(h, me);
-	}
-	write_unlock_bh(&nf_conntrack_lock);
-
-	/* Someone could be still looking at the helper in a bh. */
-	synchronize_net();
-}
-
 /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
 void __nf_ct_refresh_acct(struct nf_conn *ct,
 			  enum ip_conntrack_info ctinfo,
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
new file mode 100644
index 0000000..ca04487
--- /dev/null
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -0,0 +1,151 @@
+/* Helper handling for netfilter. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+static LIST_HEAD(helpers);
+
+struct nf_conntrack_helper *
+__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_helper *h;
+
+	list_for_each_entry(h, &helpers, list) {
+		if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
+			return h;
+	}
+	return NULL;
+}
+
+struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_helper *helper;
+
+	/* need nf_conntrack_lock to assure that helper exists until
+	 * try_module_get() is called */
+	read_lock_bh(&nf_conntrack_lock);
+
+	helper = __nf_ct_helper_find(tuple);
+	if (helper) {
+		/* need to increase module usage count to assure helper will
+		 * not go away while the caller is e.g. busy putting a
+		 * conntrack in the hash that uses the helper */
+		if (!try_module_get(helper->me))
+			helper = NULL;
+	}
+
+	read_unlock_bh(&nf_conntrack_lock);
+
+	return helper;
+}
+
+void nf_ct_helper_put(struct nf_conntrack_helper *helper)
+{
+	module_put(helper->me);
+}
+
+struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name)
+{
+	struct nf_conntrack_helper *h;
+
+	list_for_each_entry(h, &helpers, list) {
+		if (!strcmp(h->name, name))
+			return h;
+	}
+
+	return NULL;
+}
+
+static inline int unhelp(struct nf_conntrack_tuple_hash *i,
+			 const struct nf_conntrack_helper *me)
+{
+	struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
+	struct nf_conn_help *help = nfct_help(ct);
+
+	if (help && help->helper == me) {
+		nf_conntrack_event(IPCT_HELPER, ct);
+		help->helper = NULL;
+	}
+	return 0;
+}
+
+int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
+{
+	int ret;
+	BUG_ON(me->timeout == 0);
+
+	ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
+					  sizeof(struct nf_conn)
+					  + sizeof(struct nf_conn_help)
+					  + __alignof__(struct nf_conn_help));
+	if (ret < 0) {
+		printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n");
+		return ret;
+	}
+	write_lock_bh(&nf_conntrack_lock);
+	list_add(&me->list, &helpers);
+	write_unlock_bh(&nf_conntrack_lock);
+
+	return 0;
+}
+
+void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
+{
+	unsigned int i;
+	struct nf_conntrack_tuple_hash *h;
+	struct nf_conntrack_expect *exp, *tmp;
+
+	/* Need write lock here, to delete helper. */
+	write_lock_bh(&nf_conntrack_lock);
+	list_del(&me->list);
+
+	/* Get rid of expectations */
+	list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
+		struct nf_conn_help *help = nfct_help(exp->master);
+		if (help->helper == me && del_timer(&exp->timeout)) {
+			nf_ct_unlink_expect(exp);
+			nf_conntrack_expect_put(exp);
+		}
+	}
+
+	/* Get rid of expecteds, set helpers to NULL. */
+	list_for_each_entry(h, &unconfirmed, list)
+		unhelp(h, me);
+	for (i = 0; i < nf_conntrack_htable_size; i++) {
+		list_for_each_entry(h, &nf_conntrack_hash[i], list)
+			unhelp(h, me);
+	}
+	write_unlock_bh(&nf_conntrack_lock);
+
+	/* Someone could be still looking at the helper in a bh. */
+	synchronize_net();
+}

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 03/33]: nf_conntrack: split out the event cache
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 01/33]: nf_conntrack: split out expectation handling Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 02/33]: nf_conntrack: split out helper handling Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 04/33]: nf_conntrack: split out protocol handling Patrick McHardy
                   ` (30 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: split out the event cache

This patch splits out the event cache into its own file
nf_conntrack_ecache.c

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 7ac05737ce5e38dc88375e149281efa0afbcadb6
tree 14f5347c2c01920680372bf8a3bd41483d22d93e
parent 19dfaa08934591045aee3699c74e9deffbfd5587
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:12:51 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:12:51 +0100

 include/net/netfilter/nf_conntrack.h        |   81 -----------------------
 include/net/netfilter/nf_conntrack_core.h   |    1 
 include/net/netfilter/nf_conntrack_ecache.h |   95 +++++++++++++++++++++++++++
 net/netfilter/Makefile                      |    4 +
 net/netfilter/nf_conntrack_core.c           |   67 -------------------
 net/netfilter/nf_conntrack_ecache.c         |   91 ++++++++++++++++++++++++++
 net/netfilter/nf_conntrack_ftp.c            |    1 
 net/netfilter/nf_conntrack_proto_sctp.c     |    1 
 net/netfilter/nf_conntrack_proto_tcp.c      |    1 
 net/netfilter/nf_conntrack_proto_udp.c      |    2 +
 net/netfilter/nf_conntrack_standalone.c     |    2 -
 net/netfilter/xt_CONNMARK.c                 |    3 +
 12 files changed, 199 insertions(+), 150 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 9d2581f..9a29505 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -244,87 +244,6 @@ extern int nf_conntrack_checksum;
 
 #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++)
 
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-#include <net/netfilter/nf_conntrack_expect.h>
-
-struct nf_conntrack_ecache {
-	struct nf_conn *ct;
-	unsigned int events;
-};
-DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
-
-#define CONNTRACK_ECACHE(x)	(__get_cpu_var(nf_conntrack_ecache).x)
-
-extern struct atomic_notifier_head nf_conntrack_chain;
-extern struct atomic_notifier_head nf_conntrack_expect_chain;
-
-static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
-}
-
-static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
-}
-
-static inline int
-nf_conntrack_expect_register_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
-}
-
-static inline int
-nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain,
-			nb);
-}
-
-extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
-extern void __nf_ct_event_cache_init(struct nf_conn *ct);
-
-static inline void
-nf_conntrack_event_cache(enum ip_conntrack_events event,
-			 const struct sk_buff *skb)
-{
-	struct nf_conn *ct = (struct nf_conn *)skb->nfct;
-	struct nf_conntrack_ecache *ecache;
-
-	local_bh_disable();
-	ecache = &__get_cpu_var(nf_conntrack_ecache);
-	if (ct != ecache->ct)
-		__nf_ct_event_cache_init(ct);
-	ecache->events |= event;
-	local_bh_enable();
-}
-
-static inline void nf_conntrack_event(enum ip_conntrack_events event,
-				      struct nf_conn *ct)
-{
-	if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
-		atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
-}
-
-static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
-			  struct nf_conntrack_expect *exp)
-{
-	atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
-}
-#else /* CONFIG_NF_CONNTRACK_EVENTS */
-static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
-					    const struct sk_buff *skb) {}
-static inline void nf_conntrack_event(enum ip_conntrack_events event,
-				      struct nf_conn *ct) {}
-static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
-static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
-			  struct nf_conntrack_expect *exp) {}
-#endif /* CONFIG_NF_CONNTRACK_EVENTS */
-
 /* no helper, no nat */
 #define	NF_CT_F_BASIC	0
 /* for helper */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index bf8d300..4676b49 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -15,6 +15,7 @@ #define _NF_CONNTRACK_CORE_H
 #include <linux/netfilter.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 
 /* This header is used to share core functionality between the
    standalone connection tracking module, and the compatibility layer's use
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
new file mode 100644
index 0000000..b62a8a9
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -0,0 +1,95 @@
+/*
+ * connection tracking event cache.
+ */
+
+#ifndef _NF_CONNTRACK_ECACHE_H
+#define _NF_CONNTRACK_ECACHE_H
+#include <net/netfilter/nf_conntrack.h>
+
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+struct nf_conntrack_ecache {
+	struct nf_conn *ct;
+	unsigned int events;
+};
+DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+
+#define CONNTRACK_ECACHE(x)	(__get_cpu_var(nf_conntrack_ecache).x)
+
+extern struct atomic_notifier_head nf_conntrack_chain;
+extern struct atomic_notifier_head nf_conntrack_expect_chain;
+
+static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
+}
+
+static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
+}
+
+static inline int
+nf_conntrack_expect_register_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
+}
+
+static inline int
+nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain,
+			nb);
+}
+
+extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
+extern void __nf_ct_event_cache_init(struct nf_conn *ct);
+extern void nf_ct_event_cache_flush(void);
+
+static inline void
+nf_conntrack_event_cache(enum ip_conntrack_events event,
+			 const struct sk_buff *skb)
+{
+	struct nf_conn *ct = (struct nf_conn *)skb->nfct;
+	struct nf_conntrack_ecache *ecache;
+
+	local_bh_disable();
+	ecache = &__get_cpu_var(nf_conntrack_ecache);
+	if (ct != ecache->ct)
+		__nf_ct_event_cache_init(ct);
+	ecache->events |= event;
+	local_bh_enable();
+}
+
+static inline void nf_conntrack_event(enum ip_conntrack_events event,
+				      struct nf_conn *ct)
+{
+	if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
+		atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
+}
+
+static inline void
+nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
+			  struct nf_conntrack_expect *exp)
+{
+	atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+}
+
+#else /* CONFIG_NF_CONNTRACK_EVENTS */
+
+static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
+					    const struct sk_buff *skb) {}
+static inline void nf_conntrack_event(enum ip_conntrack_events event,
+				      struct nf_conn *ct) {}
+static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
+static inline void
+nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
+			  struct nf_conntrack_expect *exp) {}
+static inline void nf_ct_event_cache_flush(void) {}
+#endif /* CONFIG_NF_CONNTRACK_EVENTS */
+
+#endif /*_NF_CONNTRACK_ECACHE_H*/
+
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 2363764..fd0641d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,5 +1,7 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
-nf_conntrack-objs	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+
+nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index cf6face..029acc4 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -85,73 +85,6 @@ static int nf_conntrack_vmalloc __read_m
 
 static unsigned int nf_conntrack_next_id;
 
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
-
-DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
-
-/* deliver cached events and clear cache entry - must be called with locally
- * disabled softirqs */
-static inline void
-__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
-{
-	DEBUGP("ecache: delivering events for %p\n", ecache->ct);
-	if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
-	    && ecache->events)
-		atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
-				    ecache->ct);
-
-	ecache->events = 0;
-	nf_ct_put(ecache->ct);
-	ecache->ct = NULL;
-}
-
-/* Deliver all cached events for a particular conntrack. This is called
- * by code prior to async packet handling for freeing the skb */
-void nf_ct_deliver_cached_events(const struct nf_conn *ct)
-{
-	struct nf_conntrack_ecache *ecache;
-
-	local_bh_disable();
-	ecache = &__get_cpu_var(nf_conntrack_ecache);
-	if (ecache->ct == ct)
-		__nf_ct_deliver_cached_events(ecache);
-	local_bh_enable();
-}
-
-/* Deliver cached events for old pending events, if current conntrack != old */
-void __nf_ct_event_cache_init(struct nf_conn *ct)
-{
-	struct nf_conntrack_ecache *ecache;
-	
-	/* take care of delivering potentially old events */
-	ecache = &__get_cpu_var(nf_conntrack_ecache);
-	BUG_ON(ecache->ct == ct);
-	if (ecache->ct)
-		__nf_ct_deliver_cached_events(ecache);
-	/* initialize for this conntrack/packet */
-	ecache->ct = ct;
-	nf_conntrack_get(&ct->ct_general);
-}
-
-/* flush the event cache - touches other CPU's data and must not be called
- * while packets are still passing through the code */
-static void nf_ct_event_cache_flush(void)
-{
-	struct nf_conntrack_ecache *ecache;
-	int cpu;
-
-	for_each_possible_cpu(cpu) {
-		ecache = &per_cpu(nf_conntrack_ecache, cpu);
-		if (ecache->ct)
-			nf_ct_put(ecache->ct);
-	}
-}
-#else
-static inline void nf_ct_event_cache_flush(void) {}
-#endif /* CONFIG_NF_CONNTRACK_EVENTS */
-
 DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
 EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
 
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
new file mode 100644
index 0000000..35763e9
--- /dev/null
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -0,0 +1,91 @@
+/* Event cache for netfilter. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
+
+DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+
+/* deliver cached events and clear cache entry - must be called with locally
+ * disabled softirqs */
+static inline void
+__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
+{
+	if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
+	    && ecache->events)
+		atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
+				    ecache->ct);
+
+	ecache->events = 0;
+	nf_ct_put(ecache->ct);
+	ecache->ct = NULL;
+}
+
+/* Deliver all cached events for a particular conntrack. This is called
+ * by code prior to async packet handling for freeing the skb */
+void nf_ct_deliver_cached_events(const struct nf_conn *ct)
+{
+	struct nf_conntrack_ecache *ecache;
+
+	local_bh_disable();
+	ecache = &__get_cpu_var(nf_conntrack_ecache);
+	if (ecache->ct == ct)
+		__nf_ct_deliver_cached_events(ecache);
+	local_bh_enable();
+}
+
+/* Deliver cached events for old pending events, if current conntrack != old */
+void __nf_ct_event_cache_init(struct nf_conn *ct)
+{
+	struct nf_conntrack_ecache *ecache;
+
+	/* take care of delivering potentially old events */
+	ecache = &__get_cpu_var(nf_conntrack_ecache);
+	BUG_ON(ecache->ct == ct);
+	if (ecache->ct)
+		__nf_ct_deliver_cached_events(ecache);
+	/* initialize for this conntrack/packet */
+	ecache->ct = ct;
+	nf_conntrack_get(&ct->ct_general);
+}
+
+/* flush the event cache - touches other CPU's data and must not be called
+ * while packets are still passing through the code */
+void nf_ct_event_cache_flush(void)
+{
+	struct nf_conntrack_ecache *ecache;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		ecache = &per_cpu(nf_conntrack_ecache, cpu);
+		if (ecache->ct)
+			nf_ct_put(ecache->ct);
+	}
+}
+
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 503fabf..10836fc 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -27,6 +27,7 @@ #include <net/tcp.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <linux/netfilter/nf_conntrack_ftp.h>
 
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index af56877..ba3e31f 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -33,6 +33,7 @@ #include <linux/interrupt.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 
 #if 0
 #define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 238bbb5..e6b6f23 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -43,6 +43,7 @@ #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 
 #if 0
 #define DEBUGP printk
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index d28981c..cf9db03 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -22,10 +22,12 @@ #include <linux/skbuff.h>
 #include <linux/ipv6.h>
 #include <net/ip6_checksum.h>
 #include <net/checksum.h>
+
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 
 unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
 unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 72643d3..73ca156 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -33,9 +33,9 @@ #define ASSERT_READ_LOCK(x)
 #define ASSERT_WRITE_LOCK(x)
 
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
-#include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 67ed531..b554823 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -31,6 +31,9 @@ MODULE_ALIAS("ipt_CONNMARK");
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_CONNMARK.h>
 #include <net/netfilter/nf_conntrack_compat.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack_ecache.h>
+#endif
 
 static unsigned int
 target(struct sk_buff **pskb,

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 04/33]: nf_conntrack: split out protocol handling
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (2 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 03/33]: nf_conntrack: split out the event cache Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 05/33]: More __read_mostly annotations Patrick McHardy
                   ` (29 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: split out protocol handling

This patch splits out L3/L4 protocol handling into its own file
nf_conntrack_proto.c

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit d27a49059250fc2676533e533fcbe77de3b8b112
tree d01bb6048cd687fe9351cb09da75ea007b2fbd76
parent 7ac05737ce5e38dc88375e149281efa0afbcadb6
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:12:54 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:12:54 +0100

 net/netfilter/Makefile                  |    2 
 net/netfilter/nf_conntrack_core.c       |   81 -----------
 net/netfilter/nf_conntrack_proto.c      |  225 +++++++++++++++++++++++++++++++
 net/netfilter/nf_conntrack_standalone.c |  116 ----------------
 4 files changed, 226 insertions(+), 198 deletions(-)

diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index fd0641d..627105d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,6 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
 
-nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 029acc4..09c0e63 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -73,8 +73,6 @@ DEFINE_RWLOCK(nf_conntrack_lock);
 atomic_t nf_conntrack_count = ATOMIC_INIT(0);
 
 void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
-struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
-struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
 unsigned int nf_conntrack_htable_size __read_mostly = 0;
 int nf_conntrack_max __read_mostly;
 struct list_head *nf_conntrack_hash __read_mostly;
@@ -115,85 +113,6 @@ DEFINE_RWLOCK(nf_ct_cache_lock);
 /* This avoids calling kmem_cache_create() with same name simultaneously */
 static DEFINE_MUTEX(nf_ct_cache_mutex);
 
-extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
-struct nf_conntrack_protocol *
-__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
-{
-	if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
-		return &nf_conntrack_generic_protocol;
-
-	return nf_ct_protos[l3proto][protocol];
-}
-
-/* this is guaranteed to always return a valid protocol helper, since
- * it falls back to generic_protocol */
-struct nf_conntrack_protocol *
-nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
-{
-	struct nf_conntrack_protocol *p;
-
-	preempt_disable();
-	p = __nf_ct_proto_find(l3proto, protocol);
-	if (!try_module_get(p->me))
-		p = &nf_conntrack_generic_protocol;
-	preempt_enable();
-	
-	return p;
-}
-
-void nf_ct_proto_put(struct nf_conntrack_protocol *p)
-{
-	module_put(p->me);
-}
-
-struct nf_conntrack_l3proto *
-nf_ct_l3proto_find_get(u_int16_t l3proto)
-{
-	struct nf_conntrack_l3proto *p;
-
-	preempt_disable();
-	p = __nf_ct_l3proto_find(l3proto);
-	if (!try_module_get(p->me))
-		p = &nf_conntrack_generic_l3proto;
-	preempt_enable();
-
-	return p;
-}
-
-void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
-{
-	module_put(p->me);
-}
-
-int
-nf_ct_l3proto_try_module_get(unsigned short l3proto)
-{
-	int ret;
-	struct nf_conntrack_l3proto *p;
-
-retry:	p = nf_ct_l3proto_find_get(l3proto);
-	if (p == &nf_conntrack_generic_l3proto) {
-		ret = request_module("nf_conntrack-%d", l3proto);
-		if (!ret)
-			goto retry;
-
-		return -EPROTOTYPE;
-	}
-
-	return 0;
-}
-
-void nf_ct_l3proto_module_put(unsigned short l3proto)
-{
-	struct nf_conntrack_l3proto *p;
-
-	preempt_disable();
-	p = __nf_ct_l3proto_find(l3proto);
-	preempt_enable();
-
-	module_put(p->me);
-}
-
 static int nf_conntrack_hash_rnd_initted;
 static unsigned int nf_conntrack_hash_rnd;
 
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
new file mode 100644
index 0000000..24c61a3
--- /dev/null
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -0,0 +1,225 @@
+/* L3/L4 protocol support for nf_conntrack. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/moduleparam.h>
+#include <linux/notifier.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
+struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
+
+struct nf_conntrack_protocol *
+__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
+{
+	if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
+		return &nf_conntrack_generic_protocol;
+
+	return nf_ct_protos[l3proto][protocol];
+}
+
+/* this is guaranteed to always return a valid protocol helper, since
+ * it falls back to generic_protocol */
+struct nf_conntrack_protocol *
+nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
+{
+	struct nf_conntrack_protocol *p;
+
+	preempt_disable();
+	p = __nf_ct_proto_find(l3proto, protocol);
+	if (!try_module_get(p->me))
+		p = &nf_conntrack_generic_protocol;
+	preempt_enable();
+
+	return p;
+}
+
+void nf_ct_proto_put(struct nf_conntrack_protocol *p)
+{
+	module_put(p->me);
+}
+
+struct nf_conntrack_l3proto *
+nf_ct_l3proto_find_get(u_int16_t l3proto)
+{
+	struct nf_conntrack_l3proto *p;
+
+	preempt_disable();
+	p = __nf_ct_l3proto_find(l3proto);
+	if (!try_module_get(p->me))
+		p = &nf_conntrack_generic_l3proto;
+	preempt_enable();
+
+	return p;
+}
+
+void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
+{
+	module_put(p->me);
+}
+
+int
+nf_ct_l3proto_try_module_get(unsigned short l3proto)
+{
+	int ret;
+	struct nf_conntrack_l3proto *p;
+
+retry:	p = nf_ct_l3proto_find_get(l3proto);
+	if (p == &nf_conntrack_generic_l3proto) {
+		ret = request_module("nf_conntrack-%d", l3proto);
+		if (!ret)
+			goto retry;
+
+		return -EPROTOTYPE;
+	}
+
+	return 0;
+}
+
+void nf_ct_l3proto_module_put(unsigned short l3proto)
+{
+	struct nf_conntrack_l3proto *p;
+
+	preempt_disable();
+	p = __nf_ct_l3proto_find(l3proto);
+	preempt_enable();
+
+	module_put(p->me);
+}
+
+static int kill_l3proto(struct nf_conn *i, void *data)
+{
+	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+			((struct nf_conntrack_l3proto *)data)->l3proto);
+}
+
+static int kill_proto(struct nf_conn *i, void *data)
+{
+	struct nf_conntrack_protocol *proto;
+	proto = (struct nf_conntrack_protocol *)data;
+	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
+			proto->proto) &&
+	       (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+			proto->l3proto);
+}
+
+int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
+{
+	int ret = 0;
+
+	write_lock_bh(&nf_conntrack_lock);
+	if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) {
+		ret = -EBUSY;
+		goto out;
+	}
+	nf_ct_l3protos[proto->l3proto] = proto;
+out:
+	write_unlock_bh(&nf_conntrack_lock);
+
+	return ret;
+}
+
+void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
+{
+	write_lock_bh(&nf_conntrack_lock);
+	nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto;
+	write_unlock_bh(&nf_conntrack_lock);
+
+	/* Somebody could be still looking at the proto in bh. */
+	synchronize_net();
+
+	/* Remove all contrack entries for this protocol */
+	nf_ct_iterate_cleanup(kill_l3proto, proto);
+}
+
+/* FIXME: Allow NULL functions and sub in pointers to generic for
+   them. --RR */
+int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto)
+{
+	int ret = 0;
+
+retry:
+	write_lock_bh(&nf_conntrack_lock);
+	if (nf_ct_protos[proto->l3proto]) {
+		if (nf_ct_protos[proto->l3proto][proto->proto]
+				!= &nf_conntrack_generic_protocol) {
+			ret = -EBUSY;
+			goto out_unlock;
+		}
+	} else {
+		/* l3proto may be loaded latter. */
+		struct nf_conntrack_protocol **proto_array;
+		int i;
+
+		write_unlock_bh(&nf_conntrack_lock);
+
+		proto_array = (struct nf_conntrack_protocol **)
+				kmalloc(MAX_NF_CT_PROTO *
+					 sizeof(struct nf_conntrack_protocol *),
+					GFP_KERNEL);
+		if (proto_array == NULL) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		for (i = 0; i < MAX_NF_CT_PROTO; i++)
+			proto_array[i] = &nf_conntrack_generic_protocol;
+
+		write_lock_bh(&nf_conntrack_lock);
+		if (nf_ct_protos[proto->l3proto]) {
+			/* bad timing, but no problem */
+			write_unlock_bh(&nf_conntrack_lock);
+			kfree(proto_array);
+		} else {
+			nf_ct_protos[proto->l3proto] = proto_array;
+			write_unlock_bh(&nf_conntrack_lock);
+		}
+
+		/*
+		 * Just once because array is never freed until unloading
+		 * nf_conntrack.ko
+		 */
+		goto retry;
+	}
+
+	nf_ct_protos[proto->l3proto][proto->proto] = proto;
+
+out_unlock:
+	write_unlock_bh(&nf_conntrack_lock);
+out:
+	return ret;
+}
+
+void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
+{
+	write_lock_bh(&nf_conntrack_lock);
+	nf_ct_protos[proto->l3proto][proto->proto]
+		= &nf_conntrack_generic_protocol;
+	write_unlock_bh(&nf_conntrack_lock);
+
+	/* Somebody could be still looking at the proto in bh. */
+	synchronize_net();
+
+	/* Remove all contrack entries for this protocol */
+	nf_ct_iterate_cleanup(kill_proto, proto);
+}
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 73ca156..eb031d2 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -50,22 +50,6 @@ MODULE_LICENSE("GPL");
 extern atomic_t nf_conntrack_count;
 DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
 
-static int kill_l3proto(struct nf_conn *i, void *data)
-{
-	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == 
-			((struct nf_conntrack_l3proto *)data)->l3proto);
-}
-
-static int kill_proto(struct nf_conn *i, void *data)
-{
-	struct nf_conntrack_protocol *proto;
-	proto = (struct nf_conntrack_protocol *)data;
-	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
-			proto->proto) &&
-	       (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
-			proto->l3proto);
-}
-
 #ifdef CONFIG_PROC_FS
 int
 print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
@@ -585,106 +569,6 @@ static ctl_table nf_ct_net_table[] = {
 EXPORT_SYMBOL(nf_ct_log_invalid);
 #endif /* CONFIG_SYSCTL */
 
-int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
-{
-	int ret = 0;
-
-	write_lock_bh(&nf_conntrack_lock);
-	if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) {
-		ret = -EBUSY;
-		goto out;
-	}
-	nf_ct_l3protos[proto->l3proto] = proto;
-out:
-	write_unlock_bh(&nf_conntrack_lock);
-
-	return ret;
-}
-
-void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
-{
-	write_lock_bh(&nf_conntrack_lock);
-	nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto;
-	write_unlock_bh(&nf_conntrack_lock);
-	
-	/* Somebody could be still looking at the proto in bh. */
-	synchronize_net();
-
-	/* Remove all contrack entries for this protocol */
-	nf_ct_iterate_cleanup(kill_l3proto, proto);
-}
-
-/* FIXME: Allow NULL functions and sub in pointers to generic for
-   them. --RR */
-int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto)
-{
-	int ret = 0;
-
-retry:
-	write_lock_bh(&nf_conntrack_lock);
-	if (nf_ct_protos[proto->l3proto]) {
-		if (nf_ct_protos[proto->l3proto][proto->proto]
-				!= &nf_conntrack_generic_protocol) {
-			ret = -EBUSY;
-			goto out_unlock;
-		}
-	} else {
-		/* l3proto may be loaded latter. */
-		struct nf_conntrack_protocol **proto_array;
-		int i;
-
-		write_unlock_bh(&nf_conntrack_lock);
-
-		proto_array = (struct nf_conntrack_protocol **)
-				kmalloc(MAX_NF_CT_PROTO *
-					 sizeof(struct nf_conntrack_protocol *),
-					GFP_KERNEL);
-		if (proto_array == NULL) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		for (i = 0; i < MAX_NF_CT_PROTO; i++)
-			proto_array[i] = &nf_conntrack_generic_protocol;
-
-		write_lock_bh(&nf_conntrack_lock);
-		if (nf_ct_protos[proto->l3proto]) {
-			/* bad timing, but no problem */
-			write_unlock_bh(&nf_conntrack_lock);
-			kfree(proto_array);
-		} else {
-			nf_ct_protos[proto->l3proto] = proto_array;
-			write_unlock_bh(&nf_conntrack_lock);
-		}
-
-		/*
-		 * Just once because array is never freed until unloading
-		 * nf_conntrack.ko
-		 */
-		goto retry;
-	}
-
-	nf_ct_protos[proto->l3proto][proto->proto] = proto;
-
-out_unlock:
-	write_unlock_bh(&nf_conntrack_lock);
-out:
-	return ret;
-}
-
-void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
-{
-	write_lock_bh(&nf_conntrack_lock);
-	nf_ct_protos[proto->l3proto][proto->proto]
-		= &nf_conntrack_generic_protocol;
-	write_unlock_bh(&nf_conntrack_lock);
-	
-	/* Somebody could be still looking at the proto in bh. */
-	synchronize_net();
-
-	/* Remove all contrack entries for this protocol */
-	nf_ct_iterate_cleanup(kill_proto, proto);
-}
-
 static int __init nf_conntrack_standalone_init(void)
 {
 #ifdef CONFIG_PROC_FS

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 05/33]: More __read_mostly annotations
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (3 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 04/33]: nf_conntrack: split out protocol handling Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 06/33]: nf_conntrack: rename struct nf_conntrack_protocol Patrick McHardy
                   ` (28 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: More __read_mostly annotations

Place rarely written variables in the read-mostly section by using
__read_mostly

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit aa38f56fd93eda7cab344eb237951108eff1b3bc
tree e4727b1eeac5a5f86e3e867e8b47aa9228ea9d38
parent d27a49059250fc2676533e533fcbe77de3b8b112
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:12:56 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:12:56 +0100

 net/netfilter/core.c                |    4 ++--
 net/netfilter/nf_conntrack_core.c   |    4 ++--
 net/netfilter/nf_conntrack_helper.c |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 17f9e1c..291b8c6 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -28,7 +28,7 @@ #include "nf_internals.h"
 
 static DEFINE_SPINLOCK(afinfo_lock);
 
-struct nf_afinfo *nf_afinfo[NPROTO];
+struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly;
 EXPORT_SYMBOL(nf_afinfo);
 
 int nf_register_afinfo(struct nf_afinfo *afinfo)
@@ -54,7 +54,7 @@ EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
  * of skbuffs queued for userspace, and not deregister a hook unless
  * this is zero, but that sucks.  Now, we simply check when the
  * packets come back: if the hook is gone, the packet is discarded. */
-struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
+struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;
 EXPORT_SYMBOL(nf_hooks);
 static DEFINE_SPINLOCK(nf_hook_lock);
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 09c0e63..6607ed4 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -73,10 +73,10 @@ DEFINE_RWLOCK(nf_conntrack_lock);
 atomic_t nf_conntrack_count = ATOMIC_INIT(0);
 
 void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
-unsigned int nf_conntrack_htable_size __read_mostly = 0;
+unsigned int nf_conntrack_htable_size __read_mostly;
 int nf_conntrack_max __read_mostly;
 struct list_head *nf_conntrack_hash __read_mostly;
-struct nf_conn nf_conntrack_untracked;
+struct nf_conn nf_conntrack_untracked __read_mostly;
 unsigned int nf_ct_log_invalid __read_mostly;
 LIST_HEAD(unconfirmed);
 static int nf_conntrack_vmalloc __read_mostly;
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index ca04487..2af9220 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -30,7 +30,7 @@ #include <net/netfilter/nf_conntrack_pro
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
-static LIST_HEAD(helpers);
+static __read_mostly LIST_HEAD(helpers);
 
 struct nf_conntrack_helper *
 __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 06/33]: nf_conntrack: rename struct nf_conntrack_protocol
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (4 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 05/33]: More __read_mostly annotations Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 07/33]: nf_conntrack: more sanity checks in protocol registration/unregistration Patrick McHardy
                   ` (27 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: rename struct nf_conntrack_protocol

Rename 'struct nf_conntrack_protocol' to 'struct nf_conntrack_l4proto' in
order to help distinguish it from 'struct nf_conntrack_l3proto'. It gets
rather confusing with 'nf_conntrack_protocol'.

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 1ef0a3824fdd09eeeaaf25e9d50165dfbaa88ad0
tree 82ccba6bd2554c3ebae001c47efa1a5bb3f0aa5e
parent aa38f56fd93eda7cab344eb237951108eff1b3bc
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:12:58 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:57:03 +0100

 include/net/netfilter/nf_conntrack_core.h      |   10 +-
 include/net/netfilter/nf_conntrack_l3proto.h   |    4 -
 include/net/netfilter/nf_conntrack_l4proto.h   |  129 ++++++++++++++++++++++++
 include/net/netfilter/nf_conntrack_protocol.h  |  129 ------------------------
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |   26 ++---
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c   |   12 +-
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   26 ++---
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c |   12 +-
 net/netfilter/nf_conntrack_core.c              |   46 ++++-----
 net/netfilter/nf_conntrack_ecache.c            |    2 
 net/netfilter/nf_conntrack_expect.c            |    2 
 net/netfilter/nf_conntrack_helper.c            |    2 
 net/netfilter/nf_conntrack_l3proto_generic.c   |    4 -
 net/netfilter/nf_conntrack_netlink.c           |   56 +++++-----
 net/netfilter/nf_conntrack_proto.c             |   72 +++++++------
 net/netfilter/nf_conntrack_proto_generic.c     |    6 +
 net/netfilter/nf_conntrack_proto_sctp.c        |   26 ++---
 net/netfilter/nf_conntrack_proto_tcp.c         |   14 +--
 net/netfilter/nf_conntrack_proto_udp.c         |   14 +--
 net/netfilter/nf_conntrack_standalone.c        |   30 +++---
 20 files changed, 311 insertions(+), 311 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 4676b49..7fdc72c 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -14,7 +14,7 @@ #define _NF_CONNTRACK_CORE_H
 
 #include <linux/netfilter.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
 /* This header is used to share core functionality between the
@@ -32,7 +32,7 @@ extern struct nf_conntrack_l3proto *nf_c
 /* Like above, but you already have conntrack read lock. */
 extern struct nf_conntrack_l3proto *__nf_ct_find_l3proto(u_int16_t l3proto);
 
-struct nf_conntrack_protocol;
+struct nf_conntrack_l4proto;
 
 extern int
 nf_ct_get_tuple(const struct sk_buff *skb,
@@ -42,13 +42,13 @@ nf_ct_get_tuple(const struct sk_buff *sk
 		u_int8_t protonum,
 		struct nf_conntrack_tuple *tuple,
 		const struct nf_conntrack_l3proto *l3proto,
-		const struct nf_conntrack_protocol *protocol);
+		const struct nf_conntrack_l4proto *l4proto);
 
 extern int
 nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
 		   const struct nf_conntrack_tuple *orig,
 		   const struct nf_conntrack_l3proto *l3proto,
-		   const struct nf_conntrack_protocol *protocol);
+		   const struct nf_conntrack_l4proto *l4proto);
 
 /* Find a connection corresponding to a tuple. */
 extern struct nf_conntrack_tuple_hash *
@@ -76,7 +76,7 @@ extern void __nf_conntrack_attach(struct
 int
 print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
 	    struct nf_conntrack_l3proto *l3proto,
-	    struct nf_conntrack_protocol *proto);
+	    struct nf_conntrack_l4proto *proto);
 
 extern struct list_head *nf_conntrack_hash;
 extern struct list_head nf_conntrack_expect_list;
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index dac43b1..ffe23a1 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -96,13 +96,13 @@ extern void nf_ct_l3proto_put(struct nf_
 /* Existing built-in protocols */
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
-extern struct nf_conntrack_l3proto nf_conntrack_generic_l3proto;
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
 
 static inline struct nf_conntrack_l3proto *
 __nf_ct_l3proto_find(u_int16_t l3proto)
 {
 	if (unlikely(l3proto >= AF_MAX))
-		return &nf_conntrack_generic_l3proto;
+		return &nf_conntrack_l3proto_generic;
 	return nf_ct_l3protos[l3proto];
 }
 
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
new file mode 100644
index 0000000..0c6babd
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -0,0 +1,129 @@
+/*
+ * Header for use in defining a given L4 protocol for connection tracking.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ *	- generalized L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h
+ */
+
+#ifndef _NF_CONNTRACK_L4PROTO_H
+#define _NF_CONNTRACK_L4PROTO_H
+#include <net/netfilter/nf_conntrack.h>
+
+struct seq_file;
+struct nfattr;
+
+struct nf_conntrack_l4proto
+{
+	/* Next pointer. */
+	struct list_head list;
+
+	/* L3 Protocol number. */
+	u_int16_t l3proto;
+
+	/* L4 Protocol number. */
+	u_int8_t l4proto;
+
+	/* Protocol name */
+	const char *name;
+
+	/* Try to fill in the third arg: dataoff is offset past network protocol
+           hdr.  Return true if possible. */
+	int (*pkt_to_tuple)(const struct sk_buff *skb,
+			    unsigned int dataoff,
+			    struct nf_conntrack_tuple *tuple);
+
+	/* Invert the per-proto part of the tuple: ie. turn xmit into reply.
+	 * Some packets can't be inverted: return 0 in that case.
+	 */
+	int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+			    const struct nf_conntrack_tuple *orig);
+
+	/* Print out the per-protocol part of the tuple. Return like seq_* */
+	int (*print_tuple)(struct seq_file *s,
+			   const struct nf_conntrack_tuple *);
+
+	/* Print out the private part of the conntrack. */
+	int (*print_conntrack)(struct seq_file *s, const struct nf_conn *);
+
+	/* Returns verdict for packet, or -1 for invalid. */
+	int (*packet)(struct nf_conn *conntrack,
+		      const struct sk_buff *skb,
+		      unsigned int dataoff,
+		      enum ip_conntrack_info ctinfo,
+		      int pf,
+		      unsigned int hooknum);
+
+	/* Called when a new connection for this protocol found;
+	 * returns TRUE if it's OK.  If so, packet() called next. */
+	int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb,
+		   unsigned int dataoff);
+
+	/* Called when a conntrack entry is destroyed */
+	void (*destroy)(struct nf_conn *conntrack);
+
+	int (*error)(struct sk_buff *skb, unsigned int dataoff,
+		     enum ip_conntrack_info *ctinfo,
+		     int pf, unsigned int hooknum);
+
+	/* convert protoinfo to nfnetink attributes */
+	int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
+			 const struct nf_conn *ct);
+
+	/* convert nfnetlink attributes to protoinfo */
+	int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
+
+	int (*tuple_to_nfattr)(struct sk_buff *skb,
+			       const struct nf_conntrack_tuple *t);
+	int (*nfattr_to_tuple)(struct nfattr *tb[],
+			       struct nf_conntrack_tuple *t);
+
+	/* Module (if any) which this is connected to. */
+	struct module *me;
+};
+
+/* Existing built-in protocols */
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
+
+#define MAX_NF_CT_PROTO 256
+extern struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX];
+
+extern struct nf_conntrack_l4proto *
+__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto);
+
+extern struct nf_conntrack_l4proto *
+nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t protocol);
+
+extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
+
+/* Protocol registration. */
+extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
+extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+
+/* Generic netlink helpers */
+extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
+				      const struct nf_conntrack_tuple *tuple);
+extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+				      struct nf_conntrack_tuple *t);
+
+/* Log invalid packets */
+extern unsigned int nf_ct_log_invalid;
+
+#ifdef CONFIG_SYSCTL
+#ifdef DEBUG_INVALID_PACKETS
+#define LOG_INVALID(proto) \
+	(nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW)
+#else
+#define LOG_INVALID(proto) \
+	((nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) \
+	 && net_ratelimit())
+#endif
+#else
+#define LOG_INVALID(proto) 0
+#endif /* CONFIG_SYSCTL */
+
+#endif /*_NF_CONNTRACK_PROTOCOL_H*/
diff --git a/include/net/netfilter/nf_conntrack_protocol.h b/include/net/netfilter/nf_conntrack_protocol.h
deleted file mode 100644
index 1f33737..0000000
--- a/include/net/netfilter/nf_conntrack_protocol.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Header for use in defining a given protocol for connection tracking.
- *
- * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
- *	- generalized L3 protocol dependent part.
- *
- * Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h
- */
-
-#ifndef _NF_CONNTRACK_PROTOCOL_H
-#define _NF_CONNTRACK_PROTOCOL_H
-#include <net/netfilter/nf_conntrack.h>
-
-struct seq_file;
-struct nfattr;
-
-struct nf_conntrack_protocol
-{
-	/* Next pointer. */
-	struct list_head list;
-
-	/* L3 Protocol number. */
-	u_int16_t l3proto;
-
-	/* Protocol number. */
-	u_int8_t proto;
-
-	/* Protocol name */
-	const char *name;
-
-	/* Try to fill in the third arg: dataoff is offset past network protocol
-           hdr.  Return true if possible. */
-	int (*pkt_to_tuple)(const struct sk_buff *skb,
-			    unsigned int dataoff,
-			    struct nf_conntrack_tuple *tuple);
-
-	/* Invert the per-proto part of the tuple: ie. turn xmit into reply.
-	 * Some packets can't be inverted: return 0 in that case.
-	 */
-	int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
-			    const struct nf_conntrack_tuple *orig);
-
-	/* Print out the per-protocol part of the tuple. Return like seq_* */
-	int (*print_tuple)(struct seq_file *s,
-			   const struct nf_conntrack_tuple *);
-
-	/* Print out the private part of the conntrack. */
-	int (*print_conntrack)(struct seq_file *s, const struct nf_conn *);
-
-	/* Returns verdict for packet, or -1 for invalid. */
-	int (*packet)(struct nf_conn *conntrack,
-		      const struct sk_buff *skb,
-		      unsigned int dataoff,
-		      enum ip_conntrack_info ctinfo,
-		      int pf,
-		      unsigned int hooknum);
-
-	/* Called when a new connection for this protocol found;
-	 * returns TRUE if it's OK.  If so, packet() called next. */
-	int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb,
-		   unsigned int dataoff);
-
-	/* Called when a conntrack entry is destroyed */
-	void (*destroy)(struct nf_conn *conntrack);
-
-	int (*error)(struct sk_buff *skb, unsigned int dataoff,
-		     enum ip_conntrack_info *ctinfo,
-		     int pf, unsigned int hooknum);
-
-	/* convert protoinfo to nfnetink attributes */
-	int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
-			 const struct nf_conn *ct);
-
-	/* convert nfnetlink attributes to protoinfo */
-	int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
-
-	int (*tuple_to_nfattr)(struct sk_buff *skb,
-			       const struct nf_conntrack_tuple *t);
-	int (*nfattr_to_tuple)(struct nfattr *tb[],
-			       struct nf_conntrack_tuple *t);
-
-	/* Module (if any) which this is connected to. */
-	struct module *me;
-};
-
-/* Existing built-in protocols */
-extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
-extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
-
-#define MAX_NF_CT_PROTO 256
-extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
-
-extern struct nf_conntrack_protocol *
-__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol);
-
-extern struct nf_conntrack_protocol *
-nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol);
-
-extern void nf_ct_proto_put(struct nf_conntrack_protocol *p);
-
-/* Protocol registration. */
-extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
-extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
-
-/* Generic netlink helpers */
-extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
-				      const struct nf_conntrack_tuple *tuple);
-extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
-				      struct nf_conntrack_tuple *t);
-
-/* Log invalid packets */
-extern unsigned int nf_ct_log_invalid;
-
-#ifdef CONFIG_SYSCTL
-#ifdef DEBUG_INVALID_PACKETS
-#define LOG_INVALID(proto) \
-	(nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW)
-#else
-#define LOG_INVALID(proto) \
-	((nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) \
-	 && net_ratelimit())
-#endif
-#else
-#define LOG_INVALID(proto) 0
-#endif /* CONFIG_SYSCTL */
-
-#endif /*_NF_CONNTRACK_PROTOCOL_H*/
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 0af803d..370df0f 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -27,7 +27,7 @@ #include <net/ip.h>
 #include <linux/netfilter_ipv4.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
@@ -429,9 +429,9 @@ #endif
 	.me		 = THIS_MODULE,
 };
 
-extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
 
 MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
 MODULE_LICENSE("GPL");
@@ -448,19 +448,19 @@ static int __init nf_conntrack_l3proto_i
 		return ret;
 	}
 
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv4: can't register tcp.\n");
 		goto cleanup_sockopt;
 	}
 
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp4);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv4: can't register udp.\n");
 		goto cleanup_tcp;
 	}
 
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmp);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv4: can't register icmp.\n");
 		goto cleanup_udp;
@@ -495,11 +495,11 @@ #endif
  cleanup_ipv4:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
  cleanup_icmp:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
  cleanup_udp:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
  cleanup_tcp:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
  cleanup_sockopt:
 	nf_unregister_sockopt(&so_getorigdst);
 	return ret;
@@ -513,9 +513,9 @@ #ifdef CONFIG_SYSCTL
 #endif
 	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
 	nf_unregister_sockopt(&so_getorigdst);
 }
 
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 790f00d..08223a5 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -22,7 +22,7 @@ #include <net/ip.h>
 #include <net/checksum.h>
 #include <linux/netfilter_ipv4.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
 unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
@@ -152,7 +152,7 @@ icmp_error_message(struct sk_buff *skb,
 		struct icmphdr icmp;
 		struct iphdr ip;
 	} _in, *inside;
-	struct nf_conntrack_protocol *innerproto;
+	struct nf_conntrack_l4proto *innerproto;
 	struct nf_conntrack_tuple_hash *h;
 	int dataoff;
 
@@ -170,7 +170,7 @@ icmp_error_message(struct sk_buff *skb,
 		return -NF_ACCEPT;
 	}
 
-	innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol);
+	innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
 	dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
 	/* Are they talking about one of our connections? */
 	if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
@@ -321,11 +321,11 @@ static int icmp_nfattr_to_tuple(struct n
 }
 #endif
 
-struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
 {
 	.list			= { NULL, NULL },
 	.l3proto		= PF_INET,
-	.proto			= IPPROTO_ICMP,
+	.l4proto		= IPPROTO_ICMP,
 	.name			= "icmp",
 	.pkt_to_tuple		= icmp_pkt_to_tuple,
 	.invert_tuple		= icmp_invert_tuple,
@@ -343,4 +343,4 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 #endif
 };
 
-EXPORT_SYMBOL(nf_conntrack_protocol_icmp);
+EXPORT_SYMBOL(nf_conntrack_l4proto_icmp);
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index e5e53ff..cdbba44 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -33,7 +33,7 @@ #include <net/ipv6.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
@@ -458,9 +458,9 @@ #endif
 	.me			= THIS_MODULE,
 };
 
-extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
-extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
 extern int nf_ct_frag6_init(void);
 extern void nf_ct_frag6_cleanup(void);
 
@@ -479,19 +479,19 @@ static int __init nf_conntrack_l3proto_i
 		printk("nf_conntrack_ipv6: can't initialize frag6.\n");
 		return ret;
 	}
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv6: can't register tcp.\n");
 		goto cleanup_frag6;
 	}
 
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp6);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv6: can't register udp.\n");
 		goto cleanup_tcp;
 	}
 
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmpv6);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv6: can't register icmpv6.\n");
 		goto cleanup_udp;
@@ -527,11 +527,11 @@ #endif
  cleanup_ipv6:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
  cleanup_icmpv6:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
  cleanup_udp:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
  cleanup_tcp:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
  cleanup_frag6:
 	nf_ct_frag6_cleanup();
 	return ret;
@@ -545,9 +545,9 @@ #ifdef CONFIG_SYSCTL
 #endif
 	nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
 	nf_ct_frag6_cleanup();
 }
 
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 34d4472..2cdf225 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -29,7 +29,7 @@ #include <net/ip6_checksum.h>
 #include <linux/seq_file.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
 
@@ -155,7 +155,7 @@ icmpv6_error_message(struct sk_buff *skb
 	struct nf_conntrack_tuple_hash *h;
 	struct icmp6hdr _hdr, *hp;
 	unsigned int inip6off;
-	struct nf_conntrack_protocol *inproto;
+	struct nf_conntrack_l4proto *inproto;
 	u_int8_t inprotonum;
 	unsigned int inprotoff;
 
@@ -185,7 +185,7 @@ icmpv6_error_message(struct sk_buff *skb
 		return -NF_ACCEPT;
 	}
 
-	inproto = __nf_ct_proto_find(PF_INET6, inprotonum);
+	inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum);
 
 	/* Are they talking about one of our connections? */
 	if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
@@ -301,10 +301,10 @@ static int icmpv6_nfattr_to_tuple(struct
 }
 #endif
 
-struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
 {
 	.l3proto		= PF_INET6,
-	.proto			= IPPROTO_ICMPV6,
+	.l4proto		= IPPROTO_ICMPV6,
 	.name			= "icmpv6",
 	.pkt_to_tuple		= icmpv6_pkt_to_tuple,
 	.invert_tuple		= icmpv6_invert_tuple,
@@ -320,4 +320,4 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 #endif
 };
 
-EXPORT_SYMBOL(nf_conntrack_protocol_icmpv6);
+EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 6607ed4..441a647 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -54,7 +54,7 @@ #define ASSERT_WRITE_LOCK(x)
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
@@ -256,7 +256,7 @@ nf_ct_get_tuple(const struct sk_buff *sk
 		u_int8_t protonum,
 		struct nf_conntrack_tuple *tuple,
 		const struct nf_conntrack_l3proto *l3proto,
-		const struct nf_conntrack_protocol *protocol)
+		const struct nf_conntrack_l4proto *l4proto)
 {
 	NF_CT_TUPLE_U_BLANK(tuple);
 
@@ -267,14 +267,14 @@ nf_ct_get_tuple(const struct sk_buff *sk
 	tuple->dst.protonum = protonum;
 	tuple->dst.dir = IP_CT_DIR_ORIGINAL;
 
-	return protocol->pkt_to_tuple(skb, dataoff, tuple);
+	return l4proto->pkt_to_tuple(skb, dataoff, tuple);
 }
 
 int
 nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
 		   const struct nf_conntrack_tuple *orig,
 		   const struct nf_conntrack_l3proto *l3proto,
-		   const struct nf_conntrack_protocol *protocol)
+		   const struct nf_conntrack_l4proto *l4proto)
 {
 	NF_CT_TUPLE_U_BLANK(inverse);
 
@@ -285,7 +285,7 @@ nf_ct_invert_tuple(struct nf_conntrack_t
 	inverse->dst.dir = !orig->dst.dir;
 
 	inverse->dst.protonum = orig->dst.protonum;
-	return protocol->invert_tuple(inverse, orig);
+	return l4proto->invert_tuple(inverse, orig);
 }
 
 static void
@@ -305,7 +305,7 @@ destroy_conntrack(struct nf_conntrack *n
 {
 	struct nf_conn *ct = (struct nf_conn *)nfct;
 	struct nf_conntrack_l3proto *l3proto;
-	struct nf_conntrack_protocol *proto;
+	struct nf_conntrack_l4proto *l4proto;
 
 	DEBUGP("destroy_conntrack(%p)\n", ct);
 	NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
@@ -321,9 +321,9 @@ destroy_conntrack(struct nf_conntrack *n
 	if (l3proto && l3proto->destroy)
 		l3proto->destroy(ct);
 
-	proto = __nf_ct_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
-	if (proto && proto->destroy)
-		proto->destroy(ct);
+	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
+	if (l4proto && l4proto->destroy)
+		l4proto->destroy(ct);
 
 	if (nf_conntrack_destroyed)
 		nf_conntrack_destroyed(ct);
@@ -647,7 +647,7 @@ void nf_conntrack_free(struct nf_conn *c
 static struct nf_conntrack_tuple_hash *
 init_conntrack(const struct nf_conntrack_tuple *tuple,
 	       struct nf_conntrack_l3proto *l3proto,
-	       struct nf_conntrack_protocol *protocol,
+	       struct nf_conntrack_l4proto *l4proto,
 	       struct sk_buff *skb,
 	       unsigned int dataoff)
 {
@@ -655,7 +655,7 @@ init_conntrack(const struct nf_conntrack
 	struct nf_conntrack_tuple repl_tuple;
 	struct nf_conntrack_expect *exp;
 
-	if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, protocol)) {
+	if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
 		DEBUGP("Can't invert tuple.\n");
 		return NULL;
 	}
@@ -666,7 +666,7 @@ init_conntrack(const struct nf_conntrack
 		return (struct nf_conntrack_tuple_hash *)conntrack;
 	}
 
-	if (!protocol->new(conntrack, skb, dataoff)) {
+	if (!l4proto->new(conntrack, skb, dataoff)) {
 		nf_conntrack_free(conntrack);
 		DEBUGP("init conntrack: can't track with proto module\n");
 		return NULL;
@@ -718,7 +718,7 @@ resolve_normal_ct(struct sk_buff *skb,
 		  u_int16_t l3num,
 		  u_int8_t protonum,
 		  struct nf_conntrack_l3proto *l3proto,
-		  struct nf_conntrack_protocol *proto,
+		  struct nf_conntrack_l4proto *l4proto,
 		  int *set_reply,
 		  enum ip_conntrack_info *ctinfo)
 {
@@ -728,7 +728,7 @@ resolve_normal_ct(struct sk_buff *skb,
 
 	if (!nf_ct_get_tuple(skb, (unsigned int)(skb->nh.raw - skb->data),
 			     dataoff, l3num, protonum, &tuple, l3proto,
-			     proto)) {
+			     l4proto)) {
 		DEBUGP("resolve_normal_ct: Can't get tuple\n");
 		return NULL;
 	}
@@ -736,7 +736,7 @@ resolve_normal_ct(struct sk_buff *skb,
 	/* look for tuple match */
 	h = nf_conntrack_find_get(&tuple, NULL);
 	if (!h) {
-		h = init_conntrack(&tuple, l3proto, proto, skb, dataoff);
+		h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff);
 		if (!h)
 			return NULL;
 		if (IS_ERR(h))
@@ -774,7 +774,7 @@ nf_conntrack_in(int pf, unsigned int hoo
 	struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 	struct nf_conntrack_l3proto *l3proto;
-	struct nf_conntrack_protocol *proto;
+	struct nf_conntrack_l4proto *l4proto;
 	unsigned int dataoff;
 	u_int8_t protonum;
 	int set_reply = 0;
@@ -792,19 +792,19 @@ nf_conntrack_in(int pf, unsigned int hoo
 		return -ret;
 	}
 
-	proto = __nf_ct_proto_find((u_int16_t)pf, protonum);
+	l4proto = __nf_ct_l4proto_find((u_int16_t)pf, protonum);
 
 	/* It may be an special packet, error, unclean...
 	 * inverse of the return code tells to the netfilter
 	 * core what to do with the packet. */
-	if (proto->error != NULL &&
-	    (ret = proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
+	if (l4proto->error != NULL &&
+	    (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
 		NF_CT_STAT_INC(error);
 		NF_CT_STAT_INC(invalid);
 		return -ret;
 	}
 
-	ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, proto,
+	ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, l4proto,
 			       &set_reply, &ctinfo);
 	if (!ct) {
 		/* Not valid part of a connection */
@@ -820,7 +820,7 @@ nf_conntrack_in(int pf, unsigned int hoo
 
 	NF_CT_ASSERT((*pskb)->nfct);
 
-	ret = proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum);
+	ret = l4proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum);
 	if (ret < 0) {
 		/* Invalid: inverse of the return code tells
 		 * the netfilter core what to do */
@@ -842,7 +842,7 @@ int nf_ct_invert_tuplepr(struct nf_connt
 {
 	return nf_ct_invert_tuple(inverse, orig,
 				  __nf_ct_l3proto_find(orig->src.l3num),
-				  __nf_ct_proto_find(orig->src.l3num,
+				  __nf_ct_l4proto_find(orig->src.l3num,
 						     orig->dst.protonum));
 }
 
@@ -1199,7 +1199,7 @@ int __init nf_conntrack_init(void)
 	/* Don't NEED lock here, but good form anyway. */
 	write_lock_bh(&nf_conntrack_lock);
         for (i = 0; i < PF_MAX; i++)
-		nf_ct_l3protos[i] = &nf_conntrack_generic_l3proto;
+		nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic;
         write_unlock_bh(&nf_conntrack_lock);
 
 	/* For use by REJECT target */
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 35763e9..5152efd 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -22,7 +22,7 @@ #include <linux/netdevice.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 076e678..7269bff 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -338,7 +338,7 @@ static int exp_seq_show(struct seq_file 
 		   expect->tuple.dst.protonum);
 	print_tuple(s, &expect->tuple,
 		    __nf_ct_l3proto_find(expect->tuple.src.l3num),
-		    __nf_ct_proto_find(expect->tuple.src.l3num,
+		    __nf_ct_l4proto_find(expect->tuple.src.l3num,
 				       expect->tuple.dst.protonum));
 	return seq_putc(s, '\n');
 }
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 2af9220..5cbe55f 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -26,7 +26,7 @@ #define ASSERT_WRITE_LOCK(x)
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 21e0bc9..1852c9d 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -26,7 +26,7 @@ #include <net/ip.h>
 
 #include <linux/netfilter_ipv4.h>
 #include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
@@ -84,7 +84,7 @@ static u_int32_t generic_get_features(co
 	return NF_CT_F_BASIC;
 }
 
-struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = {
 	.l3proto	 = PF_UNSPEC,
 	.name		 = "unknown",
 	.pkt_to_tuple	 = generic_pkt_to_tuple,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index c3d53d9..dc08302 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -38,7 +38,7 @@ #include <net/netfilter/nf_conntrack_cor
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <linux/netfilter_ipv4/ip_nat_protocol.h>
 
 #include <linux/netfilter/nfnetlink.h>
@@ -51,15 +51,15 @@ static char __initdata version[] = "0.93
 static inline int
 ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
 			    const struct nf_conntrack_tuple *tuple,
-			    struct nf_conntrack_protocol *proto)
+			    struct nf_conntrack_l4proto *l4proto)
 {
 	int ret = 0;
 	struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
 
 	NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
 
-	if (likely(proto->tuple_to_nfattr))
-		ret = proto->tuple_to_nfattr(skb, tuple);
+	if (likely(l4proto->tuple_to_nfattr))
+		ret = l4proto->tuple_to_nfattr(skb, tuple);
 	
 	NFA_NEST_END(skb, nest_parms);
 
@@ -94,7 +94,7 @@ ctnetlink_dump_tuples(struct sk_buff *sk
 {
 	int ret;
 	struct nf_conntrack_l3proto *l3proto;
-	struct nf_conntrack_protocol *proto;
+	struct nf_conntrack_l4proto *l4proto;
 
 	l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
 	ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
@@ -103,9 +103,9 @@ ctnetlink_dump_tuples(struct sk_buff *sk
 	if (unlikely(ret < 0))
 		return ret;
 
-	proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
-	ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
-	nf_ct_proto_put(proto);
+	l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+	ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto);
+	nf_ct_l4proto_put(l4proto);
 
 	return ret;
 }
@@ -142,27 +142,27 @@ nfattr_failure:
 static inline int
 ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
 {
-	struct nf_conntrack_protocol *proto = nf_ct_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+	struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
 	struct nfattr *nest_proto;
 	int ret;
 
-	if (!proto->to_nfattr) {
-		nf_ct_proto_put(proto);
+	if (!l4proto->to_nfattr) {
+		nf_ct_l4proto_put(l4proto);
 		return 0;
 	}
 	
 	nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
 
-	ret = proto->to_nfattr(skb, nest_proto, ct);
+	ret = l4proto->to_nfattr(skb, nest_proto, ct);
 
-	nf_ct_proto_put(proto);
+	nf_ct_l4proto_put(l4proto);
 
 	NFA_NEST_END(skb, nest_proto);
 
 	return ret;
 
 nfattr_failure:
-	nf_ct_proto_put(proto);
+	nf_ct_l4proto_put(l4proto);
 	return -1;
 }
 
@@ -493,7 +493,7 @@ ctnetlink_parse_tuple_proto(struct nfatt
 			    struct nf_conntrack_tuple *tuple)
 {
 	struct nfattr *tb[CTA_PROTO_MAX];
-	struct nf_conntrack_protocol *proto;
+	struct nf_conntrack_l4proto *l4proto;
 	int ret = 0;
 
 	nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
@@ -505,12 +505,12 @@ ctnetlink_parse_tuple_proto(struct nfatt
 		return -EINVAL;
 	tuple->dst.protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
 
-	proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+	l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
 
-	if (likely(proto->nfattr_to_tuple))
-		ret = proto->nfattr_to_tuple(tb, tuple);
+	if (likely(l4proto->nfattr_to_tuple))
+		ret = l4proto->nfattr_to_tuple(tb, tuple);
 
-	nf_ct_proto_put(proto);
+	nf_ct_l4proto_put(l4proto);
 	
 	return ret;
 }
@@ -890,18 +890,18 @@ static inline int
 ctnetlink_change_protoinfo(struct nf_conn *ct, struct nfattr *cda[])
 {
 	struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
-	struct nf_conntrack_protocol *proto;
+	struct nf_conntrack_l4proto *l4proto;
 	u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
 	u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
 	int err = 0;
 
 	nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
 
-	proto = nf_ct_proto_find_get(l3num, npt);
+	l4proto = nf_ct_l4proto_find_get(l3num, npt);
 
-	if (proto->from_nfattr)
-		err = proto->from_nfattr(tb, ct);
-	nf_ct_proto_put(proto); 
+	if (l4proto->from_nfattr)
+		err = l4proto->from_nfattr(tb, ct);
+	nf_ct_l4proto_put(l4proto);
 
 	return err;
 }
@@ -1081,7 +1081,7 @@ ctnetlink_exp_dump_mask(struct sk_buff *
 {
 	int ret;
 	struct nf_conntrack_l3proto *l3proto;
-	struct nf_conntrack_protocol *proto;
+	struct nf_conntrack_l4proto *l4proto;
 	struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
 
 	l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
@@ -1091,9 +1091,9 @@ ctnetlink_exp_dump_mask(struct sk_buff *
 	if (unlikely(ret < 0))
 		goto nfattr_failure;
 
-	proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
-	ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
-	nf_ct_proto_put(proto);
+	l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+	ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto);
+	nf_ct_l4proto_put(l4proto);
 	if (unlikely(ret < 0))
 		goto nfattr_failure;
 
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 24c61a3..330b9ac 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -24,38 +24,38 @@ #include <linux/netdevice.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
-struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
+struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly;
 struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
 
-struct nf_conntrack_protocol *
-__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
+struct nf_conntrack_l4proto *
+__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto)
 {
 	if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
-		return &nf_conntrack_generic_protocol;
+		return &nf_conntrack_l4proto_generic;
 
-	return nf_ct_protos[l3proto][protocol];
+	return nf_ct_protos[l3proto][l4proto];
 }
 
 /* this is guaranteed to always return a valid protocol helper, since
  * it falls back to generic_protocol */
-struct nf_conntrack_protocol *
-nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
+struct nf_conntrack_l4proto *
+nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto)
 {
-	struct nf_conntrack_protocol *p;
+	struct nf_conntrack_l4proto *p;
 
 	preempt_disable();
-	p = __nf_ct_proto_find(l3proto, protocol);
+	p = __nf_ct_l4proto_find(l3proto, l4proto);
 	if (!try_module_get(p->me))
-		p = &nf_conntrack_generic_protocol;
+		p = &nf_conntrack_l4proto_generic;
 	preempt_enable();
 
 	return p;
 }
 
-void nf_ct_proto_put(struct nf_conntrack_protocol *p)
+void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p)
 {
 	module_put(p->me);
 }
@@ -68,7 +68,7 @@ nf_ct_l3proto_find_get(u_int16_t l3proto
 	preempt_disable();
 	p = __nf_ct_l3proto_find(l3proto);
 	if (!try_module_get(p->me))
-		p = &nf_conntrack_generic_l3proto;
+		p = &nf_conntrack_l3proto_generic;
 	preempt_enable();
 
 	return p;
@@ -86,7 +86,7 @@ nf_ct_l3proto_try_module_get(unsigned sh
 	struct nf_conntrack_l3proto *p;
 
 retry:	p = nf_ct_l3proto_find_get(l3proto);
-	if (p == &nf_conntrack_generic_l3proto) {
+	if (p == &nf_conntrack_l3proto_generic) {
 		ret = request_module("nf_conntrack-%d", l3proto);
 		if (!ret)
 			goto retry;
@@ -114,14 +114,14 @@ static int kill_l3proto(struct nf_conn *
 			((struct nf_conntrack_l3proto *)data)->l3proto);
 }
 
-static int kill_proto(struct nf_conn *i, void *data)
+static int kill_l4proto(struct nf_conn *i, void *data)
 {
-	struct nf_conntrack_protocol *proto;
-	proto = (struct nf_conntrack_protocol *)data;
+	struct nf_conntrack_l4proto *l4proto;
+	l4proto = (struct nf_conntrack_l4proto *)data;
 	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
-			proto->proto) &&
+			l4proto->l4proto) &&
 	       (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
-			proto->l3proto);
+			l4proto->l3proto);
 }
 
 int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
@@ -129,7 +129,7 @@ int nf_conntrack_l3proto_register(struct
 	int ret = 0;
 
 	write_lock_bh(&nf_conntrack_lock);
-	if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) {
+	if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) {
 		ret = -EBUSY;
 		goto out;
 	}
@@ -143,7 +143,7 @@ out:
 void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
 {
 	write_lock_bh(&nf_conntrack_lock);
-	nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto;
+	nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic;
 	write_unlock_bh(&nf_conntrack_lock);
 
 	/* Somebody could be still looking at the proto in bh. */
@@ -155,43 +155,43 @@ void nf_conntrack_l3proto_unregister(str
 
 /* FIXME: Allow NULL functions and sub in pointers to generic for
    them. --RR */
-int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto)
+int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
 {
 	int ret = 0;
 
 retry:
 	write_lock_bh(&nf_conntrack_lock);
-	if (nf_ct_protos[proto->l3proto]) {
-		if (nf_ct_protos[proto->l3proto][proto->proto]
-				!= &nf_conntrack_generic_protocol) {
+	if (nf_ct_protos[l4proto->l3proto]) {
+		if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
+				!= &nf_conntrack_l4proto_generic) {
 			ret = -EBUSY;
 			goto out_unlock;
 		}
 	} else {
 		/* l3proto may be loaded latter. */
-		struct nf_conntrack_protocol **proto_array;
+		struct nf_conntrack_l4proto **proto_array;
 		int i;
 
 		write_unlock_bh(&nf_conntrack_lock);
 
-		proto_array = (struct nf_conntrack_protocol **)
+		proto_array = (struct nf_conntrack_l4proto **)
 				kmalloc(MAX_NF_CT_PROTO *
-					 sizeof(struct nf_conntrack_protocol *),
+					 sizeof(struct nf_conntrack_l4proto *),
 					GFP_KERNEL);
 		if (proto_array == NULL) {
 			ret = -ENOMEM;
 			goto out;
 		}
 		for (i = 0; i < MAX_NF_CT_PROTO; i++)
-			proto_array[i] = &nf_conntrack_generic_protocol;
+			proto_array[i] = &nf_conntrack_l4proto_generic;
 
 		write_lock_bh(&nf_conntrack_lock);
-		if (nf_ct_protos[proto->l3proto]) {
+		if (nf_ct_protos[l4proto->l3proto]) {
 			/* bad timing, but no problem */
 			write_unlock_bh(&nf_conntrack_lock);
 			kfree(proto_array);
 		} else {
-			nf_ct_protos[proto->l3proto] = proto_array;
+			nf_ct_protos[l4proto->l3proto] = proto_array;
 			write_unlock_bh(&nf_conntrack_lock);
 		}
 
@@ -202,7 +202,7 @@ retry:
 		goto retry;
 	}
 
-	nf_ct_protos[proto->l3proto][proto->proto] = proto;
+	nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto;
 
 out_unlock:
 	write_unlock_bh(&nf_conntrack_lock);
@@ -210,16 +210,16 @@ out:
 	return ret;
 }
 
-void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
+void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
 {
 	write_lock_bh(&nf_conntrack_lock);
-	nf_ct_protos[proto->l3proto][proto->proto]
-		= &nf_conntrack_generic_protocol;
+	nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
+		= &nf_conntrack_l4proto_generic;
 	write_unlock_bh(&nf_conntrack_lock);
 
 	/* Somebody could be still looking at the proto in bh. */
 	synchronize_net();
 
 	/* Remove all contrack entries for this protocol */
-	nf_ct_iterate_cleanup(kill_proto, proto);
+	nf_ct_iterate_cleanup(kill_l4proto, l4proto);
 }
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 26408bb..f44811e 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -15,7 +15,7 @@ #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 
 unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
 
@@ -71,10 +71,10 @@ static int new(struct nf_conn *conntrack
 	return 1;
 }
 
-struct nf_conntrack_protocol nf_conntrack_generic_protocol =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
 {
 	.l3proto		= PF_UNSPEC,
-	.proto			= 0,
+	.l4proto		= 0,
 	.name			= "unknown",
 	.pkt_to_tuple		= generic_pkt_to_tuple,
 	.invert_tuple		= generic_invert_tuple,
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index ba3e31f..5115619 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -32,7 +32,7 @@ #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 
 #include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
 #if 0
@@ -509,9 +509,9 @@ static int sctp_new(struct nf_conn *conn
 	return 1;
 }
 
-struct nf_conntrack_protocol nf_conntrack_protocol_sctp4 = { 
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
 	.l3proto	 = PF_INET,
-	.proto 		 = IPPROTO_SCTP, 
+	.l4proto 	 = IPPROTO_SCTP,
 	.name 		 = "sctp",
 	.pkt_to_tuple 	 = sctp_pkt_to_tuple, 
 	.invert_tuple 	 = sctp_invert_tuple, 
@@ -523,9 +523,9 @@ struct nf_conntrack_protocol nf_conntrac
 	.me 		 = THIS_MODULE 
 };
 
-struct nf_conntrack_protocol nf_conntrack_protocol_sctp6 = { 
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
 	.l3proto	 = PF_INET6,
-	.proto 		 = IPPROTO_SCTP, 
+	.l4proto 	 = IPPROTO_SCTP,
 	.name 		 = "sctp",
 	.pkt_to_tuple 	 = sctp_pkt_to_tuple, 
 	.invert_tuple 	 = sctp_invert_tuple, 
@@ -625,14 +625,14 @@ int __init nf_conntrack_proto_sctp_init(
 {
 	int ret;
 
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_sctp4);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
 	if (ret) {
-		printk("nf_conntrack_proto_sctp4: protocol register failed\n");
+		printk("nf_conntrack_l4proto_sctp4: protocol register failed\n");
 		goto out;
 	}
-	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_sctp6);
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
 	if (ret) {
-		printk("nf_conntrack_proto_sctp6: protocol register failed\n");
+		printk("nf_conntrack_l4proto_sctp6: protocol register failed\n");
 		goto cleanup_sctp4;
 	}
 
@@ -648,10 +648,10 @@ #endif
 
 #ifdef CONFIG_SYSCTL
  cleanup:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 #endif
  cleanup_sctp4:
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
  out:
 	DEBUGP("SCTP conntrack module loading %s\n", 
 					ret ? "failed": "succeeded");
@@ -660,8 +660,8 @@ #endif
 
 void __exit nf_conntrack_proto_sctp_fini(void)
 {
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6);
-	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
 #ifdef CONFIG_SYSCTL
  	unregister_sysctl_table(nf_ct_sysctl_header);
 #endif
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index e6b6f23..32b88b7 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -42,7 +42,7 @@ #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
 #if 0
@@ -1169,10 +1169,10 @@ static int nfattr_to_tcp(struct nfattr *
 }
 #endif
   
-struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
 {
 	.l3proto		= PF_INET,
-	.proto 			= IPPROTO_TCP,
+	.l4proto 		= IPPROTO_TCP,
 	.name 			= "tcp",
 	.pkt_to_tuple 		= tcp_pkt_to_tuple,
 	.invert_tuple 		= tcp_invert_tuple,
@@ -1190,10 +1190,10 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 #endif
 };
 
-struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 =
 {
 	.l3proto		= PF_INET6,
-	.proto 			= IPPROTO_TCP,
+	.l4proto 		= IPPROTO_TCP,
 	.name 			= "tcp",
 	.pkt_to_tuple 		= tcp_pkt_to_tuple,
 	.invert_tuple 		= tcp_invert_tuple,
@@ -1211,5 +1211,5 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 #endif
 };
 
-EXPORT_SYMBOL(nf_conntrack_protocol_tcp4);
-EXPORT_SYMBOL(nf_conntrack_protocol_tcp6);
+EXPORT_SYMBOL(nf_conntrack_l4proto_tcp4);
+EXPORT_SYMBOL(nf_conntrack_l4proto_tcp6);
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index cf9db03..200d7d3 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -26,7 +26,7 @@ #include <net/checksum.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
 unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
@@ -148,10 +148,10 @@ static int udp_error(struct sk_buff *skb
 	return NF_ACCEPT;
 }
 
-struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
 {
 	.l3proto		= PF_INET,
-	.proto			= IPPROTO_UDP,
+	.l4proto		= IPPROTO_UDP,
 	.name			= "udp",
 	.pkt_to_tuple		= udp_pkt_to_tuple,
 	.invert_tuple		= udp_invert_tuple,
@@ -167,10 +167,10 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 #endif
 };
 
-struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 =
 {
 	.l3proto		= PF_INET6,
-	.proto			= IPPROTO_UDP,
+	.l4proto		= IPPROTO_UDP,
 	.name			= "udp",
 	.pkt_to_tuple		= udp_pkt_to_tuple,
 	.invert_tuple		= udp_invert_tuple,
@@ -186,5 +186,5 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 #endif
 };
 
-EXPORT_SYMBOL(nf_conntrack_protocol_udp4);
-EXPORT_SYMBOL(nf_conntrack_protocol_udp6);
+EXPORT_SYMBOL(nf_conntrack_l4proto_udp4);
+EXPORT_SYMBOL(nf_conntrack_l4proto_udp6);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index eb031d2..6ebac7d 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -35,7 +35,7 @@ #define ASSERT_WRITE_LOCK(x)
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
-#include <net/netfilter/nf_conntrack_protocol.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 
@@ -54,9 +54,9 @@ #ifdef CONFIG_PROC_FS
 int
 print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
 	    struct nf_conntrack_l3proto *l3proto,
-	    struct nf_conntrack_protocol *proto)
+	    struct nf_conntrack_l4proto *l4proto)
 {
-	return l3proto->print_tuple(s, tuple) || proto->print_tuple(s, tuple);
+	return l3proto->print_tuple(s, tuple) || l4proto->print_tuple(s, tuple);
 }
 
 #ifdef CONFIG_NF_CT_ACCT
@@ -135,7 +135,7 @@ static int ct_seq_show(struct seq_file *
 	const struct nf_conntrack_tuple_hash *hash = v;
 	const struct nf_conn *conntrack = nf_ct_tuplehash_to_ctrack(hash);
 	struct nf_conntrack_l3proto *l3proto;
-	struct nf_conntrack_protocol *proto;
+	struct nf_conntrack_l4proto *l4proto;
 
 	ASSERT_READ_LOCK(&nf_conntrack_lock);
 	NF_CT_ASSERT(conntrack);
@@ -148,16 +148,16 @@ static int ct_seq_show(struct seq_file *
 				       .tuple.src.l3num);
 
 	NF_CT_ASSERT(l3proto);
-	proto = __nf_ct_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+	l4proto = __nf_ct_l4proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
 				   .tuple.src.l3num,
 				   conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
 				   .tuple.dst.protonum);
-	NF_CT_ASSERT(proto);
+	NF_CT_ASSERT(l4proto);
 
 	if (seq_printf(s, "%-8s %u %-8s %u %ld ",
 		       l3proto->name,
 		       conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num,
-		       proto->name,
+		       l4proto->name,
 		       conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
 		       timer_pending(&conntrack->timeout)
 		       ? (long)(conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
@@ -166,11 +166,11 @@ static int ct_seq_show(struct seq_file *
 	if (l3proto->print_conntrack(s, conntrack))
 		return -ENOSPC;
 
-	if (proto->print_conntrack(s, conntrack))
+	if (l4proto->print_conntrack(s, conntrack))
 		return -ENOSPC;
 
 	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
-			l3proto, proto))
+			l3proto, l4proto))
 		return -ENOSPC;
 
 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
@@ -181,7 +181,7 @@ static int ct_seq_show(struct seq_file *
 			return -ENOSPC;
 
 	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
-			l3proto, proto))
+			l3proto, l4proto))
 		return -ENOSPC;
 
 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
@@ -655,8 +655,8 @@ EXPORT_SYMBOL(nf_ct_l3proto_try_module_g
 EXPORT_SYMBOL(nf_ct_l3proto_module_put);
 EXPORT_SYMBOL(nf_conntrack_l3proto_register);
 EXPORT_SYMBOL(nf_conntrack_l3proto_unregister);
-EXPORT_SYMBOL(nf_conntrack_protocol_register);
-EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
+EXPORT_SYMBOL(nf_conntrack_l4proto_register);
+EXPORT_SYMBOL(nf_conntrack_l4proto_unregister);
 EXPORT_SYMBOL(nf_ct_invert_tuplepr);
 EXPORT_SYMBOL(nf_conntrack_destroyed);
 EXPORT_SYMBOL(need_conntrack);
@@ -665,9 +665,9 @@ EXPORT_SYMBOL(nf_conntrack_helper_unregi
 EXPORT_SYMBOL(nf_ct_iterate_cleanup);
 EXPORT_SYMBOL(__nf_ct_refresh_acct);
 EXPORT_SYMBOL(nf_ct_protos);
-EXPORT_SYMBOL(__nf_ct_proto_find);
-EXPORT_SYMBOL(nf_ct_proto_find_get);
-EXPORT_SYMBOL(nf_ct_proto_put);
+EXPORT_SYMBOL(__nf_ct_l4proto_find);
+EXPORT_SYMBOL(nf_ct_l4proto_find_get);
+EXPORT_SYMBOL(nf_ct_l4proto_put);
 EXPORT_SYMBOL(nf_ct_l3proto_find_get);
 EXPORT_SYMBOL(nf_ct_l3proto_put);
 EXPORT_SYMBOL(nf_ct_l3protos);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 07/33]: nf_conntrack: more sanity checks in protocol registration/unregistration
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (5 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 06/33]: nf_conntrack: rename struct nf_conntrack_protocol Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 08/33]: nf_conntrack: remove ASSERT_{READ,WRITE}_LOCK Patrick McHardy
                   ` (26 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: more sanity checks in protocol registration/unregistration

Add some more sanity checks when registering/unregistering l3/l4 protocols.

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 806420ab0fbfae2bcb4a3942190747afe5809b4d
tree 179894f058bff731aa57fc2c9f2dc211ea4beb4a
parent 1ef0a3824fdd09eeeaaf25e9d50165dfbaa88ad0
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:13:00 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:57:07 +0100

 include/net/netfilter/nf_conntrack_l3proto.h |    2 -
 include/net/netfilter/nf_conntrack_l4proto.h |    2 -
 net/netfilter/nf_conntrack_core.c            |    2 -
 net/netfilter/nf_conntrack_proto.c           |   55 +++++++++++++++++++++++---
 4 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index ffe23a1..11b4b29 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -86,7 +86,7 @@ extern struct nf_conntrack_l3proto *nf_c
 
 /* Protocol registration. */
 extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
-extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+extern int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
 
 extern struct nf_conntrack_l3proto *
 nf_ct_l3proto_find_get(u_int16_t l3proto);
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 0c6babd..5193e48 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -102,7 +102,7 @@ extern void nf_ct_l4proto_put(struct nf_
 
 /* Protocol registration. */
 extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
-extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+extern int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
 
 /* Generic netlink helpers */
 extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 441a647..73615d3 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1198,7 +1198,7 @@ int __init nf_conntrack_init(void)
 
 	/* Don't NEED lock here, but good form anyway. */
 	write_lock_bh(&nf_conntrack_lock);
-        for (i = 0; i < PF_MAX; i++)
+        for (i = 0; i < AF_MAX; i++)
 		nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic;
         write_unlock_bh(&nf_conntrack_lock);
 
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 330b9ac..a6a3b1d 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -28,7 +28,7 @@ #include <net/netfilter/nf_conntrack_l4p
 #include <net/netfilter/nf_conntrack_core.h>
 
 struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly;
-struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
+struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly;
 
 struct nf_conntrack_l4proto *
 __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto)
@@ -128,21 +128,40 @@ int nf_conntrack_l3proto_register(struct
 {
 	int ret = 0;
 
+	if (proto->l3proto >= AF_MAX) {
+		ret = -EBUSY;
+		goto out;
+	}
+
 	write_lock_bh(&nf_conntrack_lock);
 	if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) {
 		ret = -EBUSY;
-		goto out;
+		goto out_unlock;
 	}
 	nf_ct_l3protos[proto->l3proto] = proto;
-out:
-	write_unlock_bh(&nf_conntrack_lock);
 
+out_unlock:
+	write_unlock_bh(&nf_conntrack_lock);
+out:
 	return ret;
 }
 
-void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
+int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
 {
+	int ret = 0;
+
+	if (proto->l3proto >= AF_MAX) {
+		ret = -EBUSY;
+		goto out;
+	}
+
 	write_lock_bh(&nf_conntrack_lock);
+	if (nf_ct_l3protos[proto->l3proto] != proto) {
+		write_unlock_bh(&nf_conntrack_lock);
+		ret = -EBUSY;
+		goto out;
+	}
+
 	nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic;
 	write_unlock_bh(&nf_conntrack_lock);
 
@@ -151,6 +170,9 @@ void nf_conntrack_l3proto_unregister(str
 
 	/* Remove all contrack entries for this protocol */
 	nf_ct_iterate_cleanup(kill_l3proto, proto);
+
+out:
+	return ret;
 }
 
 /* FIXME: Allow NULL functions and sub in pointers to generic for
@@ -159,6 +181,11 @@ int nf_conntrack_l4proto_register(struct
 {
 	int ret = 0;
 
+	if (l4proto->l3proto >= PF_MAX) {
+		ret = -EBUSY;
+		goto out;
+	}
+
 retry:
 	write_lock_bh(&nf_conntrack_lock);
 	if (nf_ct_protos[l4proto->l3proto]) {
@@ -210,9 +237,22 @@ out:
 	return ret;
 }
 
-void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
+int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
 {
+	int ret = 0;
+
+	if (l4proto->l3proto >= PF_MAX) {
+		ret = -EBUSY;
+		goto out;
+	}
+
 	write_lock_bh(&nf_conntrack_lock);
+	if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
+	    != l4proto) {
+		write_unlock_bh(&nf_conntrack_lock);
+		ret = -EBUSY;
+		goto out;
+	}
 	nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
 		= &nf_conntrack_l4proto_generic;
 	write_unlock_bh(&nf_conntrack_lock);
@@ -222,4 +262,7 @@ void nf_conntrack_l4proto_unregister(str
 
 	/* Remove all contrack entries for this protocol */
 	nf_ct_iterate_cleanup(kill_l4proto, l4proto);
+
+out:
+	return ret;
 }

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 08/33]: nf_conntrack: remove ASSERT_{READ,WRITE}_LOCK
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (6 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 07/33]: nf_conntrack: more sanity checks in protocol registration/unregistration Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 09/33]: nf_conntrack: minor __nf_ct_refresh_acct() whitespace cleanup Patrick McHardy
                   ` (25 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: remove ASSERT_{READ,WRITE}_LOCK

Remove the usage of ASSERT_READ_LOCK/ASSERT_WRITE_LOCK in nf_conntrack,
it didn't do anything, it was just an empty define and it uglified the code.

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit fa685ac2d1dfe17d62464fd28c8151df5d323e47
tree 3f065a78dc8a815cc1456d3d433580580350521a
parent 806420ab0fbfae2bcb4a3942190747afe5809b4d
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:13:01 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:57:08 +0100

 net/netfilter/nf_conntrack_core.c       |    7 -------
 net/netfilter/nf_conntrack_standalone.c |    4 ----
 2 files changed, 0 insertions(+), 11 deletions(-)

diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 73615d3..ab161b7 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -47,11 +47,6 @@ #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/socket.h>
 
-/* This rwlock protects the main hash table, protocol/helper/expected
-   registrations, conntrack timers*/
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -292,7 +287,6 @@ static void
 clean_from_lists(struct nf_conn *ct)
 {
 	DEBUGP("clean_from_lists(%p)\n", ct);
-	ASSERT_WRITE_LOCK(&nf_conntrack_lock);
 	list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
 	list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
 
@@ -371,7 +365,6 @@ __nf_conntrack_find(const struct nf_conn
 	struct nf_conntrack_tuple_hash *h;
 	unsigned int hash = hash_conntrack(tuple);
 
-	ASSERT_READ_LOCK(&nf_conntrack_lock);
 	list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
 		if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
 		    nf_ct_tuple_equal(tuple, &h->tuple)) {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 6ebac7d..f87d333 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -29,9 +29,6 @@ #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
 
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
@@ -137,7 +134,6 @@ static int ct_seq_show(struct seq_file *
 	struct nf_conntrack_l3proto *l3proto;
 	struct nf_conntrack_l4proto *l4proto;
 
-	ASSERT_READ_LOCK(&nf_conntrack_lock);
 	NF_CT_ASSERT(conntrack);
 
 	/* we only want to print DIR_ORIGINAL */

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 09/33]: nf_conntrack: minor __nf_ct_refresh_acct() whitespace cleanup
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (7 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 08/33]: nf_conntrack: remove ASSERT_{READ,WRITE}_LOCK Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:08 ` [NETFILTER 10/33]: nf_conntrack: remove unused struct list_head from protocols Patrick McHardy
                   ` (24 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: minor __nf_ct_refresh_acct() whitespace cleanup

Minor whitespace cleanup.

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 01d88c08b8b25a08c7e2b3520ebc8e83ec4b3888
tree 759bbdf121cebe29c688cb50f2f16164edc2b966
parent fa685ac2d1dfe17d62464fd28c8151df5d323e47
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:13:02 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:57:08 +0100

 net/netfilter/nf_conntrack_core.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index ab161b7..355b330 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -877,9 +877,10 @@ #ifdef CONFIG_NF_CT_ACCT
 		ct->counters[CTINFO2DIR(ctinfo)].packets++;
 		ct->counters[CTINFO2DIR(ctinfo)].bytes +=
 			skb->len - (unsigned int)(skb->nh.raw - skb->data);
-	if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
-	    || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
-		event |= IPCT_COUNTER_FILLING;
+
+		if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
+		    || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
+			event |= IPCT_COUNTER_FILLING;
 	}
 #endif
 

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 10/33]: nf_conntrack: remove unused struct list_head from protocols
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (8 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 09/33]: nf_conntrack: minor __nf_ct_refresh_acct() whitespace cleanup Patrick McHardy
@ 2006-11-29  2:08 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 11/33]: nf_conntrack: reduce timer updates in __nf_ct_refresh_acct() Patrick McHardy
                   ` (23 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:08 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: remove unused struct list_head from protocols

Remove unused struct list_head from struct nf_conntrack_l3proto and
nf_conntrack_l4proto as all protocols are kept in arrays, not linked
lists.

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 4bbe725325797bfbe6366209b9e974fe4ef0e83b
tree d38cbcd9876606366933dfe10d88dc8129270f4a
parent 01d88c08b8b25a08c7e2b3520ebc8e83ec4b3888
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:13:04 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:57:09 +0100

 include/net/netfilter/nf_conntrack_l3proto.h |    3 ---
 include/net/netfilter/nf_conntrack_l4proto.h |    3 ---
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c |    1 -
 3 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 11b4b29..6364df0 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -18,9 +18,6 @@ struct nfattr;
 
 struct nf_conntrack_l3proto
 {
-	/* Next pointer. */
-	struct list_head list;
-
 	/* L3 Protocol Family number. ex) PF_INET */
 	u_int16_t l3proto;
 
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 5193e48..c22804a 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -16,9 +16,6 @@ struct nfattr;
 
 struct nf_conntrack_l4proto
 {
-	/* Next pointer. */
-	struct list_head list;
-
 	/* L3 Protocol number. */
 	u_int16_t l3proto;
 
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 08223a5..95fc22b 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -323,7 +323,6 @@ #endif
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
 {
-	.list			= { NULL, NULL },
 	.l3proto		= PF_INET,
 	.l4proto		= IPPROTO_ICMP,
 	.name			= "icmp",

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 11/33]: nf_conntrack: reduce timer updates in __nf_ct_refresh_acct()
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (9 preceding siblings ...)
  2006-11-29  2:08 ` [NETFILTER 10/33]: nf_conntrack: remove unused struct list_head from protocols Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 12/33]: nf_conntrack_ftp: fix missing helper mask initilization Patrick McHardy
                   ` (22 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: reduce timer updates in __nf_ct_refresh_acct()

Only update the conntrack timer if there's been at least HZ jiffies since
the last update. Reduces the number of del_timer/add_timer cycles from one
per packet to one per connection per second (plus once for each state change
of a connection)

Should handle timer wraparounds and connection timeout changes.

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 5a564daecd5e2cf14dfc657b5fcdb91218324e90
tree cdce6d1b1abbfbedd9b018d97889af766a35bd54
parent 4bbe725325797bfbe6366209b9e974fe4ef0e83b
author Martin Josefsson <gandalf@wlug.westbo.se> Tue, 28 Nov 2006 23:13:05 +0100
committer Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:57:09 +0100

 net/netfilter/nf_conntrack_core.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 355b330..3e7c0a9 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -864,9 +864,14 @@ void __nf_ct_refresh_acct(struct nf_conn
 		ct->timeout.expires = extra_jiffies;
 		event = IPCT_REFRESH;
 	} else {
-		/* Need del_timer for race avoidance (may already be dying). */
-		if (del_timer(&ct->timeout)) {
-			ct->timeout.expires = jiffies + extra_jiffies;
+		unsigned long newtime = jiffies + extra_jiffies;
+
+		/* Only update the timeout if the new timeout is at least
+		   HZ jiffies from the old timeout. Need del_timer for race
+		   avoidance (may already be dying). */
+		if (newtime - ct->timeout.expires >= HZ
+		    && del_timer(&ct->timeout)) {
+			ct->timeout.expires = newtime;
 			add_timer(&ct->timeout);
 			event = IPCT_REFRESH;
 		}

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 12/33]: nf_conntrack_ftp: fix missing helper mask initilization
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (10 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 11/33]: nf_conntrack: reduce timer updates in __nf_ct_refresh_acct() Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 13/33]: nf_conntrack: move extern declaration to header files Patrick McHardy
                   ` (21 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack_ftp: fix missing helper mask initilization

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 7aeb0641e3f08db8639b8fd67723d9b24907063d
tree dc2516c0bd1ffbf60a62f5e4d6597ca9c1c34b47
parent 5a564daecd5e2cf14dfc657b5fcdb91218324e90
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:17 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:12:50 +0100

 net/netfilter/nf_conntrack_ftp.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 10836fc..05cb78c 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -586,6 +586,7 @@ static int __init nf_conntrack_ftp_init(
 		for (j = 0; j < 2; j++) {
 			ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
 			ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
+			ftp[i][j].mask.src.l3num = 0xFFFF;
 			ftp[i][j].mask.src.u.tcp.port = 0xFFFF;
 			ftp[i][j].mask.dst.protonum = 0xFF;
 			ftp[i][j].max_expected = 1;

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 13/33]: nf_conntrack: move extern declaration to header files
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (11 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 12/33]: nf_conntrack_ftp: fix missing helper mask initilization Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 14/33]: nf_conntrack: automatic sysctl registation for conntrack protocols Patrick McHardy
                   ` (20 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: move extern declaration to header files

Using extern in a C file is a bad idea because the compiler can't
catch type errors.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit f45fe0b6460390ab5a561f3cbcf48a5c8368b168
tree d65356b3c785ed2e50b20dfa844154c6be3dcd1a
parent 7aeb0641e3f08db8639b8fd67723d9b24907063d
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:19 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:13:31 +0100

 include/net/netfilter/ipv4/nf_conntrack_ipv4.h |    4 ++++
 include/net/netfilter/ipv6/nf_conntrack_ipv6.h |   25 ++++++++++++++++++++++++
 include/net/netfilter/nf_conntrack.h           |    5 +++++
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    6 ------
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   18 -----------------
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c |    3 ---
 net/netfilter/nf_conntrack_expect.c            |    1 -
 net/netfilter/nf_conntrack_l3proto_generic.c   |    2 --
 net/netfilter/nf_conntrack_standalone.c        |    7 -------
 9 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 9168443..8c4f7e8 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -37,4 +37,8 @@ #endif
 struct sk_buff *
 nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
 
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
+
 #endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
new file mode 100644
index 0000000..b4b6049
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -0,0 +1,25 @@
+#ifndef _NF_CONNTRACK_IPV6_H
+#define _NF_CONNTRACK_IPV6_H
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
+
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
+
+extern int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start,
+				  u8 *nexthdrp, int len);
+
+extern int nf_ct_frag6_init(void);
+extern void nf_ct_frag6_cleanup(void);
+extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb);
+extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
+			       struct net_device *in,
+			       struct net_device *out,
+			       int (*okfn)(struct sk_buff *));
+
+extern unsigned int nf_ct_frag6_timeout;
+extern unsigned int nf_ct_frag6_low_thresh;
+extern unsigned int nf_ct_frag6_high_thresh;
+
+#endif /* _NF_CONNTRACK_IPV6_H*/
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 9a29505..d0d0e64 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -79,6 +79,8 @@ struct nf_conn_help {
 
 
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+
 struct nf_conn
 {
 	/* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
@@ -241,7 +243,10 @@ static inline int nf_ct_is_dying(struct 
 
 extern unsigned int nf_conntrack_htable_size;
 extern int nf_conntrack_checksum;
+extern atomic_t nf_conntrack_count;
+extern int nf_conntrack_max;
 
+DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
 #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++)
 
 /* no helper, no nat */
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 370df0f..d190708 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -38,8 +38,6 @@ #else
 #define DEBUGP(format, args...)
 #endif
 
-DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat);
-
 static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 			     struct nf_conntrack_tuple *tuple)
 {
@@ -429,10 +427,6 @@ #endif
 	.me		 = THIS_MODULE,
 };
 
-extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
-extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
-extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
-
 MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
 MODULE_LICENSE("GPL");
 
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index cdbba44..9108ecc 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -43,8 +43,6 @@ #else
 #define DEBUGP(format, args...)
 #endif
 
-DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
-
 static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 			     struct nf_conntrack_tuple *tuple)
 {
@@ -211,11 +209,6 @@ out:
 	return nf_conntrack_confirm(pskb);
 }
 
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb);
-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
-			       struct net_device *in,
-			       struct net_device *out,
-			       int (*okfn)(struct sk_buff *));
 static unsigned int ipv6_defrag(unsigned int hooknum,
 				struct sk_buff **pskb,
 				const struct net_device *in,
@@ -335,11 +328,6 @@ #ifdef CONFIG_SYSCTL
 /* From nf_conntrack_proto_icmpv6.c */
 extern unsigned int nf_ct_icmpv6_timeout;
 
-/* From nf_conntrack_reasm.c */
-extern unsigned int nf_ct_frag6_timeout;
-extern unsigned int nf_ct_frag6_low_thresh;
-extern unsigned int nf_ct_frag6_high_thresh;
-
 static struct ctl_table_header *nf_ct_ipv6_sysctl_header;
 
 static ctl_table nf_ct_sysctl_table[] = {
@@ -458,12 +446,6 @@ #endif
 	.me			= THIS_MODULE,
 };
 
-extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
-extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
-extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
-extern int nf_ct_frag6_init(void);
-extern void nf_ct_frag6_cleanup(void);
-
 MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 2cdf225..b3b468c 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -142,9 +142,6 @@ static int icmpv6_new(struct nf_conn *co
 	return 1;
 }
 
-extern int
-nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len);
-extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
 static int
 icmpv6_error_message(struct sk_buff *skb,
 		     unsigned int icmp6off,
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 7269bff..79cfd79 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -28,7 +28,6 @@ #include <net/netfilter/nf_conntrack_tup
 
 LIST_HEAD(nf_conntrack_expect_list);
 kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
-DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
 static unsigned int nf_conntrack_expect_next_id;
 
 /* nf_conntrack_expect helper functions */
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 1852c9d..3124b3a 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -37,8 +37,6 @@ #else
 #define DEBUGP(format, args...)
 #endif
 
-DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat);
-
 static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 				struct nf_conntrack_tuple *tuple)
 {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index f87d333..2283a26 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -44,9 +44,6 @@ #endif
 
 MODULE_LICENSE("GPL");
 
-extern atomic_t nf_conntrack_count;
-DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
-
 #ifdef CONFIG_PROC_FS
 int
 print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
@@ -334,10 +331,6 @@ int nf_conntrack_checksum __read_mostly 
 
 #ifdef CONFIG_SYSCTL
 
-/* From nf_conntrack_core.c */
-extern int nf_conntrack_max;
-extern unsigned int nf_conntrack_htable_size;
-
 /* From nf_conntrack_proto_tcp.c */
 extern unsigned int nf_ct_tcp_timeout_syn_sent;
 extern unsigned int nf_ct_tcp_timeout_syn_recv;

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 14/33]: nf_conntrack: automatic sysctl registation for conntrack protocols
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (12 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 13/33]: nf_conntrack: move extern declaration to header files Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 15/33]: nf_conntrack: move conntrack protocol sysctls to individual modules Patrick McHardy
                   ` (19 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: automatic sysctl registation for conntrack protocols

Add helper functions for sysctl registration with optional instantiating
of common path elements (like net/netfilter) and use it for support for
automatic registation of conntrack protocol sysctls.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit d8467cb91235e63cf7d36cdea1e6336a4df217bd
tree 253f1a33df3fb83b680fd0a74604b8a8c2853614
parent f45fe0b6460390ab5a561f3cbcf48a5c8368b168
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:21 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:13:32 +0100

 include/linux/netfilter.h                    |   10 ++
 include/net/netfilter/nf_conntrack_l3proto.h |    6 +
 include/net/netfilter/nf_conntrack_l4proto.h |    6 +
 net/netfilter/Makefile                       |    1 
 net/netfilter/nf_conntrack_proto.c           |  102 ++++++++++++++++++++
 net/netfilter/nf_sysctl.c                    |  134 ++++++++++++++++++++++++++
 6 files changed, 259 insertions(+), 0 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 6ab5e2d..f6f3fcb 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -117,6 +117,16 @@ void nf_unregister_hooks(struct nf_hook_
 int nf_register_sockopt(struct nf_sockopt_ops *reg);
 void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
 
+#ifdef CONFIG_SYSCTL
+/* Sysctl registration */
+struct ctl_table_header *nf_register_sysctl_table(struct ctl_table *path,
+						  struct ctl_table *table);
+void nf_unregister_sysctl_table(struct ctl_table_header *header,
+				struct ctl_table *table);
+extern struct ctl_table nf_net_netfilter_sysctl_path[];
+extern struct ctl_table nf_net_ipv4_netfilter_sysctl_path[];
+#endif /* CONFIG_SYSCTL */
+
 extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
 
 /* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 6364df0..664ddcf 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -75,6 +75,12 @@ struct nf_conntrack_l3proto
 	int (*nfattr_to_tuple)(struct nfattr *tb[],
 			       struct nf_conntrack_tuple *t);
 
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header	*ctl_table_header;
+	struct ctl_table	*ctl_table_path;
+	struct ctl_table	*ctl_table;
+#endif /* CONFIG_SYSCTL */
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index c22804a..fe1e8fa 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -76,6 +76,12 @@ struct nf_conntrack_l4proto
 	int (*nfattr_to_tuple)(struct nfattr *tb[],
 			       struct nf_conntrack_tuple *t);
 
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header	**ctl_table_header;
+	struct ctl_table	*ctl_table;
+	unsigned int		*ctl_table_users;
+#endif /* CONFIG_SYSCTL */
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 627105d..84d529d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -4,6 +4,7 @@ nf_conntrack-y	:= nf_conntrack_core.o nf
 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
+obj-$(CONFIG_SYSCTL) += nf_sysctl.o
 
 obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index a6a3b1d..941b5c3 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
 #include <linux/stddef.h>
@@ -30,6 +31,34 @@ #include <net/netfilter/nf_conntrack_cor
 struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly;
 struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly;
 
+#ifdef CONFIG_SYSCTL
+static DEFINE_MUTEX(nf_ct_proto_sysctl_mutex);
+
+static int
+nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_table *path,
+		      struct ctl_table *table, unsigned int *users)
+{
+	if (*header == NULL) {
+		*header = nf_register_sysctl_table(path, table);
+		if (*header == NULL)
+			return -ENOMEM;
+	}
+	if (users != NULL)
+		(*users)++;
+	return 0;
+}
+
+static void
+nf_ct_unregister_sysctl(struct ctl_table_header **header,
+			struct ctl_table *table, unsigned int *users)
+{
+	if (users != NULL && --*users > 0)
+		return;
+	nf_unregister_sysctl_table(*header, table);
+	*header = NULL;
+}
+#endif
+
 struct nf_conntrack_l4proto *
 __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto)
 {
@@ -124,6 +153,33 @@ static int kill_l4proto(struct nf_conn *
 			l4proto->l3proto);
 }
 
+static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
+{
+	int err = 0;
+
+#ifdef CONFIG_SYSCTL
+	mutex_lock(&nf_ct_proto_sysctl_mutex);
+	if (l3proto->ctl_table != NULL) {
+		err = nf_ct_register_sysctl(&l3proto->ctl_table_header,
+					    l3proto->ctl_table_path,
+					    l3proto->ctl_table, NULL);
+	}
+	mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif
+	return err;
+}
+
+static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto)
+{
+#ifdef CONFIG_SYSCTL
+	mutex_lock(&nf_ct_proto_sysctl_mutex);
+	if (l3proto->ctl_table_header != NULL)
+		nf_ct_unregister_sysctl(&l3proto->ctl_table_header,
+					l3proto->ctl_table, NULL);
+	mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif
+}
+
 int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
 {
 	int ret = 0;
@@ -139,6 +195,12 @@ int nf_conntrack_l3proto_register(struct
 		goto out_unlock;
 	}
 	nf_ct_l3protos[proto->l3proto] = proto;
+	write_unlock_bh(&nf_conntrack_lock);
+
+	ret = nf_ct_l3proto_register_sysctl(proto);
+	if (ret < 0)
+		nf_conntrack_l3proto_unregister(proto);
+	return ret;
 
 out_unlock:
 	write_unlock_bh(&nf_conntrack_lock);
@@ -165,6 +227,8 @@ int nf_conntrack_l3proto_unregister(stru
 	nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic;
 	write_unlock_bh(&nf_conntrack_lock);
 
+	nf_ct_l3proto_unregister_sysctl(proto);
+
 	/* Somebody could be still looking at the proto in bh. */
 	synchronize_net();
 
@@ -175,6 +239,36 @@ out:
 	return ret;
 }
 
+static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto)
+{
+	int err = 0;
+
+#ifdef CONFIG_SYSCTL
+	mutex_lock(&nf_ct_proto_sysctl_mutex);
+	if (l4proto->ctl_table != NULL) {
+		err = nf_ct_register_sysctl(l4proto->ctl_table_header,
+					    nf_net_netfilter_sysctl_path,
+					    l4proto->ctl_table,
+					    l4proto->ctl_table_users);
+	}
+	mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif
+	return err;
+}
+
+static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto)
+{
+#ifdef CONFIG_SYSCTL
+	mutex_lock(&nf_ct_proto_sysctl_mutex);
+	if (l4proto->ctl_table_header != NULL &&
+	    *l4proto->ctl_table_header != NULL)
+		nf_ct_unregister_sysctl(l4proto->ctl_table_header,
+					l4proto->ctl_table,
+					l4proto->ctl_table_users);
+	mutex_unlock(&nf_ct_proto_sysctl_mutex);
+#endif
+}
+
 /* FIXME: Allow NULL functions and sub in pointers to generic for
    them. --RR */
 int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
@@ -230,6 +324,12 @@ retry:
 	}
 
 	nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto;
+	write_unlock_bh(&nf_conntrack_lock);
+
+	ret = nf_ct_l4proto_register_sysctl(l4proto);
+	if (ret < 0)
+		nf_conntrack_l4proto_unregister(l4proto);
+	return ret;
 
 out_unlock:
 	write_unlock_bh(&nf_conntrack_lock);
@@ -257,6 +357,8 @@ int nf_conntrack_l4proto_unregister(stru
 		= &nf_conntrack_l4proto_generic;
 	write_unlock_bh(&nf_conntrack_lock);
 
+	nf_ct_l4proto_unregister_sysctl(l4proto);
+
 	/* Somebody could be still looking at the proto in bh. */
 	synchronize_net();
 
diff --git a/net/netfilter/nf_sysctl.c b/net/netfilter/nf_sysctl.c
new file mode 100644
index 0000000..06ddddb
--- /dev/null
+++ b/net/netfilter/nf_sysctl.c
@@ -0,0 +1,134 @@
+/* nf_sysctl.c	netfilter sysctl registration/unregistation
+ *
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ */
+#include <linux/module.h>
+#include <linux/sysctl.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+static void
+path_free(struct ctl_table *path, struct ctl_table *table)
+{
+	struct ctl_table *t, *next;
+
+	for (t = path; t != NULL && t != table; t = next) {
+		next = t->child;
+		kfree(t);
+	}
+}
+
+static struct ctl_table *
+path_dup(struct ctl_table *path, struct ctl_table *table)
+{
+	struct ctl_table *t, *last = NULL, *tmp;
+
+	for (t = path; t != NULL; t = t->child) {
+		/* twice the size since path elements are terminated by an
+		 * empty element */
+		tmp = kmemdup(t, 2 * sizeof(*t), GFP_KERNEL);
+		if (tmp == NULL) {
+			if (last != NULL)
+				path_free(path, table);
+			return NULL;
+		}
+
+		if (last != NULL)
+			last->child = tmp;
+		else
+			path = tmp;
+		last = tmp;
+	}
+
+	if (last != NULL)
+		last->child = table;
+	else
+		path = table;
+
+	return path;
+}
+
+struct ctl_table_header *
+nf_register_sysctl_table(struct ctl_table *path, struct ctl_table *table)
+{
+	struct ctl_table_header *header;
+
+	path = path_dup(path, table);
+	if (path == NULL)
+		return NULL;
+	header = register_sysctl_table(path, 0);
+	if (header == NULL)
+		path_free(path, table);
+	return header;
+}
+EXPORT_SYMBOL_GPL(nf_register_sysctl_table);
+
+void
+nf_unregister_sysctl_table(struct ctl_table_header *header,
+			   struct ctl_table *table)
+{
+	struct ctl_table *path = header->ctl_table;
+
+	unregister_sysctl_table(header);
+	path_free(path, table);
+}
+EXPORT_SYMBOL_GPL(nf_unregister_sysctl_table);
+
+/* net/netfilter */
+static struct ctl_table nf_net_netfilter_table[] = {
+	{
+		.ctl_name	= NET_NETFILTER,
+		.procname	= "netfilter",
+		.mode		= 0555,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+struct ctl_table nf_net_netfilter_sysctl_path[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.mode		= 0555,
+		.child		= nf_net_netfilter_table,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path);
+
+/* net/ipv4/netfilter */
+static struct ctl_table nf_net_ipv4_netfilter_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NETFILTER,
+		.procname	= "netfilter",
+		.mode		= 0555,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+static struct ctl_table nf_net_ipv4_table[] = {
+	{
+		.ctl_name	= NET_IPV4,
+		.procname	= "ipv4",
+		.mode		= 0555,
+		.child		= nf_net_ipv4_netfilter_table,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+struct ctl_table nf_net_ipv4_netfilter_sysctl_path[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.mode		= 0555,
+		.child		= nf_net_ipv4_table,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 15/33]: nf_conntrack: move conntrack protocol sysctls to individual modules
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (13 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 14/33]: nf_conntrack: automatic sysctl registation for conntrack protocols Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 16/33]: nf_conntrack: sysctl compatibility with old connection tracking Patrick McHardy
                   ` (18 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: move conntrack protocol sysctls to individual modules

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit bcd8d5a98d1a3c257d15c1cfa038aa0bf0e0ea44
tree 70a66b6930977099d64304a8ae13b12d5d3e6336
parent d8467cb91235e63cf7d36cdea1e6336a4df217bd
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:22 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:13:32 +0100

 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |   53 ---------
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c   |   23 ++++
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   55 +--------
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c |   23 ++++
 net/netfilter/nf_conntrack_core.c              |    8 +
 net/netfilter/nf_conntrack_proto.c             |   12 ++
 net/netfilter/nf_conntrack_proto_generic.c     |   23 ++++
 net/netfilter/nf_conntrack_proto_sctp.c        |  101 ++++++-----------
 net/netfilter/nf_conntrack_proto_tcp.c         |  140 ++++++++++++++++++++++--
 net/netfilter/nf_conntrack_proto_udp.c         |   40 ++++++-
 net/netfilter/nf_conntrack_standalone.c        |  142 ------------------------
 11 files changed, 293 insertions(+), 327 deletions(-)

diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index d190708..786c4ce 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -266,44 +266,6 @@ static struct nf_hook_ops ipv4_conntrack
 	},
 };
 
-#ifdef CONFIG_SYSCTL
-/* From nf_conntrack_proto_icmp.c */
-extern unsigned int nf_ct_icmp_timeout;
-static struct ctl_table_header *nf_ct_ipv4_sysctl_header;
-
-static ctl_table nf_ct_sysctl_table[] = {
-	{
-		.ctl_name	= NET_NF_CONNTRACK_ICMP_TIMEOUT,
-		.procname	= "nf_conntrack_icmp_timeout",
-		.data		= &nf_ct_icmp_timeout,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-        { .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_netfilter_table[] = {
-	{
-		.ctl_name       = NET_NETFILTER,
-		.procname       = "netfilter",
-		.mode           = 0555,
-		.child          = nf_ct_sysctl_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_net_table[] = {
-	{
-		.ctl_name       = CTL_NET,
-		.procname       = "net",
-		.mode           = 0555,
-		.child          = nf_ct_netfilter_table,
-	},
-	{ .ctl_name = 0 }
-};
-#endif
-
 /* Fast function for those who don't want to parse /proc (and I don't
    blame them). */
 /* Reversing the socket's dst/src point of view gives us the reply
@@ -472,20 +434,8 @@ static int __init nf_conntrack_l3proto_i
 		printk("nf_conntrack_ipv4: can't register hooks.\n");
 		goto cleanup_ipv4;
 	}
-#ifdef CONFIG_SYSCTL
-	nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
-	if (nf_ct_ipv4_sysctl_header == NULL) {
-		printk("nf_conntrack: can't register to sysctl.\n");
-		ret = -ENOMEM;
-		goto cleanup_hooks;
-	}
-#endif
 	return ret;
 
-#ifdef CONFIG_SYSCTL
- cleanup_hooks:
-	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
-#endif
  cleanup_ipv4:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
  cleanup_icmp:
@@ -502,9 +452,6 @@ #endif
 static void __exit nf_conntrack_l3proto_ipv4_fini(void)
 {
 	synchronize_net();
-#ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
-#endif
 	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 95fc22b..c59f281 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -25,7 +25,7 @@ #include <net/netfilter/nf_conntrack_tup
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
-unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
+static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
 
 #if 0
 #define DEBUGP printk
@@ -321,6 +321,23 @@ static int icmp_nfattr_to_tuple(struct n
 }
 #endif
 
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *icmp_sysctl_header;
+static struct ctl_table icmp_sysctl_table[] = {
+	{
+		.ctl_name	= NET_NF_CONNTRACK_ICMP_TIMEOUT,
+		.procname	= "nf_conntrack_icmp_timeout",
+		.data		= &nf_ct_icmp_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+        {
+		.ctl_name = 0
+	}
+};
+#endif /* CONFIG_SYSCTL */
+
 struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
 {
 	.l3proto		= PF_INET,
@@ -340,6 +357,10 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr	= icmp_tuple_to_nfattr,
 	.nfattr_to_tuple	= icmp_nfattr_to_tuple,
 #endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_header	= &icmp_sysctl_header,
+	.ctl_table		= icmp_sysctl_table,
+#endif
 };
 
 EXPORT_SYMBOL(nf_conntrack_l4proto_icmp);
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 9108ecc..a20615f 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -324,21 +324,7 @@ static struct nf_hook_ops ipv6_conntrack
 };
 
 #ifdef CONFIG_SYSCTL
-
-/* From nf_conntrack_proto_icmpv6.c */
-extern unsigned int nf_ct_icmpv6_timeout;
-
-static struct ctl_table_header *nf_ct_ipv6_sysctl_header;
-
-static ctl_table nf_ct_sysctl_table[] = {
-	{
-		.ctl_name	= NET_NF_CONNTRACK_ICMPV6_TIMEOUT,
-		.procname	= "nf_conntrack_icmpv6_timeout",
-		.data		= &nf_ct_icmpv6_timeout,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
+static ctl_table nf_ct_ipv6_sysctl_table[] = {
 	{
 		.ctl_name	= NET_NF_CONNTRACK_FRAG6_TIMEOUT,
 		.procname	= "nf_conntrack_frag6_timeout",
@@ -365,26 +351,6 @@ static ctl_table nf_ct_sysctl_table[] = 
 	},
         { .ctl_name = 0 }
 };
-
-static ctl_table nf_ct_netfilter_table[] = {
-	{
-		.ctl_name	= NET_NETFILTER,
-		.procname	= "netfilter",
-		.mode		= 0555,
-		.child		= nf_ct_sysctl_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_net_table[] = {
-	{
-		.ctl_name	= CTL_NET,
-		.procname	= "net",
-		.mode		= 0555,
-		.child		= nf_ct_netfilter_table,
-	},
-	{ .ctl_name = 0 }
-};
 #endif
 
 #if defined(CONFIG_NF_CT_NETLINK) || \
@@ -442,6 +408,10 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr	= ipv6_tuple_to_nfattr,
 	.nfattr_to_tuple	= ipv6_nfattr_to_tuple,
 #endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_path		= nf_net_netfilter_sysctl_path,
+	.ctl_table		= nf_ct_ipv6_sysctl_table,
+#endif
 	.get_features		= ipv6_get_features,
 	.me			= THIS_MODULE,
 };
@@ -492,20 +462,8 @@ static int __init nf_conntrack_l3proto_i
 		       "hook.\n");
 		goto cleanup_ipv6;
 	}
-#ifdef CONFIG_SYSCTL
-	nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
-	if (nf_ct_ipv6_sysctl_header == NULL) {
-		printk("nf_conntrack: can't register to sysctl.\n");
-		ret = -ENOMEM;
-		goto cleanup_hooks;
-	}
-#endif
 	return ret;
 
-#ifdef CONFIG_SYSCTL
- cleanup_hooks:
-	nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
-#endif
  cleanup_ipv6:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
  cleanup_icmpv6:
@@ -522,9 +480,6 @@ #endif
 static void __exit nf_conntrack_l3proto_ipv6_fini(void)
 {
 	synchronize_net();
-#ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
-#endif
 	nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index b3b468c..1e8e700 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -33,7 +33,7 @@ #include <net/netfilter/nf_conntrack_l4p
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
 
-unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
+static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
 
 #if 0
 #define DEBUGP printk
@@ -298,6 +298,23 @@ static int icmpv6_nfattr_to_tuple(struct
 }
 #endif
 
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *icmpv6_sysctl_header;
+static struct ctl_table icmpv6_sysctl_table[] = {
+	{
+		.ctl_name	= NET_NF_CONNTRACK_ICMPV6_TIMEOUT,
+		.procname	= "nf_conntrack_icmpv6_timeout",
+		.data		= &nf_ct_icmpv6_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_SYSCTL */
+
 struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
 {
 	.l3proto		= PF_INET6,
@@ -315,6 +332,10 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr	= icmpv6_tuple_to_nfattr,
 	.nfattr_to_tuple	= icmpv6_nfattr_to_tuple,
 #endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_header	= &icmpv6_sysctl_header,
+	.ctl_table		= icmpv6_sysctl_table,
+#endif
 };
 
 EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3e7c0a9..4b97279 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1070,6 +1070,8 @@ void nf_conntrack_cleanup(void)
 	free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
 			    nf_conntrack_htable_size);
 
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_generic);
+
 	/* free l3proto protocol tables */
 	for (i = 0; i < PF_MAX; i++)
 		if (nf_ct_protos[i]) {
@@ -1195,6 +1197,10 @@ int __init nf_conntrack_init(void)
 		goto err_free_conntrack_slab;
 	}
 
+	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_generic);
+	if (ret < 0)
+		goto out_free_expect_slab;
+
 	/* Don't NEED lock here, but good form anyway. */
 	write_lock_bh(&nf_conntrack_lock);
         for (i = 0; i < AF_MAX; i++)
@@ -1212,6 +1218,8 @@ int __init nf_conntrack_init(void)
 
 	return ret;
 
+out_free_expect_slab:
+	kmem_cache_destroy(nf_conntrack_expect_cachep);
 err_free_conntrack_slab:
 	nf_conntrack_unregister_cache(NF_CT_F_BASIC);
 err_free_hash:
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 941b5c3..891c9c5 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -252,7 +252,7 @@ #ifdef CONFIG_SYSCTL
 					    l4proto->ctl_table_users);
 	}
 	mutex_unlock(&nf_ct_proto_sysctl_mutex);
-#endif
+#endif /* CONFIG_SYSCTL */
 	return err;
 }
 
@@ -266,7 +266,7 @@ #ifdef CONFIG_SYSCTL
 					l4proto->ctl_table,
 					l4proto->ctl_table_users);
 	mutex_unlock(&nf_ct_proto_sysctl_mutex);
-#endif
+#endif /* CONFIG_SYSCTL */
 }
 
 /* FIXME: Allow NULL functions and sub in pointers to generic for
@@ -280,6 +280,9 @@ int nf_conntrack_l4proto_register(struct
 		goto out;
 	}
 
+	if (l4proto == &nf_conntrack_l4proto_generic)
+		return nf_ct_l4proto_register_sysctl(l4proto);
+
 retry:
 	write_lock_bh(&nf_conntrack_lock);
 	if (nf_ct_protos[l4proto->l3proto]) {
@@ -346,6 +349,11 @@ int nf_conntrack_l4proto_unregister(stru
 		goto out;
 	}
 
+	if (l4proto == &nf_conntrack_l4proto_generic) {
+		nf_ct_l4proto_unregister_sysctl(l4proto);
+		goto out;
+	}
+
 	write_lock_bh(&nf_conntrack_lock);
 	if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
 	    != l4proto) {
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index f44811e..15306b9 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -17,7 +17,7 @@ #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 
-unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
+static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
 
 static int generic_pkt_to_tuple(const struct sk_buff *skb,
 				unsigned int dataoff,
@@ -71,6 +71,23 @@ static int new(struct nf_conn *conntrack
 	return 1;
 }
 
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *generic_sysctl_header;
+static struct ctl_table generic_sysctl_table[] = {
+	{
+		.ctl_name	= NET_NF_CONNTRACK_GENERIC_TIMEOUT,
+		.procname	= "nf_conntrack_generic_timeout",
+		.data		= &nf_ct_generic_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_SYSCTL */
+
 struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
 {
 	.l3proto		= PF_UNSPEC,
@@ -82,4 +99,8 @@ struct nf_conntrack_l4proto nf_conntrack
 	.print_conntrack	= generic_print_conntrack,
 	.packet			= packet,
 	.new			= new,
+#ifdef CONFIG_SYSCTL
+	.ctl_table_header	= &generic_sysctl_header,
+	.ctl_table		= generic_sysctl_table,
+#endif
 };
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 5115619..cc69330 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -509,36 +509,10 @@ static int sctp_new(struct nf_conn *conn
 	return 1;
 }
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
-	.l3proto	 = PF_INET,
-	.l4proto 	 = IPPROTO_SCTP,
-	.name 		 = "sctp",
-	.pkt_to_tuple 	 = sctp_pkt_to_tuple, 
-	.invert_tuple 	 = sctp_invert_tuple, 
-	.print_tuple 	 = sctp_print_tuple, 
-	.print_conntrack = sctp_print_conntrack,
-	.packet 	 = sctp_packet, 
-	.new 		 = sctp_new, 
-	.destroy 	 = NULL, 
-	.me 		 = THIS_MODULE 
-};
-
-struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
-	.l3proto	 = PF_INET6,
-	.l4proto 	 = IPPROTO_SCTP,
-	.name 		 = "sctp",
-	.pkt_to_tuple 	 = sctp_pkt_to_tuple, 
-	.invert_tuple 	 = sctp_invert_tuple, 
-	.print_tuple 	 = sctp_print_tuple, 
-	.print_conntrack = sctp_print_conntrack,
-	.packet 	 = sctp_packet, 
-	.new 		 = sctp_new, 
-	.destroy 	 = NULL, 
-	.me 		 = THIS_MODULE 
-};
-
 #ifdef CONFIG_SYSCTL
-static ctl_table nf_ct_sysctl_table[] = {
+static unsigned int sctp_sysctl_table_users;
+static struct ctl_table_header *sctp_sysctl_header;
+static struct ctl_table sctp_sysctl_table[] = {
 	{
 		.ctl_name	= NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
 		.procname	= "nf_conntrack_sctp_timeout_closed",
@@ -595,31 +569,47 @@ static ctl_table nf_ct_sysctl_table[] = 
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_jiffies,
 	},
-	{ .ctl_name = 0 }
-};
-
-static ctl_table nf_ct_netfilter_table[] = {
 	{
-		.ctl_name	= NET_NETFILTER,
-		.procname	= "netfilter",
-		.mode		= 0555,
-		.child		= nf_ct_sysctl_table,
-	},
-	{ .ctl_name = 0 }
+		.ctl_name = 0
+	}
 };
+#endif
 
-static ctl_table nf_ct_net_table[] = {
-	{
-		.ctl_name	= CTL_NET,
-		.procname	= "net",
-		.mode		= 0555, 
-		.child		= nf_ct_netfilter_table,
-	},
-	{ .ctl_name = 0 }
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
+	.l3proto		= PF_INET,
+	.l4proto 		= IPPROTO_SCTP,
+	.name 			= "sctp",
+	.pkt_to_tuple 		= sctp_pkt_to_tuple,
+	.invert_tuple 		= sctp_invert_tuple,
+	.print_tuple 		= sctp_print_tuple,
+	.print_conntrack	= sctp_print_conntrack,
+	.packet 		= sctp_packet,
+	.new 			= sctp_new,
+	.me 			= THIS_MODULE,
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &sctp_sysctl_table_users,
+	.ctl_table_header	= &sctp_sysctl_header,
+	.ctl_table		= sctp_sysctl_table,
+#endif
 };
 
-static struct ctl_table_header *nf_ct_sysctl_header;
+struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
+	.l3proto		= PF_INET6,
+	.l4proto 		= IPPROTO_SCTP,
+	.name 			= "sctp",
+	.pkt_to_tuple 		= sctp_pkt_to_tuple,
+	.invert_tuple 		= sctp_invert_tuple,
+	.print_tuple 		= sctp_print_tuple,
+	.print_conntrack	= sctp_print_conntrack,
+	.packet 		= sctp_packet,
+	.new 			= sctp_new,
+	.me 			= THIS_MODULE,
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &sctp_sysctl_table_users,
+	.ctl_table_header	= &sctp_sysctl_header,
+	.ctl_table		= sctp_sysctl_table,
 #endif
+};
 
 int __init nf_conntrack_proto_sctp_init(void)
 {
@@ -636,20 +626,8 @@ int __init nf_conntrack_proto_sctp_init(
 		goto cleanup_sctp4;
 	}
 
-#ifdef CONFIG_SYSCTL
-	nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
-	if (nf_ct_sysctl_header == NULL) {
-		printk("nf_conntrack_proto_sctp: can't register to sysctl.\n");
-		goto cleanup;
-	}
-#endif
-
 	return ret;
 
-#ifdef CONFIG_SYSCTL
- cleanup:
-	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
-#endif
  cleanup_sctp4:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
  out:
@@ -662,9 +640,6 @@ void __exit nf_conntrack_proto_sctp_fini
 {
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
-#ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(nf_ct_sysctl_header);
-#endif
 	DEBUGP("SCTP conntrack module unloaded\n");
 }
 
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 32b88b7..6f6f9a0 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -93,22 +93,22 @@ #define MINS * 60 SECS
 #define HOURS * 60 MINS
 #define DAYS * 24 HOURS
 
-unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly =      2 MINS;
-unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly =     60 SECS;
-unsigned int nf_ct_tcp_timeout_established __read_mostly =   5 DAYS;
-unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly =      2 MINS;
-unsigned int nf_ct_tcp_timeout_close_wait __read_mostly =   60 SECS;
-unsigned int nf_ct_tcp_timeout_last_ack __read_mostly =     30 SECS;
-unsigned int nf_ct_tcp_timeout_time_wait __read_mostly =     2 MINS;
-unsigned int nf_ct_tcp_timeout_close __read_mostly =        10 SECS;
+static unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly =      2 MINS;
+static unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly =     60 SECS;
+static unsigned int nf_ct_tcp_timeout_established __read_mostly =   5 DAYS;
+static unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly =      2 MINS;
+static unsigned int nf_ct_tcp_timeout_close_wait __read_mostly =   60 SECS;
+static unsigned int nf_ct_tcp_timeout_last_ack __read_mostly =     30 SECS;
+static unsigned int nf_ct_tcp_timeout_time_wait __read_mostly =     2 MINS;
+static unsigned int nf_ct_tcp_timeout_close __read_mostly =        10 SECS;
 
 /* RFC1122 says the R2 limit should be at least 100 seconds.
    Linux uses 15 packets as limit, which corresponds 
    to ~13-30min depending on RTO. */
-unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly =   5 MINS;
+static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly =   5 MINS;
  
-static unsigned int * tcp_timeouts[]
-= { NULL,                              /* TCP_CONNTRACK_NONE */
+static unsigned int * tcp_timeouts[] = {
+    NULL,                              /* TCP_CONNTRACK_NONE */
     &nf_ct_tcp_timeout_syn_sent,       /* TCP_CONNTRACK_SYN_SENT, */
     &nf_ct_tcp_timeout_syn_recv,       /* TCP_CONNTRACK_SYN_RECV, */
     &nf_ct_tcp_timeout_established,    /* TCP_CONNTRACK_ESTABLISHED, */
@@ -1168,7 +1168,113 @@ static int nfattr_to_tcp(struct nfattr *
 	return 0;
 }
 #endif
-  
+
+#ifdef CONFIG_SYSCTL
+static unsigned int tcp_sysctl_table_users;
+static struct ctl_table_header *tcp_sysctl_header;
+static struct ctl_table tcp_sysctl_table[] = {
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
+		.procname	= "nf_conntrack_tcp_timeout_syn_sent",
+		.data		= &nf_ct_tcp_timeout_syn_sent,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
+		.procname	= "nf_conntrack_tcp_timeout_syn_recv",
+		.data		= &nf_ct_tcp_timeout_syn_recv,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
+		.procname	= "nf_conntrack_tcp_timeout_established",
+		.data		= &nf_ct_tcp_timeout_established,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
+		.procname	= "nf_conntrack_tcp_timeout_fin_wait",
+		.data		= &nf_ct_tcp_timeout_fin_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
+		.procname	= "nf_conntrack_tcp_timeout_close_wait",
+		.data		= &nf_ct_tcp_timeout_close_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
+		.procname	= "nf_conntrack_tcp_timeout_last_ack",
+		.data		= &nf_ct_tcp_timeout_last_ack,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
+		.procname	= "nf_conntrack_tcp_timeout_time_wait",
+		.data		= &nf_ct_tcp_timeout_time_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
+		.procname	= "nf_conntrack_tcp_timeout_close",
+		.data		= &nf_ct_tcp_timeout_close,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
+		.procname	= "nf_conntrack_tcp_timeout_max_retrans",
+		.data		= &nf_ct_tcp_timeout_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_LOOSE,
+		.procname	= "nf_conntrack_tcp_loose",
+		.data		= &nf_ct_tcp_loose,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_BE_LIBERAL,
+		.procname       = "nf_conntrack_tcp_be_liberal",
+		.data           = &nf_ct_tcp_be_liberal,
+		.maxlen         = sizeof(unsigned int),
+		.mode           = 0644,
+		.proc_handler   = &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_TCP_MAX_RETRANS,
+		.procname	= "nf_conntrack_tcp_max_retrans",
+		.data		= &nf_ct_tcp_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_SYSCTL */
+
 struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
 {
 	.l3proto		= PF_INET,
@@ -1188,6 +1294,11 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
 	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
 #endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &tcp_sysctl_table_users,
+	.ctl_table_header	= &tcp_sysctl_header,
+	.ctl_table		= tcp_sysctl_table,
+#endif
 };
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 =
@@ -1209,6 +1320,11 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
 	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
 #endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &tcp_sysctl_table_users,
+	.ctl_table_header	= &tcp_sysctl_header,
+	.ctl_table		= tcp_sysctl_table,
+#endif
 };
 
 EXPORT_SYMBOL(nf_conntrack_l4proto_tcp4);
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 200d7d3..d86749c 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -29,8 +29,8 @@ #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
-unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
-unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
+static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
+static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
 
 static int udp_pkt_to_tuple(const struct sk_buff *skb,
 			     unsigned int dataoff,
@@ -148,6 +148,32 @@ static int udp_error(struct sk_buff *skb
 	return NF_ACCEPT;
 }
 
+#ifdef CONFIG_SYSCTL
+static unsigned int udp_sysctl_table_users;
+static struct ctl_table_header *udp_sysctl_header;
+static struct ctl_table udp_sysctl_table[] = {
+	{
+		.ctl_name	= NET_NF_CONNTRACK_UDP_TIMEOUT,
+		.procname	= "nf_conntrack_udp_timeout",
+		.data		= &nf_ct_udp_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
+		.procname	= "nf_conntrack_udp_timeout_stream",
+		.data		= &nf_ct_udp_timeout_stream,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_SYSCTL */
+
 struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
 {
 	.l3proto		= PF_INET,
@@ -165,6 +191,11 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
 	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
 #endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &udp_sysctl_table_users,
+	.ctl_table_header	= &udp_sysctl_header,
+	.ctl_table		= udp_sysctl_table,
+#endif
 };
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 =
@@ -184,6 +215,11 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
 	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
 #endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &udp_sysctl_table_users,
+	.ctl_table_header	= &udp_sysctl_header,
+	.ctl_table		= udp_sysctl_table,
+#endif
 };
 
 EXPORT_SYMBOL(nf_conntrack_l4proto_udp4);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 2283a26..9d89068 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -330,28 +330,6 @@ #endif /* CONFIG_PROC_FS */
 int nf_conntrack_checksum __read_mostly = 1;
 
 #ifdef CONFIG_SYSCTL
-
-/* From nf_conntrack_proto_tcp.c */
-extern unsigned int nf_ct_tcp_timeout_syn_sent;
-extern unsigned int nf_ct_tcp_timeout_syn_recv;
-extern unsigned int nf_ct_tcp_timeout_established;
-extern unsigned int nf_ct_tcp_timeout_fin_wait;
-extern unsigned int nf_ct_tcp_timeout_close_wait;
-extern unsigned int nf_ct_tcp_timeout_last_ack;
-extern unsigned int nf_ct_tcp_timeout_time_wait;
-extern unsigned int nf_ct_tcp_timeout_close;
-extern unsigned int nf_ct_tcp_timeout_max_retrans;
-extern int nf_ct_tcp_loose;
-extern int nf_ct_tcp_be_liberal;
-extern int nf_ct_tcp_max_retrans;
-
-/* From nf_conntrack_proto_udp.c */
-extern unsigned int nf_ct_udp_timeout;
-extern unsigned int nf_ct_udp_timeout_stream;
-
-/* From nf_conntrack_proto_generic.c */
-extern unsigned int nf_ct_generic_timeout;
-
 /* Log invalid packets of a given protocol */
 static int log_invalid_proto_min = 0;
 static int log_invalid_proto_max = 255;
@@ -392,94 +370,6 @@ static ctl_table nf_ct_sysctl_table[] = 
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
-		.procname	= "nf_conntrack_tcp_timeout_syn_sent",
-		.data		= &nf_ct_tcp_timeout_syn_sent,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
-		.procname	= "nf_conntrack_tcp_timeout_syn_recv",
-		.data		= &nf_ct_tcp_timeout_syn_recv,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
-		.procname	= "nf_conntrack_tcp_timeout_established",
-		.data		= &nf_ct_tcp_timeout_established,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
-		.procname	= "nf_conntrack_tcp_timeout_fin_wait",
-		.data		= &nf_ct_tcp_timeout_fin_wait,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
-		.procname	= "nf_conntrack_tcp_timeout_close_wait",
-		.data		= &nf_ct_tcp_timeout_close_wait,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
-		.procname	= "nf_conntrack_tcp_timeout_last_ack",
-		.data		= &nf_ct_tcp_timeout_last_ack,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
-		.procname	= "nf_conntrack_tcp_timeout_time_wait",
-		.data		= &nf_ct_tcp_timeout_time_wait,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
-		.procname	= "nf_conntrack_tcp_timeout_close",
-		.data		= &nf_ct_tcp_timeout_close,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_UDP_TIMEOUT,
-		.procname	= "nf_conntrack_udp_timeout",
-		.data		= &nf_ct_udp_timeout,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
-		.procname	= "nf_conntrack_udp_timeout_stream",
-		.data		= &nf_ct_udp_timeout_stream,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_GENERIC_TIMEOUT,
-		.procname	= "nf_conntrack_generic_timeout",
-		.data		= &nf_ct_generic_timeout,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
 		.ctl_name	= NET_NF_CONNTRACK_LOG_INVALID,
 		.procname	= "nf_conntrack_log_invalid",
 		.data		= &nf_ct_log_invalid,
@@ -490,38 +380,6 @@ static ctl_table nf_ct_sysctl_table[] = 
 		.extra1		= &log_invalid_proto_min,
 		.extra2		= &log_invalid_proto_max,
 	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
-		.procname	= "nf_conntrack_tcp_timeout_max_retrans",
-		.data		= &nf_ct_tcp_timeout_max_retrans,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_LOOSE,
-		.procname	= "nf_conntrack_tcp_loose",
-		.data		= &nf_ct_tcp_loose,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_BE_LIBERAL,
-		.procname       = "nf_conntrack_tcp_be_liberal",
-		.data           = &nf_ct_tcp_be_liberal,
-		.maxlen         = sizeof(unsigned int),
-		.mode           = 0644,
-		.proc_handler   = &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_NF_CONNTRACK_TCP_MAX_RETRANS,
-		.procname	= "nf_conntrack_tcp_max_retrans",
-		.data		= &nf_ct_tcp_max_retrans,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
 
 	{ .ctl_name = 0 }
 };

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 16/33]: nf_conntrack: sysctl compatibility with old connection tracking
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (14 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 15/33]: nf_conntrack: move conntrack protocol sysctls to individual modules Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 17/33]: nf_conntrack: /proc " Patrick McHardy
                   ` (17 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: sysctl compatibility with old connection tracking

This patch adds an option to keep the connection tracking sysctls visible
under their old names.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit acba3b4bada973eb5697d29accdd3dd734990019
tree 84fbdb635f018df25d304745513cee3903659cc3
parent bcd8d5a98d1a3c257d15c1cfa038aa0bf0e0ea44
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:24 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:13:33 +0100

 include/net/netfilter/nf_conntrack_l4proto.h   |    6 +
 net/ipv4/netfilter/Kconfig                     |   11 ++
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |   58 +++++++++++++
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c   |   18 ++++
 net/netfilter/nf_conntrack_core.c              |    2 
 net/netfilter/nf_conntrack_proto.c             |   20 ++++
 net/netfilter/nf_conntrack_proto_generic.c     |   18 ++++
 net/netfilter/nf_conntrack_proto_sctp.c        |   67 +++++++++++++++
 net/netfilter/nf_conntrack_proto_tcp.c         |  107 ++++++++++++++++++++++++
 net/netfilter/nf_conntrack_proto_udp.c         |   26 ++++++
 10 files changed, 332 insertions(+), 1 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index fe1e8fa..fc8af08 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -80,7 +80,11 @@ #ifdef CONFIG_SYSCTL
 	struct ctl_table_header	**ctl_table_header;
 	struct ctl_table	*ctl_table;
 	unsigned int		*ctl_table_users;
-#endif /* CONFIG_SYSCTL */
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	struct ctl_table_header	*ctl_compat_table_header;
+	struct ctl_table	*ctl_compat_table;
+#endif
+#endif
 
 	/* Module (if any) which this is connected to. */
 	struct module *me;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d88c292..4ac5b5c 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -19,6 +19,17 @@ config NF_CONNTRACK_IPV4
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NF_CONNTRACK_PROC_COMPAT
+	bool "proc/sysctl compatibility with old connection tracking"
+	depends on NF_CONNTRACK
+	default y
+	help
+	  This option enables /proc and sysctl compatibility with the old
+	  layer 3 dependant connection tracking. This is needed to keep
+	  old programs that have not been adapted to the new names working.
+
+	  If unsure, say Y.
+
 # connection tracking, helpers and protocols
 config IP_NF_CONNTRACK
 	tristate "Connection tracking (required for masq/NAT)"
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 786c4ce..bcec682 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -266,6 +266,60 @@ static struct nf_hook_ops ipv4_conntrack
 	},
 };
 
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+static int log_invalid_proto_min = 0;
+static int log_invalid_proto_max = 255;
+
+static ctl_table ip_ct_sysctl_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_MAX,
+		.procname	= "ip_conntrack_max",
+		.data		= &nf_conntrack_max,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_COUNT,
+		.procname	= "ip_conntrack_count",
+		.data		= &nf_conntrack_count,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_BUCKETS,
+		.procname	= "ip_conntrack_buckets",
+		.data		= &nf_conntrack_htable_size,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_CHECKSUM,
+		.procname	= "ip_conntrack_checksum",
+		.data		= &nf_conntrack_checksum,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_LOG_INVALID,
+		.procname	= "ip_conntrack_log_invalid",
+		.data		= &nf_ct_log_invalid,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &log_invalid_proto_min,
+		.extra2		= &log_invalid_proto_max,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_SYSCTL && CONFIG_NF_CONNTRACK_PROC_COMPAT */
+
 /* Fast function for those who don't want to parse /proc (and I don't
    blame them). */
 /* Reversing the socket's dst/src point of view gives us the reply
@@ -386,6 +440,10 @@ #if defined(CONFIG_NF_CT_NETLINK) || \
 	.tuple_to_nfattr = ipv4_tuple_to_nfattr,
 	.nfattr_to_tuple = ipv4_nfattr_to_tuple,
 #endif
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+	.ctl_table_path  = nf_net_ipv4_netfilter_sysctl_path,
+	.ctl_table	 = ip_ct_sysctl_table,
+#endif
 	.me		 = THIS_MODULE,
 };
 
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index c59f281..46aa44a 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -336,6 +336,21 @@ static struct ctl_table icmp_sysctl_tabl
 		.ctl_name = 0
 	}
 };
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table icmp_compat_sysctl_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
+		.procname	= "ip_conntrack_icmp_timeout",
+		.data		= &nf_ct_icmp_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+        {
+		.ctl_name = 0
+	}
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
@@ -360,6 +375,9 @@ #endif
 #ifdef CONFIG_SYSCTL
 	.ctl_table_header	= &icmp_sysctl_header,
 	.ctl_table		= icmp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	.ctl_compat_table	= icmp_compat_sysctl_table,
+#endif
 #endif
 };
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 4b97279..a672806 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -66,10 +66,12 @@ DEFINE_RWLOCK(nf_conntrack_lock);
 
 /* nf_conntrack_standalone needs this */
 atomic_t nf_conntrack_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL_GPL(nf_conntrack_count);
 
 void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
 unsigned int nf_conntrack_htable_size __read_mostly;
 int nf_conntrack_max __read_mostly;
+EXPORT_SYMBOL_GPL(nf_conntrack_max);
 struct list_head *nf_conntrack_hash __read_mostly;
 struct nf_conn nf_conntrack_untracked __read_mostly;
 unsigned int nf_ct_log_invalid __read_mostly;
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 891c9c5..4798afc 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -250,7 +250,22 @@ #ifdef CONFIG_SYSCTL
 					    nf_net_netfilter_sysctl_path,
 					    l4proto->ctl_table,
 					    l4proto->ctl_table_users);
+		if (err < 0)
+			goto out;
 	}
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	if (l4proto->ctl_compat_table != NULL) {
+		err = nf_ct_register_sysctl(&l4proto->ctl_compat_table_header,
+					    nf_net_ipv4_netfilter_sysctl_path,
+					    l4proto->ctl_compat_table, NULL);
+		if (err == 0)
+			goto out;
+		nf_ct_unregister_sysctl(l4proto->ctl_table_header,
+					l4proto->ctl_table,
+					l4proto->ctl_table_users);
+	}
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+out:
 	mutex_unlock(&nf_ct_proto_sysctl_mutex);
 #endif /* CONFIG_SYSCTL */
 	return err;
@@ -265,6 +280,11 @@ #ifdef CONFIG_SYSCTL
 		nf_ct_unregister_sysctl(l4proto->ctl_table_header,
 					l4proto->ctl_table,
 					l4proto->ctl_table_users);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	if (l4proto->ctl_compat_table_header != NULL)
+		nf_ct_unregister_sysctl(&l4proto->ctl_compat_table_header,
+					l4proto->ctl_compat_table, NULL);
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 	mutex_unlock(&nf_ct_proto_sysctl_mutex);
 #endif /* CONFIG_SYSCTL */
 }
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 15306b9..6990253 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -86,6 +86,21 @@ static struct ctl_table generic_sysctl_t
 		.ctl_name	= 0
 	}
 };
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table generic_compat_sysctl_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
+		.procname	= "ip_conntrack_generic_timeout",
+		.data		= &nf_ct_generic_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
@@ -102,5 +117,8 @@ struct nf_conntrack_l4proto nf_conntrack
 #ifdef CONFIG_SYSCTL
 	.ctl_table_header	= &generic_sysctl_header,
 	.ctl_table		= generic_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	.ctl_compat_table	= generic_compat_sysctl_table,
+#endif
 #endif
 };
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index cc69330..7c64b9c 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -573,6 +573,70 @@ static struct ctl_table sctp_sysctl_tabl
 		.ctl_name = 0
 	}
 };
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table sctp_compat_sysctl_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
+		.procname	= "ip_conntrack_sctp_timeout_closed",
+		.data		= &nf_ct_sctp_timeout_closed,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT,
+		.procname	= "ip_conntrack_sctp_timeout_cookie_wait",
+		.data		= &nf_ct_sctp_timeout_cookie_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED,
+		.procname	= "ip_conntrack_sctp_timeout_cookie_echoed",
+		.data		= &nf_ct_sctp_timeout_cookie_echoed,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED,
+		.procname	= "ip_conntrack_sctp_timeout_established",
+		.data		= &nf_ct_sctp_timeout_established,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT,
+		.procname	= "ip_conntrack_sctp_timeout_shutdown_sent",
+		.data		= &nf_ct_sctp_timeout_shutdown_sent,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD,
+		.procname	= "ip_conntrack_sctp_timeout_shutdown_recd",
+		.data		= &nf_ct_sctp_timeout_shutdown_recd,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT,
+		.procname	= "ip_conntrack_sctp_timeout_shutdown_ack_sent",
+		.data		= &nf_ct_sctp_timeout_shutdown_ack_sent,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name = 0
+	}
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
@@ -590,6 +654,9 @@ #ifdef CONFIG_SYSCTL
 	.ctl_table_users	= &sctp_sysctl_table_users,
 	.ctl_table_header	= &sctp_sysctl_header,
 	.ctl_table		= sctp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	.ctl_compat_table	= sctp_compat_sysctl_table,
+#endif
 #endif
 };
 
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6f6f9a0..d99c7c4 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1273,6 +1273,110 @@ static struct ctl_table tcp_sysctl_table
 		.ctl_name	= 0
 	}
 };
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table tcp_compat_sysctl_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
+		.procname	= "ip_conntrack_tcp_timeout_syn_sent",
+		.data		= &nf_ct_tcp_timeout_syn_sent,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
+		.procname	= "ip_conntrack_tcp_timeout_syn_recv",
+		.data		= &nf_ct_tcp_timeout_syn_recv,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
+		.procname	= "ip_conntrack_tcp_timeout_established",
+		.data		= &nf_ct_tcp_timeout_established,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
+		.procname	= "ip_conntrack_tcp_timeout_fin_wait",
+		.data		= &nf_ct_tcp_timeout_fin_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
+		.procname	= "ip_conntrack_tcp_timeout_close_wait",
+		.data		= &nf_ct_tcp_timeout_close_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
+		.procname	= "ip_conntrack_tcp_timeout_last_ack",
+		.data		= &nf_ct_tcp_timeout_last_ack,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
+		.procname	= "ip_conntrack_tcp_timeout_time_wait",
+		.data		= &nf_ct_tcp_timeout_time_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
+		.procname	= "ip_conntrack_tcp_timeout_close",
+		.data		= &nf_ct_tcp_timeout_close,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
+		.procname	= "ip_conntrack_tcp_timeout_max_retrans",
+		.data		= &nf_ct_tcp_timeout_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
+		.procname	= "ip_conntrack_tcp_loose",
+		.data		= &nf_ct_tcp_loose,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
+		.procname	= "ip_conntrack_tcp_be_liberal",
+		.data		= &nf_ct_tcp_be_liberal,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
+		.procname	= "ip_conntrack_tcp_max_retrans",
+		.data		= &nf_ct_tcp_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
@@ -1298,6 +1402,9 @@ #ifdef CONFIG_SYSCTL
 	.ctl_table_users	= &tcp_sysctl_table_users,
 	.ctl_table_header	= &tcp_sysctl_header,
 	.ctl_table		= tcp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	.ctl_compat_table	= tcp_compat_sysctl_table,
+#endif
 #endif
 };
 
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index d86749c..908fde7 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -172,6 +172,29 @@ static struct ctl_table udp_sysctl_table
 		.ctl_name	= 0
 	}
 };
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+static struct ctl_table udp_compat_sysctl_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
+		.procname	= "ip_conntrack_udp_timeout",
+		.data		= &nf_ct_udp_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
+		.procname	= "ip_conntrack_udp_timeout_stream",
+		.data		= &nf_ct_udp_timeout_stream,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
 struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
@@ -195,6 +218,9 @@ #ifdef CONFIG_SYSCTL
 	.ctl_table_users	= &udp_sysctl_table_users,
 	.ctl_table_header	= &udp_sysctl_header,
 	.ctl_table		= udp_sysctl_table,
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	.ctl_compat_table	= udp_compat_sysctl_table,
+#endif
 #endif
 };
 

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 17/33]: nf_conntrack: /proc compatibility with old connection tracking
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (15 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 16/33]: nf_conntrack: sysctl compatibility with old connection tracking Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 18/33]: conntrack: add '_get' to {ip, nf}_conntrack_expect_find Patrick McHardy
                   ` (16 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nf_conntrack: /proc compatibility with old connection tracking

This patch adds /proc/net/ip_conntrack, /proc/net/ip_conntrack_expect and
/proc/net/stat/ip_conntrack files to keep old programs using them working.

The /proc/net/ip_conntrack and /proc/net/ip_conntrack_expect files show only
IPv4 entries, the /proc/net/stat/ip_conntrack shows global statistics.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit f47bd635aca86e2410a66822cec2c85de4a06ae4
tree cf1684aac6802fec71fb47de38bbcdb4e3cc5036
parent acba3b4bada973eb5697d29accdd3dd734990019
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:25 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:00 +0100

 include/net/netfilter/ipv4/nf_conntrack_ipv4.h     |    3 
 net/ipv4/netfilter/Makefile                        |    5 
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c     |   13 +
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |  412 +++++++++++++++++++++++
 net/netfilter/nf_conntrack_l3proto_generic.c       |    1 
 net/netfilter/nf_conntrack_standalone.c            |    1 
 6 files changed, 434 insertions(+), 1 deletions(-)

diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 8c4f7e8..34b453a 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -41,4 +41,7 @@ extern struct nf_conntrack_l4proto nf_co
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
 
+extern int nf_conntrack_ipv4_compat_init(void);
+extern void nf_conntrack_ipv4_compat_fini(void);
+
 #endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 09aaed1..4ce20eb 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -89,6 +89,11 @@ obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
 
 # objects for l3 independent conntrack
 nf_conntrack_ipv4-objs  :=  nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
+ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
+ifeq ($(CONFIG_PROC_FS),y)
+nf_conntrack_ipv4-objs	+= nf_conntrack_l3proto_ipv4_compat.o
+endif
+endif
 
 # l3 independent conntrack
 obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index bcec682..f24e872 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -492,8 +492,16 @@ static int __init nf_conntrack_l3proto_i
 		printk("nf_conntrack_ipv4: can't register hooks.\n");
 		goto cleanup_ipv4;
 	}
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+	ret = nf_conntrack_ipv4_compat_init();
+	if (ret < 0)
+		goto cleanup_hooks;
+#endif
 	return ret;
-
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ cleanup_hooks:
+ 	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+#endif
  cleanup_ipv4:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
  cleanup_icmp:
@@ -510,6 +518,9 @@ static int __init nf_conntrack_l3proto_i
 static void __exit nf_conntrack_l3proto_ipv4_fini(void)
 {
 	synchronize_net();
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+	nf_conntrack_ipv4_compat_fini();
+#endif
 	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
new file mode 100644
index 0000000..3b31bc6
--- /dev/null
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -0,0 +1,412 @@
+/* ip_conntrack proc compat - based on ip_conntrack_standalone.c
+ *
+ * (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/percpu.h>
+
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#ifdef CONFIG_NF_CT_ACCT
+static unsigned int
+seq_print_counters(struct seq_file *s,
+		   const struct ip_conntrack_counter *counter)
+{
+	return seq_printf(s, "packets=%llu bytes=%llu ",
+			  (unsigned long long)counter->packets,
+			  (unsigned long long)counter->bytes);
+}
+#else
+#define seq_print_counters(x, y)	0
+#endif
+
+struct ct_iter_state {
+	unsigned int bucket;
+};
+
+static struct list_head *ct_get_first(struct seq_file *seq)
+{
+	struct ct_iter_state *st = seq->private;
+
+	for (st->bucket = 0;
+	     st->bucket < nf_conntrack_htable_size;
+	     st->bucket++) {
+		if (!list_empty(&nf_conntrack_hash[st->bucket]))
+			return nf_conntrack_hash[st->bucket].next;
+	}
+	return NULL;
+}
+
+static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+{
+	struct ct_iter_state *st = seq->private;
+
+	head = head->next;
+	while (head == &nf_conntrack_hash[st->bucket]) {
+		if (++st->bucket >= nf_conntrack_htable_size)
+			return NULL;
+		head = nf_conntrack_hash[st->bucket].next;
+	}
+	return head;
+}
+
+static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct list_head *head = ct_get_first(seq);
+
+	if (head)
+		while (pos && (head = ct_get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&nf_conntrack_lock);
+	return ct_get_idx(seq, *pos);
+}
+
+static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return ct_get_next(s, v);
+}
+
+static void ct_seq_stop(struct seq_file *s, void *v)
+{
+	read_unlock_bh(&nf_conntrack_lock);
+}
+
+static int ct_seq_show(struct seq_file *s, void *v)
+{
+	const struct nf_conntrack_tuple_hash *hash = v;
+	const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash);
+	struct nf_conntrack_l3proto *l3proto;
+	struct nf_conntrack_l4proto *l4proto;
+
+	NF_CT_ASSERT(ct);
+
+	/* we only want to print DIR_ORIGINAL */
+	if (NF_CT_DIRECTION(hash))
+		return 0;
+	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num != AF_INET)
+		return 0;
+
+	l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+				       .tuple.src.l3num);
+	NF_CT_ASSERT(l3proto);
+	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+				       .tuple.src.l3num,
+				       ct->tuplehash[IP_CT_DIR_ORIGINAL]
+				       .tuple.dst.protonum);
+	NF_CT_ASSERT(l4proto);
+
+	if (seq_printf(s, "%-8s %u %ld ",
+		      l4proto->name,
+		      ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
+		      timer_pending(&ct->timeout)
+		      ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
+		return -ENOSPC;
+
+	if (l3proto->print_conntrack(s, ct))
+		return -ENOSPC;
+
+	if (l4proto->print_conntrack(s, ct))
+		return -ENOSPC;
+
+	if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+			l3proto, l4proto))
+		return -ENOSPC;
+
+ 	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
+		return -ENOSPC;
+
+	if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
+		if (seq_printf(s, "[UNREPLIED] "))
+			return -ENOSPC;
+
+	if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
+			l3proto, l4proto))
+		return -ENOSPC;
+
+ 	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
+		return -ENOSPC;
+
+	if (test_bit(IPS_ASSURED_BIT, &ct->status))
+		if (seq_printf(s, "[ASSURED] "))
+			return -ENOSPC;
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+	if (seq_printf(s, "mark=%u ", ct->mark))
+		return -ENOSPC;
+#endif
+
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+	if (seq_printf(s, "secmark=%u ", ct->secmark))
+		return -ENOSPC;
+#endif
+
+	if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
+		return -ENOSPC;
+
+	return 0;
+}
+
+static struct seq_operations ct_seq_ops = {
+	.start = ct_seq_start,
+	.next  = ct_seq_next,
+	.stop  = ct_seq_stop,
+	.show  = ct_seq_show
+};
+
+static int ct_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	struct ct_iter_state *st;
+	int ret;
+
+	st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+	ret = seq_open(file, &ct_seq_ops);
+	if (ret)
+		goto out_free;
+	seq          = file->private_data;
+	seq->private = st;
+	memset(st, 0, sizeof(struct ct_iter_state));
+	return ret;
+out_free:
+	kfree(st);
+	return ret;
+}
+
+static struct file_operations ct_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = ct_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release_private,
+};
+
+/* expects */
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct list_head *e = &nf_conntrack_expect_list;
+	loff_t i;
+
+	/* strange seq_file api calls stop even if we fail,
+	 * thus we need to grab lock since stop unlocks */
+	read_lock_bh(&nf_conntrack_lock);
+
+	if (list_empty(e))
+		return NULL;
+
+	for (i = 0; i <= *pos; i++) {
+		e = e->next;
+		if (e == &nf_conntrack_expect_list)
+			return NULL;
+	}
+	return e;
+}
+
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ 	struct list_head *e = v;
+
+	++*pos;
+	e = e->next;
+
+	if (e == &nf_conntrack_expect_list)
+		return NULL;
+
+	return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
+	read_unlock_bh(&nf_conntrack_lock);
+}
+
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+	struct nf_conntrack_expect *exp = v;
+
+	if (exp->tuple.src.l3num != AF_INET)
+		return 0;
+
+	if (exp->timeout.function)
+		seq_printf(s, "%ld ", timer_pending(&exp->timeout)
+			   ? (long)(exp->timeout.expires - jiffies)/HZ : 0);
+	else
+		seq_printf(s, "- ");
+
+	seq_printf(s, "proto=%u ", exp->tuple.dst.protonum);
+
+	print_tuple(s, &exp->tuple,
+		    __nf_ct_l3proto_find(exp->tuple.src.l3num),
+		    __nf_ct_l4proto_find(exp->tuple.src.l3num,
+		    			 exp->tuple.dst.protonum));
+	return seq_putc(s, '\n');
+}
+
+static struct seq_operations exp_seq_ops = {
+	.start = exp_seq_start,
+	.next = exp_seq_next,
+	.stop = exp_seq_stop,
+	.show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &exp_seq_ops);
+}
+
+static struct file_operations ip_exp_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = exp_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+
+static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	int cpu;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return &per_cpu(nf_conntrack_stat, cpu);
+	}
+
+	return NULL;
+}
+
+static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	int cpu;
+
+	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return &per_cpu(nf_conntrack_stat, cpu);
+	}
+
+	return NULL;
+}
+
+static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int ct_cpu_seq_show(struct seq_file *seq, void *v)
+{
+	unsigned int nr_conntracks = atomic_read(&nf_conntrack_count);
+	struct ip_conntrack_stat *st = v;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "entries  searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error  expect_new expect_create expect_delete\n");
+		return 0;
+	}
+
+	seq_printf(seq, "%08x  %08x %08x %08x %08x %08x %08x %08x "
+			"%08x %08x %08x %08x %08x  %08x %08x %08x \n",
+		   nr_conntracks,
+		   st->searched,
+		   st->found,
+		   st->new,
+		   st->invalid,
+		   st->ignore,
+		   st->delete,
+		   st->delete_list,
+		   st->insert,
+		   st->insert_failed,
+		   st->drop,
+		   st->early_drop,
+		   st->error,
+
+		   st->expect_new,
+		   st->expect_create,
+		   st->expect_delete
+		);
+	return 0;
+}
+
+static struct seq_operations ct_cpu_seq_ops = {
+	.start  = ct_cpu_seq_start,
+	.next   = ct_cpu_seq_next,
+	.stop   = ct_cpu_seq_stop,
+	.show   = ct_cpu_seq_show,
+};
+
+static int ct_cpu_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ct_cpu_seq_ops);
+}
+
+static struct file_operations ct_cpu_seq_fops = {
+	.owner   = THIS_MODULE,
+	.open    = ct_cpu_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release_private,
+};
+
+int __init nf_conntrack_ipv4_compat_init(void)
+{
+	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+
+	proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
+	if (!proc)
+		goto err1;
+
+	proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+					&ip_exp_file_ops);
+	if (!proc_exp)
+		goto err2;
+
+	proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+	if (!proc_stat)
+		goto err3;
+
+	proc_stat->proc_fops = &ct_cpu_seq_fops;
+	proc_stat->owner = THIS_MODULE;
+
+	return 0;
+
+err3:
+	proc_net_remove("ip_conntrack_expect");
+err2:
+	proc_net_remove("ip_conntrack");
+err1:
+	return -ENOMEM;
+}
+
+void __exit nf_conntrack_ipv4_compat_fini(void)
+{
+	remove_proc_entry("ip_conntrack", proc_net_stat);
+	proc_net_remove("ip_conntrack_expect");
+	proc_net_remove("ip_conntrack");
+}
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 3124b3a..a3d31c3 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -92,3 +92,4 @@ struct nf_conntrack_l3proto nf_conntrack
 	.prepare	 = generic_prepare,
 	.get_features	 = generic_get_features,
 };
+EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 9d89068..3db24f4 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -52,6 +52,7 @@ print_tuple(struct seq_file *s, const st
 {
 	return l3proto->print_tuple(s, tuple) || l4proto->print_tuple(s, tuple);
 }
+EXPORT_SYMBOL_GPL(print_tuple);
 
 #ifdef CONFIG_NF_CT_ACCT
 static unsigned int

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 18/33]: conntrack: add '_get' to {ip, nf}_conntrack_expect_find
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (16 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 17/33]: nf_conntrack: /proc " Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 19/33]: ip_conntrack: fix NAT helper unload races Patrick McHardy
                   ` (15 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: conntrack: add '_get' to {ip, nf}_conntrack_expect_find

We usually uses 'xxx_find_get' for function which increments
reference count.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit c75fb025856b71ab4a7ceb837f77932c0ccd4b5d
tree 53dfe6884b52037b1b4b3875def5c09a4a046f17
parent f47bd635aca86e2410a66822cec2c85de4a06ae4
author Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> Tue, 28 Nov 2006 23:13:33 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:48 +0100

 include/linux/netfilter_ipv4/ip_conntrack.h   |    2 +-
 include/net/netfilter/nf_conntrack_expect.h   |    2 +-
 net/ipv4/netfilter/ip_conntrack_core.c        |    2 +-
 net/ipv4/netfilter/ip_conntrack_helper_pptp.c |    4 ++--
 net/ipv4/netfilter/ip_conntrack_netlink.c     |    4 ++--
 net/ipv4/netfilter/ip_conntrack_standalone.c  |    2 +-
 net/ipv4/netfilter/ip_nat_helper_pptp.c       |    2 +-
 net/netfilter/nf_conntrack_expect.c           |    2 +-
 net/netfilter/nf_conntrack_netlink.c          |    4 ++--
 net/netfilter/nf_conntrack_standalone.c       |    2 +-
 10 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 64e8680..61da569 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -277,7 +277,7 @@ extern struct ip_conntrack_expect *
 __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
 
 extern struct ip_conntrack_expect *
-ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple);
 
 extern struct ip_conntrack_tuple_hash *
 __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 5aa483e..2d335f0 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -53,7 +53,7 @@ struct nf_conntrack_expect *
 __nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
 
 struct nf_conntrack_expect *
-nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple);
 
 struct nf_conntrack_expect *
 find_expectation(const struct nf_conntrack_tuple *tuple);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 8b848aa..4d1f954 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -233,7 +233,7 @@ __ip_conntrack_expect_find(const struct 
 
 /* Just find a expectation corresponding to a tuple. */
 struct ip_conntrack_expect *
-ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
 {
 	struct ip_conntrack_expect *i;
 	
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index a2af5e0..a5c057b 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -142,7 +142,7 @@ static void pptp_expectfn(struct ip_conn
 		DEBUGP("trying to unexpect other dir: ");
 		DUMP_TUPLE(&inv_t);
 
-		exp_other = ip_conntrack_expect_find(&inv_t);
+		exp_other = ip_conntrack_expect_find_get(&inv_t);
 		if (exp_other) {
 			/* delete other expectation.  */
 			DEBUGP("found\n");
@@ -176,7 +176,7 @@ static int destroy_sibling_or_exp(const 
 		ip_conntrack_put(sibling);
 		return 1;
 	} else {
-		exp = ip_conntrack_expect_find(t);
+		exp = ip_conntrack_expect_find_get(t);
 		if (exp) {
 			DEBUGP("unexpect_related of expect %p\n", exp);
 			ip_conntrack_unexpect_related(exp);
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 1bb8ed3..3d277aa 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1256,7 +1256,7 @@ ctnetlink_get_expect(struct sock *ctnl, 
 	if (err < 0)
 		return err;
 
-	exp = ip_conntrack_expect_find(&tuple);
+	exp = ip_conntrack_expect_find_get(&tuple);
 	if (!exp)
 		return -ENOENT;
 
@@ -1309,7 +1309,7 @@ ctnetlink_del_expect(struct sock *ctnl, 
 			return err;
 
 		/* bump usage count to 2 */
-		exp = ip_conntrack_expect_find(&tuple);
+		exp = ip_conntrack_expect_find_get(&tuple);
 		if (!exp)
 			return -ENOENT;
 
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 0213575..2df6753 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -926,7 +926,7 @@ EXPORT_SYMBOL(__ip_ct_refresh_acct);
 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
 EXPORT_SYMBOL(ip_conntrack_expect_put);
 EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
-EXPORT_SYMBOL_GPL(ip_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
 EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index 329fdcd..acf55d8 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -101,7 +101,7 @@ static void pptp_nat_expected(struct ip_
 
 	DEBUGP("trying to unexpect other dir: ");
 	DUMP_TUPLE(&t);
-	other_exp = ip_conntrack_expect_find(&t);
+	other_exp = ip_conntrack_expect_find_get(&t);
 	if (other_exp) {
 		ip_conntrack_unexpect_related(other_exp);
 		ip_conntrack_expect_put(other_exp);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 79cfd79..aa5903e 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -68,7 +68,7 @@ __nf_conntrack_expect_find(const struct 
 
 /* Just find a expectation corresponding to a tuple. */
 struct nf_conntrack_expect *
-nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_expect *i;
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index dc08302..7357b8f 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1284,7 +1284,7 @@ ctnetlink_get_expect(struct sock *ctnl, 
 	if (err < 0)
 		return err;
 
-	exp = nf_conntrack_expect_find(&tuple);
+	exp = nf_conntrack_expect_find_get(&tuple);
 	if (!exp)
 		return -ENOENT;
 
@@ -1339,7 +1339,7 @@ ctnetlink_del_expect(struct sock *ctnl, 
 			return err;
 
 		/* bump usage count to 2 */
-		exp = nf_conntrack_expect_find(&tuple);
+		exp = nf_conntrack_expect_find_get(&tuple);
 		if (!exp)
 			return -ENOENT;
 
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 3db24f4..be94b63 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -549,7 +549,7 @@ EXPORT_SYMBOL(__nf_conntrack_find);
 EXPORT_SYMBOL(nf_ct_unlink_expect);
 EXPORT_SYMBOL(nf_conntrack_hash_insert);
 EXPORT_SYMBOL(__nf_conntrack_expect_find);
-EXPORT_SYMBOL(nf_conntrack_expect_find);
+EXPORT_SYMBOL(nf_conntrack_expect_find_get);
 EXPORT_SYMBOL(nf_conntrack_expect_list);
 #if defined(CONFIG_NF_CT_NETLINK) || \
     defined(CONFIG_NF_CT_NETLINK_MODULE)

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 19/33]: ip_conntrack: fix NAT helper unload races
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (17 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 18/33]: conntrack: add '_get' to {ip, nf}_conntrack_expect_find Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 20/33]: sip conntrack: minor cleanup Patrick McHardy
                   ` (14 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: ip_conntrack: fix NAT helper unload races

The NAT helpr hooks are protected by RCU, but all of the
conntrack helpers test and use the global pointers instead
of copying them first using rcu_dereference()

Also replace synchronize_net() by synchronize_rcu() for clarity
since sychronizing only with packet receive processing is
insufficient to prevent races.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit be8302ed9dba541073030f78208bd96304f13964
tree 1a7bebba0af91b0396af875fd3d4d39a7eb6a310
parent c75fb025856b71ab4a7ceb837f77932c0ccd4b5d
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:27 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:49 +0100

 net/ipv4/netfilter/ip_conntrack_amanda.c      |    9 +
 net/ipv4/netfilter/ip_conntrack_ftp.c         |    8 +
 net/ipv4/netfilter/ip_conntrack_helper_h323.c |  164 +++++++++++++++----------
 net/ipv4/netfilter/ip_conntrack_helper_pptp.c |   29 +++-
 net/ipv4/netfilter/ip_conntrack_irc.c         |   12 +-
 net/ipv4/netfilter/ip_conntrack_sip.c         |   12 +-
 net/ipv4/netfilter/ip_conntrack_tftp.c        |    6 +
 net/ipv4/netfilter/ip_nat_amanda.c            |    9 +
 net/ipv4/netfilter/ip_nat_ftp.c               |    9 +
 net/ipv4/netfilter/ip_nat_helper_h323.c       |   58 ++++-----
 net/ipv4/netfilter/ip_nat_helper_pptp.c       |   27 ++--
 net/ipv4/netfilter/ip_nat_irc.c               |    9 +
 net/ipv4/netfilter/ip_nat_sip.c               |   15 +-
 net/ipv4/netfilter/ip_nat_tftp.c              |    9 +
 net/netfilter/nf_conntrack_ftp.c              |    9 +
 15 files changed, 216 insertions(+), 169 deletions(-)

diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 7fca246..ad246ba 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -92,6 +92,7 @@ static int help(struct sk_buff **pskb,
 	char pbuf[sizeof("65535")], *tmp;
 	u_int16_t port, len;
 	int ret = NF_ACCEPT;
+	typeof(ip_nat_amanda_hook) ip_nat_amanda;
 
 	/* Only look at packets from the Amanda server */
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
@@ -161,9 +162,11 @@ static int help(struct sk_buff **pskb,
 		exp->mask.dst.protonum = 0xFF;
 		exp->mask.dst.u.tcp.port = htons(0xFFFF);
 
-		if (ip_nat_amanda_hook)
-			ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
-						 len, exp);
+		/* RCU read locked by nf_hook_slow */
+		ip_nat_amanda = rcu_dereference(ip_nat_amanda_hook);
+		if (ip_nat_amanda)
+			ret = ip_nat_amanda(pskb, ctinfo, off - dataoff,
+					    len, exp);
 		else if (ip_conntrack_expect_related(exp) != 0)
 			ret = NF_DROP;
 		ip_conntrack_expect_put(exp);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 93dcf96..0410c99 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -310,6 +310,7 @@ static int help(struct sk_buff **pskb,
 	struct ip_conntrack_expect *exp;
 	unsigned int i;
 	int found = 0, ends_in_nl;
+	typeof(ip_nat_ftp_hook) ip_nat_ftp;
 
 	/* Until there's been traffic both ways, don't look in packets. */
 	if (ctinfo != IP_CT_ESTABLISHED
@@ -433,9 +434,10 @@ static int help(struct sk_buff **pskb,
 
 	/* Now, NAT might want to mangle the packet, and register the
 	 * (possibly changed) expectation itself. */
-	if (ip_nat_ftp_hook)
-		ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
-				      matchoff, matchlen, exp, &seq);
+	ip_nat_ftp = rcu_dereference(ip_nat_ftp_hook);
+	if (ip_nat_ftp)
+		ret = ip_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
+				 matchoff, matchlen, exp, &seq);
 	else {
 		/* Can't expect this?  Best to drop packet now. */
 		if (ip_conntrack_expect_related(exp) != 0)
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index a06b340..aabfe1c 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -237,6 +237,7 @@ static int expect_rtp_rtcp(struct sk_buf
 	u_int16_t rtp_port;
 	struct ip_conntrack_expect *rtp_exp;
 	struct ip_conntrack_expect *rtcp_exp;
+	typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
 
 	/* Read RTP or RTCP address */
 	if (!get_h245_addr(*data, addr, &ip, &port) ||
@@ -279,11 +280,11 @@ static int expect_rtp_rtcp(struct sk_buf
 	rtcp_exp->flags = 0;
 
 	if (ct->tuplehash[dir].tuple.src.ip !=
-	    ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) {
+	    ct->tuplehash[!dir].tuple.dst.ip &&
+	    (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook))) {
 		/* NAT needed */
-		ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff,
-					addr, port, rtp_port, rtp_exp,
-					rtcp_exp);
+		ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+				   addr, port, rtp_port, rtp_exp, rtcp_exp);
 	} else {		/* Conntrack only */
 		rtp_exp->expectfn = NULL;
 		rtcp_exp->expectfn = NULL;
@@ -328,6 +329,7 @@ static int expect_t120(struct sk_buff **
 	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp = NULL;
+	typeof(nat_t120_hook) nat_t120;
 
 	/* Read T.120 address */
 	if (!get_h245_addr(*data, addr, &ip, &port) ||
@@ -350,10 +352,11 @@ static int expect_t120(struct sk_buff **
 	exp->flags = IP_CT_EXPECT_PERMANENT;	/* Accept multiple channels */
 
 	if (ct->tuplehash[dir].tuple.src.ip !=
-	    ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) {
+	    ct->tuplehash[!dir].tuple.dst.ip &&
+	    (nat_t120 = rcu_dereference(nat_t120_hook))) {
 		/* NAT needed */
-		ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr,
-				    port, exp);
+		ret = nat_t120(pskb, ct, ctinfo, data, dataoff, addr,
+			       port, exp);
 	} else {		/* Conntrack only */
 		exp->expectfn = NULL;
 		if (ip_conntrack_expect_related(exp) == 0) {
@@ -651,6 +654,7 @@ static int expect_h245(struct sk_buff **
 	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp = NULL;
+	typeof(nat_h245_hook) nat_h245;
 
 	/* Read h245Address */
 	if (!get_h225_addr(*data, addr, &ip, &port) ||
@@ -673,10 +677,11 @@ static int expect_h245(struct sk_buff **
 	exp->flags = 0;
 
 	if (ct->tuplehash[dir].tuple.src.ip !=
-	    ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) {
+	    ct->tuplehash[!dir].tuple.dst.ip &&
+	    (nat_h245 = rcu_dereference(nat_h245_hook))) {
 		/* NAT needed */
-		ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr,
-				    port, exp);
+		ret = nat_h245(pskb, ct, ctinfo, data, dataoff, addr,
+			       port, exp);
 	} else {		/* Conntrack only */
 		exp->expectfn = ip_conntrack_h245_expect;
 
@@ -712,6 +717,7 @@ static int expect_callforwarding(struct 
 	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp = NULL;
+	typeof(nat_callforwarding_hook) nat_callforwarding;
 
 	/* Read alternativeAddress */
 	if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
@@ -759,10 +765,11 @@ static int expect_callforwarding(struct 
 	exp->flags = 0;
 
 	if (ct->tuplehash[dir].tuple.src.ip !=
-	    ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) {
+	    ct->tuplehash[!dir].tuple.dst.ip &&
+	    (nat_callforwarding = rcu_dereference(nat_callforwarding_hook))) {
 		/* Need NAT */
-		ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff,
-					      addr, port, exp);
+		ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
+					 addr, port, exp);
 	} else {		/* Conntrack only */
 		exp->expectfn = ip_conntrack_q931_expect;
 
@@ -793,6 +800,7 @@ static int process_setup(struct sk_buff 
 	int i;
 	__be32 ip;
 	u_int16_t port;
+	typeof(set_h225_addr_hook) set_h225_addr;
 
 	DEBUGP("ip_ct_q931: Setup\n");
 
@@ -803,8 +811,10 @@ static int process_setup(struct sk_buff 
 			return -1;
 	}
 
+	set_h225_addr = rcu_dereference(set_h225_addr_hook);
+
 	if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
-	    (set_h225_addr_hook) &&
+	    (set_h225_addr) &&
 	    get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
 	    ip != ct->tuplehash[!dir].tuple.src.ip) {
 		DEBUGP("ip_ct_q931: set destCallSignalAddress "
@@ -812,17 +822,17 @@ static int process_setup(struct sk_buff 
 		       NIPQUAD(ip), port,
 		       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
 		       ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
-		ret = set_h225_addr_hook(pskb, data, dataoff,
-					 &setup->destCallSignalAddress,
-					 ct->tuplehash[!dir].tuple.src.ip,
-					 ntohs(ct->tuplehash[!dir].tuple.src.
-					       u.tcp.port));
+		ret = set_h225_addr(pskb, data, dataoff,
+				    &setup->destCallSignalAddress,
+				    ct->tuplehash[!dir].tuple.src.ip,
+				    ntohs(ct->tuplehash[!dir].tuple.src.
+					  u.tcp.port));
 		if (ret < 0)
 			return -1;
 	}
 
 	if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
-	    (set_h225_addr_hook) &&
+	    (set_h225_addr) &&
 	    get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
 	    && ip != ct->tuplehash[!dir].tuple.dst.ip) {
 		DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
@@ -830,11 +840,11 @@ static int process_setup(struct sk_buff 
 		       NIPQUAD(ip), port,
 		       NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
 		       ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
-		ret = set_h225_addr_hook(pskb, data, dataoff,
-					 &setup->sourceCallSignalAddress,
-					 ct->tuplehash[!dir].tuple.dst.ip,
-					 ntohs(ct->tuplehash[!dir].tuple.dst.
-					       u.tcp.port));
+		ret = set_h225_addr(pskb, data, dataoff,
+				    &setup->sourceCallSignalAddress,
+				    ct->tuplehash[!dir].tuple.dst.ip,
+				    ntohs(ct->tuplehash[!dir].tuple.dst.
+					  u.tcp.port));
 		if (ret < 0)
 			return -1;
 	}
@@ -1231,6 +1241,7 @@ static int expect_q931(struct sk_buff **
 	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp;
+	typeof(nat_q931_hook) nat_q931;
 
 	/* Look for the first related address */
 	for (i = 0; i < count; i++) {
@@ -1258,9 +1269,9 @@ static int expect_q931(struct sk_buff **
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = IP_CT_EXPECT_PERMANENT;	/* Accept multiple calls */
 
-	if (nat_q931_hook) {	/* Need NAT */
-		ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i,
-				    port, exp);
+	nat_q931 = rcu_dereference(nat_q931_hook);
+	if (nat_q931) {	/* Need NAT */
+		ret = nat_q931(pskb, ct, ctinfo, data, addr, i, port, exp);
 	} else {		/* Conntrack only */
 		exp->expectfn = ip_conntrack_q931_expect;
 
@@ -1288,11 +1299,14 @@ static int process_grq(struct sk_buff **
 		       enum ip_conntrack_info ctinfo,
 		       unsigned char **data, GatekeeperRequest * grq)
 {
+	typeof(set_ras_addr_hook) set_ras_addr;
+
 	DEBUGP("ip_ct_ras: GRQ\n");
 
-	if (set_ras_addr_hook)	/* NATed */
-		return set_ras_addr_hook(pskb, ct, ctinfo, data,
-					 &grq->rasAddress, 1);
+	set_ras_addr = rcu_dereference(set_ras_addr_hook);
+	if (set_ras_addr)	/* NATed */
+		return set_ras_addr(pskb, ct, ctinfo, data,
+				    &grq->rasAddress, 1);
 	return 0;
 }
 
@@ -1362,6 +1376,7 @@ static int process_rrq(struct sk_buff **
 {
 	struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
 	int ret;
+	typeof(set_ras_addr_hook) set_ras_addr;
 
 	DEBUGP("ip_ct_ras: RRQ\n");
 
@@ -1371,10 +1386,11 @@ static int process_rrq(struct sk_buff **
 	if (ret < 0)
 		return -1;
 
-	if (set_ras_addr_hook) {
-		ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
-					rrq->rasAddress.item,
-					rrq->rasAddress.count);
+	set_ras_addr = rcu_dereference(set_ras_addr_hook);
+	if (set_ras_addr) {
+		ret = set_ras_addr(pskb, ct, ctinfo, data,
+				   rrq->rasAddress.item,
+				   rrq->rasAddress.count);
 		if (ret < 0)
 			return -1;
 	}
@@ -1397,13 +1413,15 @@ static int process_rcf(struct sk_buff **
 	int dir = CTINFO2DIR(ctinfo);
 	int ret;
 	struct ip_conntrack_expect *exp;
+	typeof(set_sig_addr_hook) set_sig_addr;
 
 	DEBUGP("ip_ct_ras: RCF\n");
 
-	if (set_sig_addr_hook) {
-		ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
-					rcf->callSignalAddress.item,
-					rcf->callSignalAddress.count);
+	set_sig_addr = rcu_dereference(set_sig_addr_hook);
+	if (set_sig_addr) {
+		ret = set_sig_addr(pskb, ct, ctinfo, data,
+				   rcf->callSignalAddress.item,
+				   rcf->callSignalAddress.count);
 		if (ret < 0)
 			return -1;
 	}
@@ -1448,13 +1466,15 @@ static int process_urq(struct sk_buff **
 	struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
 	int dir = CTINFO2DIR(ctinfo);
 	int ret;
+	typeof(set_sig_addr_hook) set_sig_addr;
 
 	DEBUGP("ip_ct_ras: URQ\n");
 
-	if (set_sig_addr_hook) {
-		ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
-					urq->callSignalAddress.item,
-					urq->callSignalAddress.count);
+	set_sig_addr = rcu_dereference(set_sig_addr_hook);
+	if (set_sig_addr) {
+		ret = set_sig_addr(pskb, ct, ctinfo, data,
+				   urq->callSignalAddress.item,
+				   urq->callSignalAddress.count);
 		if (ret < 0)
 			return -1;
 	}
@@ -1479,28 +1499,30 @@ static int process_arq(struct sk_buff **
 	int dir = CTINFO2DIR(ctinfo);
 	__be32 ip;
 	u_int16_t port;
+	typeof(set_h225_addr_hook) set_h225_addr;
 
 	DEBUGP("ip_ct_ras: ARQ\n");
 
+	set_h225_addr = rcu_dereference(set_h225_addr_hook);
 	if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
 	    get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
 	    ip == ct->tuplehash[dir].tuple.src.ip &&
-	    port == info->sig_port[dir] && set_h225_addr_hook) {
+	    port == info->sig_port[dir] && set_h225_addr) {
 		/* Answering ARQ */
-		return set_h225_addr_hook(pskb, data, 0,
-					  &arq->destCallSignalAddress,
-					  ct->tuplehash[!dir].tuple.dst.ip,
-					  info->sig_port[!dir]);
+		return set_h225_addr(pskb, data, 0,
+				     &arq->destCallSignalAddress,
+				     ct->tuplehash[!dir].tuple.dst.ip,
+				     info->sig_port[!dir]);
 	}
 
 	if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
 	    get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
-	    ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) {
+	    ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr) {
 		/* Calling ARQ */
-		return set_h225_addr_hook(pskb, data, 0,
-					  &arq->srcCallSignalAddress,
-					  ct->tuplehash[!dir].tuple.dst.ip,
-					  port);
+		return set_h225_addr(pskb, data, 0,
+				     &arq->srcCallSignalAddress,
+				     ct->tuplehash[!dir].tuple.dst.ip,
+				     port);
 	}
 
 	return 0;
@@ -1516,6 +1538,7 @@ static int process_acf(struct sk_buff **
 	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp;
+	typeof(set_sig_addr_hook) set_sig_addr;
 
 	DEBUGP("ip_ct_ras: ACF\n");
 
@@ -1523,10 +1546,10 @@ static int process_acf(struct sk_buff **
 		return 0;
 
 	if (ip == ct->tuplehash[dir].tuple.dst.ip) {	/* Answering ACF */
-		if (set_sig_addr_hook)
-			return set_sig_addr_hook(pskb, ct, ctinfo, data,
-						 &acf->destCallSignalAddress,
-						 1);
+		set_sig_addr = rcu_dereference(set_sig_addr_hook);
+		if (set_sig_addr)
+			return set_sig_addr(pskb, ct, ctinfo, data,
+					    &acf->destCallSignalAddress, 1);
 		return 0;
 	}
 
@@ -1566,11 +1589,14 @@ static int process_lrq(struct sk_buff **
 		       enum ip_conntrack_info ctinfo,
 		       unsigned char **data, LocationRequest * lrq)
 {
+	typeof(set_ras_addr_hook) set_ras_addr;
+
 	DEBUGP("ip_ct_ras: LRQ\n");
 
-	if (set_ras_addr_hook)
-		return set_ras_addr_hook(pskb, ct, ctinfo, data,
-					 &lrq->replyAddress, 1);
+	set_ras_addr = rcu_dereference(set_ras_addr_hook);
+	if (set_ras_addr)
+		return set_ras_addr(pskb, ct, ctinfo, data,
+				    &lrq->replyAddress, 1);
 	return 0;
 }
 
@@ -1629,20 +1655,24 @@ static int process_irr(struct sk_buff **
 		       unsigned char **data, InfoRequestResponse * irr)
 {
 	int ret;
+	typeof(set_ras_addr_hook) set_ras_addr;
+	typeof(set_sig_addr_hook) set_sig_addr;
 
 	DEBUGP("ip_ct_ras: IRR\n");
 
-	if (set_ras_addr_hook) {
-		ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
-					&irr->rasAddress, 1);
+	set_ras_addr = rcu_dereference(set_ras_addr_hook);
+	if (set_ras_addr) {
+		ret = set_ras_addr(pskb, ct, ctinfo, data,
+				   &irr->rasAddress, 1);
 		if (ret < 0)
 			return -1;
 	}
 
-	if (set_sig_addr_hook) {
-		ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
-					irr->callSignalAddress.item,
-					irr->callSignalAddress.count);
+	set_sig_addr = rcu_dereference(set_sig_addr_hook);
+	if (set_sig_addr) {
+		ret = set_sig_addr(pskb, ct, ctinfo, data,
+				   irr->callSignalAddress.item,
+				   irr->callSignalAddress.count);
 		if (ret < 0)
 			return -1;
 	}
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index a5c057b..4d19373 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -124,6 +124,8 @@ #define PPTP_GRE_STREAM_TIMEOUT 	(5 HOUR
 static void pptp_expectfn(struct ip_conntrack *ct,
 			 struct ip_conntrack_expect *exp)
 {
+	typeof(ip_nat_pptp_hook_expectfn) ip_nat_pptp_expectfn;
+
 	DEBUGP("increasing timeouts\n");
 
 	/* increase timeout of GRE data channel conntrack entry */
@@ -133,7 +135,9 @@ static void pptp_expectfn(struct ip_conn
 	/* Can you see how rusty this code is, compared with the pre-2.6.11
 	 * one? That's what happened to my shiny newnat of 2002 ;( -HW */
 
-	if (!ip_nat_pptp_hook_expectfn) {
+	rcu_read_lock();
+	ip_nat_pptp_expectfn = rcu_dereference(ip_nat_pptp_hook_expectfn);
+	if (!ip_nat_pptp_expectfn) {
 		struct ip_conntrack_tuple inv_t;
 		struct ip_conntrack_expect *exp_other;
 
@@ -153,8 +157,9 @@ static void pptp_expectfn(struct ip_conn
 		}
 	} else {
 		/* we need more than simple inversion */
-		ip_nat_pptp_hook_expectfn(ct, exp);
+		ip_nat_pptp_expectfn(ct, exp);
 	}
+	rcu_read_unlock();
 }
 
 static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
@@ -226,6 +231,7 @@ exp_gre(struct ip_conntrack *ct,
 {
 	struct ip_conntrack_expect *exp_orig, *exp_reply;
 	int ret = 1;
+	typeof(ip_nat_pptp_hook_exp_gre) ip_nat_pptp_exp_gre;
 
 	exp_orig = ip_conntrack_expect_alloc(ct);
 	if (exp_orig == NULL)
@@ -262,8 +268,9 @@ exp_gre(struct ip_conntrack *ct,
 	exp_reply->tuple.dst.u.gre.key = peer_callid;
 	exp_reply->tuple.dst.protonum = IPPROTO_GRE;
 
-	if (ip_nat_pptp_hook_exp_gre)
-		ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
+	ip_nat_pptp_exp_gre = rcu_dereference(ip_nat_pptp_hook_exp_gre);
+	if (ip_nat_pptp_exp_gre)
+		ip_nat_pptp_exp_gre(exp_orig, exp_reply);
 	if (ip_conntrack_expect_related(exp_orig) != 0)
 		goto out_put_both;
 	if (ip_conntrack_expect_related(exp_reply) != 0)
@@ -303,6 +310,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
 	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
 	u_int16_t msg;
 	__be16 cid = 0, pcid = 0;
+	typeof(ip_nat_pptp_hook_inbound) ip_nat_pptp_inbound;
 
 	msg = ntohs(ctlh->messageType);
 	DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
@@ -402,9 +410,9 @@ pptp_inbound_pkt(struct sk_buff **pskb,
 		goto invalid;
 	}
 
-	if (ip_nat_pptp_hook_inbound)
-		return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
-						pptpReq);
+	ip_nat_pptp_inbound = rcu_dereference(ip_nat_pptp_hook_inbound);
+	if (ip_nat_pptp_inbound)
+		return ip_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq);
 	return NF_ACCEPT;
 
 invalid:
@@ -427,6 +435,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
 	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
 	u_int16_t msg;
 	__be16 cid = 0, pcid = 0;
+	typeof(ip_nat_pptp_hook_outbound) ip_nat_pptp_outbound;
 
 	msg = ntohs(ctlh->messageType);
 	DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
@@ -492,9 +501,9 @@ pptp_outbound_pkt(struct sk_buff **pskb,
 		goto invalid;
 	}
 
-	if (ip_nat_pptp_hook_outbound)
-		return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
-						 pptpReq);
+	ip_nat_pptp_outbound = rcu_dereference(ip_nat_pptp_hook_outbound);
+	if (ip_nat_pptp_outbound)
+		return ip_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq);
 	return NF_ACCEPT;
 
 invalid:
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 75f7c3d..91832ec 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -114,6 +114,7 @@ static int help(struct sk_buff **pskb,
 	u_int16_t dcc_port;
 	int i, ret = NF_ACCEPT;
 	char *addr_beg_p, *addr_end_p;
+	typeof(ip_nat_irc_hook) ip_nat_irc;
 
 	DEBUGP("entered\n");
 
@@ -222,11 +223,12 @@ static int help(struct sk_buff **pskb,
 					{ .tcp = { htons(0xFFFF) } }, 0xFF }});
 			exp->expectfn = NULL;
 			exp->flags = 0;
-			if (ip_nat_irc_hook)
-				ret = ip_nat_irc_hook(pskb, ctinfo, 
-						      addr_beg_p - ib_ptr,
-						      addr_end_p - addr_beg_p,
-						      exp);
+			ip_nat_irc = rcu_dereference(ip_nat_irc_hook);
+			if (ip_nat_irc)
+				ret = ip_nat_irc(pskb, ctinfo,
+						 addr_beg_p - ib_ptr,
+						 addr_end_p - addr_beg_p,
+						 exp);
 			else if (ip_conntrack_expect_related(exp) != 0)
 				ret = NF_DROP;
 			ip_conntrack_expect_put(exp);
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index f4f7599..bf423db 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -308,6 +308,7 @@ static int set_expected_rtp(struct sk_bu
 	struct ip_conntrack_expect *exp;
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 	int ret;
+	typeof(ip_nat_sdp_hook) ip_nat_sdp;
 
 	exp = ip_conntrack_expect_alloc(ct);
 	if (exp == NULL)
@@ -328,8 +329,9 @@ static int set_expected_rtp(struct sk_bu
 	exp->expectfn = NULL;
 	exp->flags = 0;
 
-	if (ip_nat_sdp_hook)
-		ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
+	ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook);
+	if (ip_nat_sdp)
+		ret = ip_nat_sdp(pskb, ctinfo, exp, dptr);
 	else {
 		if (ip_conntrack_expect_related(exp) != 0)
 			ret = NF_DROP;
@@ -351,6 +353,7 @@ static int sip_help(struct sk_buff **psk
 	int matchoff, matchlen;
 	__be32 ipaddr;
 	u_int16_t port;
+	typeof(ip_nat_sip_hook) ip_nat_sip;
 
 	/* No Data ? */
 	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
@@ -368,8 +371,9 @@ static int sip_help(struct sk_buff **psk
 		goto out;
 	}
 
-	if (ip_nat_sip_hook) {
-		if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
+	ip_nat_sip = rcu_dereference(ip_nat_sip_hook);
+	if (ip_nat_sip) {
+		if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) {
 			ret = NF_DROP;
 			goto out;
 		}
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index fe0b634..ef56de2 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -50,6 +50,7 @@ static int tftp_help(struct sk_buff **ps
 	struct tftphdr _tftph, *tfh;
 	struct ip_conntrack_expect *exp;
 	unsigned int ret = NF_ACCEPT;
+	typeof(ip_nat_tftp_hook) ip_nat_tftp;
 
 	tfh = skb_header_pointer(*pskb,
 				 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
@@ -81,8 +82,9 @@ static int tftp_help(struct sk_buff **ps
 		DEBUGP("expect: ");
 		DUMP_TUPLE(&exp->tuple);
 		DUMP_TUPLE(&exp->mask);
-		if (ip_nat_tftp_hook)
-			ret = ip_nat_tftp_hook(pskb, ctinfo, exp);
+		ip_nat_tftp = rcu_dereference(ip_nat_tftp_hook);
+		if (ip_nat_tftp)
+			ret = ip_nat_tftp(pskb, ctinfo, exp);
 		else if (ip_conntrack_expect_related(exp) != 0)
 			ret = NF_DROP;
 		ip_conntrack_expect_put(exp);
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c
index 3a88871..85df1a9 100644
--- a/net/ipv4/netfilter/ip_nat_amanda.c
+++ b/net/ipv4/netfilter/ip_nat_amanda.c
@@ -70,15 +70,14 @@ static unsigned int help(struct sk_buff 
 
 static void __exit ip_nat_amanda_fini(void)
 {
-	ip_nat_amanda_hook = NULL;
-	/* Make sure noone calls it, meanwhile. */
-	synchronize_net();
+	rcu_assign_pointer(ip_nat_amanda_hook, NULL);
+	synchronize_rcu();
 }
 
 static int __init ip_nat_amanda_init(void)
 {
-	BUG_ON(ip_nat_amanda_hook);
-	ip_nat_amanda_hook = help;
+	BUG_ON(rcu_dereference(ip_nat_amanda_hook));
+	rcu_assign_pointer(ip_nat_amanda_hook, help);
 	return 0;
 }
 
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index a71c233..913960e 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -156,15 +156,14 @@ static unsigned int ip_nat_ftp(struct sk
 
 static void __exit ip_nat_ftp_fini(void)
 {
-	ip_nat_ftp_hook = NULL;
-	/* Make sure noone calls it, meanwhile. */
-	synchronize_net();
+	rcu_assign_pointer(ip_nat_ftp_hook, NULL);
+	synchronize_rcu();
 }
 
 static int __init ip_nat_ftp_init(void)
 {
-	BUG_ON(ip_nat_ftp_hook);
-	ip_nat_ftp_hook = ip_nat_ftp;
+	BUG_ON(rcu_dereference(ip_nat_ftp_hook));
+	rcu_assign_pointer(ip_nat_ftp_hook, ip_nat_ftp);
 	return 0;
 }
 
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index 4a7d344..bdc99ef 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -563,25 +563,25 @@ static int nat_callforwarding(struct sk_
 /****************************************************************************/
 static int __init init(void)
 {
-	BUG_ON(set_h245_addr_hook != NULL);
-	BUG_ON(set_h225_addr_hook != NULL);
-	BUG_ON(set_sig_addr_hook != NULL);
-	BUG_ON(set_ras_addr_hook != NULL);
-	BUG_ON(nat_rtp_rtcp_hook != NULL);
-	BUG_ON(nat_t120_hook != NULL);
-	BUG_ON(nat_h245_hook != NULL);
-	BUG_ON(nat_callforwarding_hook != NULL);
-	BUG_ON(nat_q931_hook != NULL);
-
-	set_h245_addr_hook = set_h245_addr;
-	set_h225_addr_hook = set_h225_addr;
-	set_sig_addr_hook = set_sig_addr;
-	set_ras_addr_hook = set_ras_addr;
-	nat_rtp_rtcp_hook = nat_rtp_rtcp;
-	nat_t120_hook = nat_t120;
-	nat_h245_hook = nat_h245;
-	nat_callforwarding_hook = nat_callforwarding;
-	nat_q931_hook = nat_q931;
+	BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
+	BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
+	BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
+	BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
+	BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
+	BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
+	BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
+	BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
+	BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
+
+	rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
+	rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
+	rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
+	rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
+	rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
+	rcu_assign_pointer(nat_t120_hook, nat_t120);
+	rcu_assign_pointer(nat_h245_hook, nat_h245);
+	rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
+	rcu_assign_pointer(nat_q931_hook, nat_q931);
 
 	DEBUGP("ip_nat_h323: init success\n");
 	return 0;
@@ -590,16 +590,16 @@ static int __init init(void)
 /****************************************************************************/
 static void __exit fini(void)
 {
-	set_h245_addr_hook = NULL;
-	set_h225_addr_hook = NULL;
-	set_sig_addr_hook = NULL;
-	set_ras_addr_hook = NULL;
-	nat_rtp_rtcp_hook = NULL;
-	nat_t120_hook = NULL;
-	nat_h245_hook = NULL;
-	nat_callforwarding_hook = NULL;
-	nat_q931_hook = NULL;
-	synchronize_net();
+	rcu_assign_pointer(set_h245_addr_hook, NULL);
+	rcu_assign_pointer(set_h225_addr_hook, NULL);
+	rcu_assign_pointer(set_sig_addr_hook, NULL);
+	rcu_assign_pointer(set_ras_addr_hook, NULL);
+	rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
+	rcu_assign_pointer(nat_t120_hook, NULL);
+	rcu_assign_pointer(nat_h245_hook, NULL);
+	rcu_assign_pointer(nat_callforwarding_hook, NULL);
+	rcu_assign_pointer(nat_q931_hook, NULL);
+	synchronize_rcu();
 }
 
 /****************************************************************************/
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index acf55d8..ec957bb 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -315,17 +315,17 @@ static int __init ip_nat_helper_pptp_ini
 	if (ret < 0)
 		return ret;
 
-	BUG_ON(ip_nat_pptp_hook_outbound);
-	ip_nat_pptp_hook_outbound = &pptp_outbound_pkt;
+	BUG_ON(rcu_dereference(ip_nat_pptp_hook_outbound));
+	rcu_assign_pointer(ip_nat_pptp_hook_outbound, pptp_outbound_pkt);
 
-	BUG_ON(ip_nat_pptp_hook_inbound);
-	ip_nat_pptp_hook_inbound = &pptp_inbound_pkt;
+	BUG_ON(rcu_dereference(ip_nat_pptp_hook_inbound));
+	rcu_assign_pointer(ip_nat_pptp_hook_inbound, pptp_inbound_pkt);
 
-	BUG_ON(ip_nat_pptp_hook_exp_gre);
-	ip_nat_pptp_hook_exp_gre = &pptp_exp_gre;
+	BUG_ON(rcu_dereference(ip_nat_pptp_hook_exp_gre));
+	rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, pptp_exp_gre);
 
-	BUG_ON(ip_nat_pptp_hook_expectfn);
-	ip_nat_pptp_hook_expectfn = &pptp_nat_expected;
+	BUG_ON(rcu_dereference(ip_nat_pptp_hook_expectfn));
+	rcu_assign_pointer(ip_nat_pptp_hook_expectfn, pptp_nat_expected);
 
 	printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
 	return 0;
@@ -335,14 +335,13 @@ static void __exit ip_nat_helper_pptp_fi
 {
 	DEBUGP("cleanup_module\n" );
 
-	ip_nat_pptp_hook_expectfn = NULL;
-	ip_nat_pptp_hook_exp_gre = NULL;
-	ip_nat_pptp_hook_inbound = NULL;
-	ip_nat_pptp_hook_outbound = NULL;
+	rcu_assign_pointer(ip_nat_pptp_hook_expectfn, NULL);
+	rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, NULL);
+	rcu_assign_pointer(ip_nat_pptp_hook_inbound, NULL);
+	rcu_assign_pointer(ip_nat_pptp_hook_outbound, NULL);
+	synchronize_rcu();
 
 	ip_nat_proto_gre_fini();
-	/* Make sure noone calls it, meanwhile */
-	synchronize_net();
 
 	printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
 }
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index a767123..feb26b4 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -98,15 +98,14 @@ static unsigned int help(struct sk_buff 
 
 static void __exit ip_nat_irc_fini(void)
 {
-	ip_nat_irc_hook = NULL;
-	/* Make sure noone calls it, meanwhile. */
-	synchronize_net();
+	rcu_assign_pointer(ip_nat_irc_hook, NULL);
+	synchronize_rcu();
 }
 
 static int __init ip_nat_irc_init(void)
 {
-	BUG_ON(ip_nat_irc_hook);
-	ip_nat_irc_hook = help;
+	BUG_ON(rcu_dereference(ip_nat_irc_hook));
+	rcu_assign_pointer(ip_nat_irc_hook, help);
 	return 0;
 }
 
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 71fc273..9fad980 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -230,18 +230,17 @@ static unsigned int ip_nat_sdp(struct sk
 
 static void __exit fini(void)
 {
-	ip_nat_sip_hook = NULL;
-	ip_nat_sdp_hook = NULL;
-	/* Make sure noone calls it, meanwhile. */
-	synchronize_net();
+	rcu_assign_pointer(ip_nat_sip_hook, NULL);
+	rcu_assign_pointer(ip_nat_sdp_hook, NULL);
+	synchronize_rcu();
 }
 
 static int __init init(void)
 {
-	BUG_ON(ip_nat_sip_hook);
-	BUG_ON(ip_nat_sdp_hook);
-	ip_nat_sip_hook = ip_nat_sip;
-	ip_nat_sdp_hook = ip_nat_sdp;
+	BUG_ON(rcu_dereference(ip_nat_sip_hook));
+	BUG_ON(rcu_dereference(ip_nat_sdp_hook));
+	rcu_assign_pointer(ip_nat_sip_hook, ip_nat_sip);
+	rcu_assign_pointer(ip_nat_sdp_hook, ip_nat_sdp);
 	return 0;
 }
 
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
index 94a7801..6047935 100644
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ b/net/ipv4/netfilter/ip_nat_tftp.c
@@ -55,15 +55,14 @@ static unsigned int help(struct sk_buff 
 
 static void __exit ip_nat_tftp_fini(void)
 {
-	ip_nat_tftp_hook = NULL;
-	/* Make sure noone calls it, meanwhile. */
-	synchronize_net();
+	rcu_assign_pointer(ip_nat_tftp_hook, NULL);
+	synchronize_rcu();
 }
 
 static int __init ip_nat_tftp_init(void)
 {
-	BUG_ON(ip_nat_tftp_hook);
-	ip_nat_tftp_hook = help;
+	BUG_ON(rcu_dereference(ip_nat_tftp_hook));
+	rcu_assign_pointer(ip_nat_tftp_hook, help);
 	return 0;
 }
 
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 05cb78c..2d23501 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -369,9 +369,9 @@ static int help(struct sk_buff **pskb,
 	struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
 	struct nf_conntrack_expect *exp;
 	struct nf_conntrack_man cmd = {};
-
 	unsigned int i;
 	int found = 0, ends_in_nl;
+	typeof(nf_nat_ftp_hook) nf_nat_ftp;
 
 	/* Until there's been traffic both ways, don't look in packets. */
 	if (ctinfo != IP_CT_ESTABLISHED
@@ -520,9 +520,10 @@ static int help(struct sk_buff **pskb,
 
 	/* Now, NAT might want to mangle the packet, and register the
 	 * (possibly changed) expectation itself. */
-	if (nf_nat_ftp_hook)
-		ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
-				      matchoff, matchlen, exp, &seq);
+	nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
+	if (nf_nat_ftp)
+		ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
+				 matchoff, matchlen, exp, &seq);
 	else {
 		/* Can't expect this?  Best to drop packet now. */
 		if (nf_conntrack_expect_related(exp) != 0)

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 20/33]: sip conntrack: minor cleanup
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (18 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 19/33]: ip_conntrack: fix NAT helper unload races Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 21/33]: sip conntrack: do case insensitive SIP header search Patrick McHardy
                   ` (13 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: sip conntrack: minor cleanup

- Use enum for header field enumeration
- Use numerical value instead of pointer to header info structure to
  identify headers, unexport ct_sip_hdrs
- group SIP and SDP entries in header info structure
- remove double forward declaration of ct_sip_get_info

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit c41ecbacb167a4adce826db76be55a0c0e089c79
tree 6f70ca81c15bd4da64281bd644c3801722fe6a4c
parent be8302ed9dba541073030f78208bd96304f13964
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:28 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:49 +0100

 include/linux/netfilter_ipv4/ip_conntrack_sip.h |   28 ++++-------
 net/ipv4/netfilter/ip_conntrack_sip.c           |   60 ++++++++++++-----------
 net/ipv4/netfilter/ip_nat_sip.c                 |   30 +++++-------
 3 files changed, 55 insertions(+), 63 deletions(-)

diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
index 913dad6..2a15eb5 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
@@ -5,23 +5,15 @@ #ifdef __KERNEL__
 #define SIP_PORT	5060
 #define SIP_TIMEOUT	3600
 
-#define POS_VIA		0
-#define POS_CONTACT	1
-#define POS_CONTENT	2
-#define POS_MEDIA	3
-#define POS_OWNER	4
-#define POS_CONNECTION	5
-#define POS_REQ_HEADER	6
-#define POS_SDP_HEADER	7
-
-struct sip_header_nfo {
-	const char	*lname;
-	const char	*sname;
-	const char	*ln_str;
-	size_t		lnlen;
-	size_t		snlen;
-	size_t		ln_strlen;
-	int		(*match_len)(const char *, const char *, int *);
+enum sip_header_pos {
+	POS_REQ_HEADER,
+	POS_VIA,
+	POS_CONTACT,
+	POS_CONTENT,
+	POS_MEDIA,
+	POS_OWNER,
+	POS_CONNECTION,
+	POS_SDP_HEADER,
 };
 
 extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
@@ -36,7 +28,7 @@ extern unsigned int (*ip_nat_sdp_hook)(s
 extern int ct_sip_get_info(const char *dptr, size_t dlen,
 			   unsigned int *matchoff,
 			   unsigned int *matchlen,
-			   struct sip_header_nfo *hnfo);
+			   enum sip_header_pos pos);
 extern int ct_sip_lnlen(const char *line, const char *limit);
 extern const char *ct_sip_search(const char *needle, const char *haystack,
                                  size_t needle_len, size_t haystack_len);
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index bf423db..cc31765 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -52,20 +52,32 @@ unsigned int (*ip_nat_sdp_hook)(struct s
 				const char *dptr);
 EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
 
-int ct_sip_get_info(const char *dptr, size_t dlen,
-				unsigned int *matchoff,
-				unsigned int *matchlen,
-				struct sip_header_nfo *hnfo);
-EXPORT_SYMBOL_GPL(ct_sip_get_info);
-
-
 static int digits_len(const char *dptr, const char *limit, int *shift);
 static int epaddr_len(const char *dptr, const char *limit, int *shift);
 static int skp_digits_len(const char *dptr, const char *limit, int *shift);
 static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
 
-struct sip_header_nfo ct_sip_hdrs[] = {
-	{ 	/* Via header */
+struct sip_header_nfo {
+	const char	*lname;
+	const char	*sname;
+	const char	*ln_str;
+	size_t		lnlen;
+	size_t		snlen;
+	size_t		ln_strlen;
+	int		(*match_len)(const char *, const char *, int *);
+};
+
+static struct sip_header_nfo ct_sip_hdrs[] = {
+	[POS_REQ_HEADER] = { 	/* SIP Requests headers */
+		.lname		= "sip:",
+		.lnlen		= sizeof("sip:") - 1,
+		.sname		= "sip:",
+		.snlen		= sizeof("sip:") - 1, /* yes, i know.. ;) */
+		.ln_str		= "@",
+		.ln_strlen	= sizeof("@") - 1,
+		.match_len	= epaddr_len
+	},
+	[POS_VIA] = { 		/* SIP Via header */
 		.lname		= "Via:",
 		.lnlen		= sizeof("Via:") - 1,
 		.sname		= "\r\nv:",
@@ -74,7 +86,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
 		.ln_strlen	= sizeof("UDP ") - 1,
 		.match_len	= epaddr_len,
 	},
-	{ 	/* Contact header */
+	[POS_CONTACT] = { 	/* SIP Contact header */
 		.lname		= "Contact:",
 		.lnlen		= sizeof("Contact:") - 1,
 		.sname		= "\r\nm:",
@@ -83,7 +95,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
 		.ln_strlen	= sizeof("sip:") - 1,
 		.match_len	= skp_epaddr_len
 	},
-	{ 	/* Content length header */
+	[POS_CONTENT] = { 	/* SIP Content length header */
 		.lname		= "Content-Length:",
 		.lnlen		= sizeof("Content-Length:") - 1,
 		.sname		= "\r\nl:",
@@ -92,7 +104,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
 		.ln_strlen	= sizeof(":") - 1,
 		.match_len	= skp_digits_len
 	},
-	{	/* SDP media info */
+	[POS_MEDIA] = {		/* SDP media info */
 		.lname		= "\nm=",
 		.lnlen		= sizeof("\nm=") - 1,
 		.sname		= "\rm=",
@@ -101,7 +113,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
 		.ln_strlen	= sizeof("audio ") - 1,
 		.match_len	= digits_len
 	},
-	{ 	/* SDP owner address*/
+	[POS_OWNER] = { 	/* SDP owner address*/
 		.lname		= "\no=",
 		.lnlen		= sizeof("\no=") - 1,
 		.sname		= "\ro=",
@@ -110,7 +122,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
 		.ln_strlen	= sizeof("IN IP4 ") - 1,
 		.match_len	= epaddr_len
 	},
-	{ 	/* SDP connection info */
+	[POS_CONNECTION] = { 	/* SDP connection info */
 		.lname		= "\nc=",
 		.lnlen		= sizeof("\nc=") - 1,
 		.sname		= "\rc=",
@@ -119,16 +131,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
 		.ln_strlen	= sizeof("IN IP4 ") - 1,
 		.match_len	= epaddr_len
 	},
-	{ 	/* Requests headers */
-		.lname		= "sip:",
-		.lnlen		= sizeof("sip:") - 1,
-		.sname		= "sip:",
-		.snlen		= sizeof("sip:") - 1, /* yes, i know.. ;) */
-		.ln_str		= "@",
-		.ln_strlen	= sizeof("@") - 1,
-		.match_len	= epaddr_len
-	},
-	{ 	/* SDP version header */
+	[POS_SDP_HEADER] = { 	/* SDP version header */
 		.lname		= "\nv=",
 		.lnlen		= sizeof("\nv=") - 1,
 		.sname		= "\rv=",
@@ -138,7 +141,6 @@ struct sip_header_nfo ct_sip_hdrs[] = {
 		.match_len	= digits_len
 	}
 };
-EXPORT_SYMBOL_GPL(ct_sip_hdrs);
 
 /* get line lenght until first CR or LF seen. */
 int ct_sip_lnlen(const char *line, const char *limit)
@@ -263,8 +265,9 @@ static int skp_epaddr_len(const char *dp
 int ct_sip_get_info(const char *dptr, size_t dlen,
 		    unsigned int *matchoff,
 		    unsigned int *matchlen,
-		    struct sip_header_nfo *hnfo)
+		    enum sip_header_pos pos)
 {
+	struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos];
 	const char *limit, *aux, *k = dptr;
 	int shift = 0;
 
@@ -298,6 +301,7 @@ int ct_sip_get_info(const char *dptr, si
 	DEBUGP("%s header not found.\n", hnfo->lname);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ct_sip_get_info);
 
 static int set_expected_rtp(struct sk_buff **pskb,
 			    struct ip_conntrack *ct,
@@ -393,7 +397,7 @@ static int sip_help(struct sk_buff **psk
 	}
 	/* Get ip and port address from SDP packet. */
 	if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
-	                    &ct_sip_hdrs[POS_CONNECTION]) > 0) {
+	                    POS_CONNECTION) > 0) {
 
 		/* We'll drop only if there are parse problems. */
 		if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
@@ -402,7 +406,7 @@ static int sip_help(struct sk_buff **psk
 			goto out;
 		}
 		if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
-		                    &ct_sip_hdrs[POS_MEDIA]) > 0) {
+		                    POS_MEDIA) > 0) {
 
 			port = simple_strtoul(dptr + matchoff, NULL, 10);
 			if (port < 1024) {
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 9fad980..47097aa 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -29,18 +29,16 @@ #else
 #define DEBUGP(format, args...)
 #endif
 
-extern struct sip_header_nfo ct_sip_hdrs[];
-
 static unsigned int mangle_sip_packet(struct sk_buff **pskb,
 				      enum ip_conntrack_info ctinfo,
 				      struct ip_conntrack *ct,
 				      const char **dptr, size_t dlen,
 				      char *buffer, int bufflen,
-				      struct sip_header_nfo *hnfo)
+				      enum sip_header_pos pos)
 {
 	unsigned int matchlen, matchoff;
 
-	if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
+	if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
 		return 0;
 
 	if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
@@ -80,14 +78,13 @@ static unsigned int ip_nat_sip(struct sk
 		if ((ctinfo) < IP_CT_IS_REPLY) {
 			mangle_sip_packet(pskb, ctinfo, ct, dptr,
 			                  (*pskb)->len - dataoff,
-			                  buffer, bufflen,
-			                  &ct_sip_hdrs[POS_CONTACT]);
+			                  buffer, bufflen, POS_CONTACT);
 			return 1;
 		}
 
 		if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
 				       (*pskb)->len - dataoff,
-		                       buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+		                       buffer, bufflen, POS_VIA))
 			return 0;
 
 		/* This search should ignore case, but later.. */
@@ -102,25 +99,24 @@ static unsigned int ip_nat_sip(struct sk
 
 		return mangle_sip_packet(pskb, ctinfo, ct, dptr,
 					 (*pskb)->len - dataoff,
-		                         buffer, bufflen,
-					 &ct_sip_hdrs[POS_CONTACT]);
+		                         buffer, bufflen, POS_CONTACT);
 	}
 	if ((ctinfo) < IP_CT_IS_REPLY) {
 		if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
 				       (*pskb)->len - dataoff,
-		                       buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+		                       buffer, bufflen, POS_VIA))
 			return 0;
 
 		/* Mangle Contact if exists only. - watch udp_nat_mangle()! */
 		mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
-		                  buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
+		                  buffer, bufflen, POS_CONTACT);
 		return 1;
 	}
 	/* This mangle requests headers. */
 	return mangle_sip_packet(pskb, ctinfo, ct, dptr,
 	                         ct_sip_lnlen(*dptr,
 				              *dptr + (*pskb)->len - dataoff),
-	                         buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
+	                         buffer, bufflen, POS_REQ_HEADER);
 }
 
 static int mangle_content_len(struct sk_buff **pskb,
@@ -136,7 +132,7 @@ static int mangle_content_len(struct sk_
 
 	/* Get actual SDP lenght */
 	if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
-	                    &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
+	                    &matchlen, POS_SDP_HEADER) > 0) {
 
 		/* since ct_sip_get_info() give us a pointer passing 'v='
 		   we need to add 2 bytes in this count. */
@@ -144,7 +140,7 @@ static int mangle_content_len(struct sk_
 
 		/* Now, update SDP lenght */
 		if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
-		                    &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
+		                    &matchlen, POS_CONTENT) > 0) {
 
 			bufflen = sprintf(buffer, "%u", c_len);
 
@@ -170,17 +166,17 @@ static unsigned int mangle_sdp(struct sk
 	/* Mangle owner and contact info. */
 	bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, &ct_sip_hdrs[POS_OWNER]))
+	                       buffer, bufflen, POS_OWNER))
 		return 0;
 
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION]))
+	                       buffer, bufflen, POS_CONNECTION))
 		return 0;
 
 	/* Mangle media port. */
 	bufflen = sprintf(buffer, "%u", port);
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, &ct_sip_hdrs[POS_MEDIA]))
+	                       buffer, bufflen, POS_MEDIA))
 		return 0;
 
 	return mangle_content_len(pskb, ctinfo, ct, dptr);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 21/33]: sip conntrack: do case insensitive SIP header search
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (19 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 20/33]: sip conntrack: minor cleanup Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 22/33]: sip conntrack: make header shortcuts optional Patrick McHardy
                   ` (12 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: sip conntrack: do case insensitive SIP header search

SIP headers are generally case-insensitive, only SDP headers are
case sensitive.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 74ea88e39e990542e1a7492edb3bc4f0bc254384
tree 21f951afd4ddab54e42683b8e9fee4096e8cc039
parent c41ecbacb167a4adce826db76be55a0c0e089c79
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:29 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:50 +0100

 include/linux/netfilter_ipv4/ip_conntrack_sip.h |    3 ++-
 net/ipv4/netfilter/ip_conntrack_sip.c           |   20 ++++++++++++++++----
 net/ipv4/netfilter/ip_nat_sip.c                 |    7 ++++---
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
index 2a15eb5..51c65ac 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
@@ -31,6 +31,7 @@ extern int ct_sip_get_info(const char *d
 			   enum sip_header_pos pos);
 extern int ct_sip_lnlen(const char *line, const char *limit);
 extern const char *ct_sip_search(const char *needle, const char *haystack,
-                                 size_t needle_len, size_t haystack_len);
+				 size_t needle_len, size_t haystack_len,
+				 int case_sensitive);
 #endif /* __KERNEL__ */
 #endif /* __IP_CONNTRACK_SIP_H__ */
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index cc31765..a9c0d1d 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -64,6 +64,7 @@ struct sip_header_nfo {
 	size_t		lnlen;
 	size_t		snlen;
 	size_t		ln_strlen;
+	int		case_sensitive;
 	int		(*match_len)(const char *, const char *, int *);
 };
 
@@ -105,6 +106,7 @@ static struct sip_header_nfo ct_sip_hdrs
 		.match_len	= skp_digits_len
 	},
 	[POS_MEDIA] = {		/* SDP media info */
+		.case_sensitive	= 1,
 		.lname		= "\nm=",
 		.lnlen		= sizeof("\nm=") - 1,
 		.sname		= "\rm=",
@@ -114,6 +116,7 @@ static struct sip_header_nfo ct_sip_hdrs
 		.match_len	= digits_len
 	},
 	[POS_OWNER] = { 	/* SDP owner address*/
+		.case_sensitive	= 1,
 		.lname		= "\no=",
 		.lnlen		= sizeof("\no=") - 1,
 		.sname		= "\ro=",
@@ -123,6 +126,7 @@ static struct sip_header_nfo ct_sip_hdrs
 		.match_len	= epaddr_len
 	},
 	[POS_CONNECTION] = { 	/* SDP connection info */
+		.case_sensitive	= 1,
 		.lname		= "\nc=",
 		.lnlen		= sizeof("\nc=") - 1,
 		.sname		= "\rc=",
@@ -132,6 +136,7 @@ static struct sip_header_nfo ct_sip_hdrs
 		.match_len	= epaddr_len
 	},
 	[POS_SDP_HEADER] = { 	/* SDP version header */
+		.case_sensitive	= 1,
 		.lname		= "\nv=",
 		.lnlen		= sizeof("\nv=") - 1,
 		.sname		= "\rv=",
@@ -161,13 +166,19 @@ EXPORT_SYMBOL_GPL(ct_sip_lnlen);
 
 /* Linear string search, case sensitive. */
 const char *ct_sip_search(const char *needle, const char *haystack,
-                          size_t needle_len, size_t haystack_len)
+			  size_t needle_len, size_t haystack_len,
+			  int case_sensitive)
 {
 	const char *limit = haystack + (haystack_len - needle_len);
 
 	while (haystack <= limit) {
-		if (memcmp(haystack, needle, needle_len) == 0)
-			return haystack;
+		if (case_sensitive) {
+			if (strncmp(haystack, needle, needle_len) == 0)
+				return haystack;
+		} else {
+			if (strnicmp(haystack, needle, needle_len) == 0)
+				return haystack;
+		}
 		haystack++;
 	}
 	return NULL;
@@ -280,7 +291,8 @@ int ct_sip_get_info(const char *dptr, si
 			continue;
 		}
 		aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
-		                    ct_sip_lnlen(dptr, limit));
+		                    ct_sip_lnlen(dptr, limit),
+				    hnfo->case_sensitive);
 		if (!aux) {
 			DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
 			       hnfo->lname);
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 47097aa..e16604c 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -87,14 +87,15 @@ static unsigned int ip_nat_sip(struct sk
 		                       buffer, bufflen, POS_VIA))
 			return 0;
 
-		/* This search should ignore case, but later.. */
 		aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
-		                    (*pskb)->len - dataoff);
+		                    (*pskb)->len - dataoff, 0);
 		if (!aux)
 			return 0;
 
 		if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
-		    ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff)))
+				   ct_sip_lnlen(aux,
+				   		*dptr + (*pskb)->len - dataoff),
+				   1))
 			return 1;
 
 		return mangle_sip_packet(pskb, ctinfo, ct, dptr,

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 22/33]: sip conntrack: make header shortcuts optional
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (20 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 21/33]: sip conntrack: do case insensitive SIP header search Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 23/33]: sip conntrack: better NAT handling Patrick McHardy
                   ` (11 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: sip conntrack: make header shortcuts optional

Not every header has a shortcut, so make them optional instead
of searching for the same string twice.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 69e5ca0b3c45fc0831ca7d401bba4d791681e92b
tree 738a21a179c76df246e958b92a284d345ed0b101
parent 74ea88e39e990542e1a7492edb3bc4f0bc254384
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:30 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:50 +0100

 net/ipv4/netfilter/ip_conntrack_sip.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index a9c0d1d..0a6a13c 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -72,8 +72,6 @@ static struct sip_header_nfo ct_sip_hdrs
 	[POS_REQ_HEADER] = { 	/* SIP Requests headers */
 		.lname		= "sip:",
 		.lnlen		= sizeof("sip:") - 1,
-		.sname		= "sip:",
-		.snlen		= sizeof("sip:") - 1, /* yes, i know.. ;) */
 		.ln_str		= "@",
 		.ln_strlen	= sizeof("@") - 1,
 		.match_len	= epaddr_len
@@ -286,7 +284,8 @@ int ct_sip_get_info(const char *dptr, si
 
 	while (dptr <= limit) {
 		if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
-		    (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+		    (hinfo->sname == NULL ||
+		     strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
 			dptr++;
 			continue;
 		}

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 23/33]: sip conntrack: better NAT handling
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (21 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 22/33]: sip conntrack: make header shortcuts optional Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 24/33]: ctnetlink: check for status attribute existence on conntrack creation Patrick McHardy
                   ` (10 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: sip conntrack: better NAT handling

The NAT handling of the SIP helper has a few problems:

- Request headers are only mangled in the reply direction, From/To headers
  not at all, which can lead to authentication failures with DNAT in case
  the authentication domain is the IP address

- Contact headers in responses are only mangled for REGISTER responses

- Headers may be mangled even though they contain addresses not
  participating in the connection, like alternative addresses

- Packets are droppen when domain names are used where the helper expects
  IP addresses

This patch takes a different approach, instead of fixed rules what field
to mangle to what content, it adds symetric mapping of From/To/Via/Contact
headers, which allows to deal properly with echoed addresses in responses
and foreign addresses not belonging to the connection.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit f344b5c94ce31b63c1c2c31ea04512bc9e3929c5
tree 3f86f114a21a92efc2f117d380ae98ae64a2f3cc
parent 69e5ca0b3c45fc0831ca7d401bba4d791681e92b
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:32 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:50 +0100

 include/linux/netfilter_ipv4/ip_conntrack_sip.h |    5 +
 net/ipv4/netfilter/ip_conntrack_sip.c           |   29 ++++
 net/ipv4/netfilter/ip_nat_sip.c                 |  171 ++++++++++++++---------
 3 files changed, 135 insertions(+), 70 deletions(-)

diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
index 51c65ac..bef6c64 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
@@ -6,7 +6,10 @@ #define SIP_PORT	5060
 #define SIP_TIMEOUT	3600
 
 enum sip_header_pos {
-	POS_REQ_HEADER,
+	POS_REG_REQ_URI,
+	POS_REQ_URI,
+	POS_FROM,
+	POS_TO,
 	POS_VIA,
 	POS_CONTACT,
 	POS_CONTENT,
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index 0a6a13c..3a26d63 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -69,13 +69,38 @@ struct sip_header_nfo {
 };
 
 static struct sip_header_nfo ct_sip_hdrs[] = {
-	[POS_REQ_HEADER] = { 	/* SIP Requests headers */
+	[POS_REG_REQ_URI] = { 	/* SIP REGISTER request URI */
+		.lname		= "sip:",
+		.lnlen		= sizeof("sip:") - 1,
+		.ln_str		= ":",
+		.ln_strlen	= sizeof(":") - 1,
+		.match_len	= epaddr_len
+	},
+	[POS_REQ_URI] = { 	/* SIP request URI */
 		.lname		= "sip:",
 		.lnlen		= sizeof("sip:") - 1,
 		.ln_str		= "@",
 		.ln_strlen	= sizeof("@") - 1,
 		.match_len	= epaddr_len
 	},
+	[POS_FROM] = {		/* SIP From header */
+		.lname		= "From:",
+		.lnlen		= sizeof("From:") - 1,
+		.sname		= "\r\nf:",
+		.snlen		= sizeof("\r\nf:") - 1,
+		.ln_str		= "sip:",
+		.ln_strlen	= sizeof("sip:") - 1,
+		.match_len	= skp_epaddr_len,
+	},
+	[POS_TO] = {		/* SIP To header */
+		.lname		= "To:",
+		.lnlen		= sizeof("To:") - 1,
+		.sname		= "\r\nt:",
+		.snlen		= sizeof("\r\nt:") - 1,
+		.ln_str		= "sip:",
+		.ln_strlen	= sizeof("sip:") - 1,
+		.match_len	= skp_epaddr_len,
+	},
 	[POS_VIA] = { 		/* SIP Via header */
 		.lname		= "Via:",
 		.lnlen		= sizeof("Via:") - 1,
@@ -284,7 +309,7 @@ int ct_sip_get_info(const char *dptr, si
 
 	while (dptr <= limit) {
 		if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
-		    (hinfo->sname == NULL ||
+		    (hnfo->sname == NULL ||
 		     strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
 			dptr++;
 			continue;
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index e16604c..6223abc 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -29,25 +29,70 @@ #else
 #define DEBUGP(format, args...)
 #endif
 
-static unsigned int mangle_sip_packet(struct sk_buff **pskb,
-				      enum ip_conntrack_info ctinfo,
-				      struct ip_conntrack *ct,
-				      const char **dptr, size_t dlen,
-				      char *buffer, int bufflen,
-				      enum sip_header_pos pos)
+struct addr_map {
+	struct {
+		char		src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+		char		dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+		unsigned int	srclen, srciplen;
+		unsigned int	dstlen, dstiplen;
+	} addr[IP_CT_DIR_MAX];
+};
+
+static void addr_map_init(struct ip_conntrack *ct, struct addr_map *map)
 {
-	unsigned int matchlen, matchoff;
+	struct ip_conntrack_tuple *t;
+	enum ip_conntrack_dir dir;
+	unsigned int n;
+
+	for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
+		t = &ct->tuplehash[dir].tuple;
+
+		n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
+			    NIPQUAD(t->src.ip));
+		map->addr[dir].srciplen = n;
+		n += sprintf(map->addr[dir].src + n, ":%u",
+			     ntohs(t->src.u.udp.port));
+		map->addr[dir].srclen = n;
+
+		n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
+			    NIPQUAD(t->dst.ip));
+		map->addr[dir].dstiplen = n;
+		n += sprintf(map->addr[dir].dst + n, ":%u",
+			     ntohs(t->dst.u.udp.port));
+		map->addr[dir].dstlen = n;
+	}
+}
+
+static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
+			struct ip_conntrack *ct, const char **dptr, size_t dlen,
+			enum sip_header_pos pos, struct addr_map *map)
+{
+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	unsigned int matchlen, matchoff, addrlen;
+	char *addr;
 
 	if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
-		return 0;
+		return 1;
+
+	if ((matchlen == map->addr[dir].srciplen ||
+	     matchlen == map->addr[dir].srclen) &&
+	    memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
+		addr    = map->addr[!dir].dst;
+		addrlen = map->addr[!dir].dstlen;
+	} else if ((matchlen == map->addr[dir].dstiplen ||
+		    matchlen == map->addr[dir].dstlen) &&
+		   memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
+		addr    = map->addr[!dir].src;
+		addrlen = map->addr[!dir].srclen;
+	} else
+		return 1;
 
 	if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
-	                              matchoff, matchlen, buffer, bufflen))
+	                              matchoff, matchlen, addr, addrlen))
 		return 0;
-
-	/* We need to reload this. Thanks Patrick. */
 	*dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
 	return 1;
+
 }
 
 static unsigned int ip_nat_sip(struct sk_buff **pskb,
@@ -55,69 +100,61 @@ static unsigned int ip_nat_sip(struct sk
 			       struct ip_conntrack *ct,
 			       const char **dptr)
 {
-	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
-	unsigned int bufflen, dataoff;
-	__be32 ip;
-	__be16 port;
+	enum sip_header_pos pos;
+	struct addr_map map;
+	int dataoff, datalen;
 
 	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+	datalen = (*pskb)->len - dataoff;
+	if (datalen < sizeof("SIP/2.0") - 1)
+		return NF_DROP;
+
+	addr_map_init(ct, &map);
+
+	/* Basic rules: requests and responses. */
+	if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
+		/* 10.2: Constructing the REGISTER Request:
+		 *
+		 * The "userinfo" and "@" components of the SIP URI MUST NOT
+		 * be present.
+		 */
+		if (datalen >= sizeof("REGISTER") - 1 &&
+		    strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
+			pos = POS_REG_REQ_URI;
+		else
+			pos = POS_REQ_URI;
+
+		if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
+			return NF_DROP;
+	}
 
-	ip   = ct->tuplehash[!dir].tuple.dst.ip;
-	port = ct->tuplehash[!dir].tuple.dst.u.udp.port;
-	bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
+	if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
+	    !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
+	    !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
+	    !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
+		return NF_DROP;
+	return NF_ACCEPT;
+}
+
+static unsigned int mangle_sip_packet(struct sk_buff **pskb,
+				      enum ip_conntrack_info ctinfo,
+				      struct ip_conntrack *ct,
+				      const char **dptr, size_t dlen,
+				      char *buffer, int bufflen,
+				      enum sip_header_pos pos)
+{
+	unsigned int matchlen, matchoff;
 
-	/* short packet ? */
-	if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
+	if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
 		return 0;
 
-	/* Basic rules: requests and responses. */
-	if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
-		const char *aux;
-
-		if ((ctinfo) < IP_CT_IS_REPLY) {
-			mangle_sip_packet(pskb, ctinfo, ct, dptr,
-			                  (*pskb)->len - dataoff,
-			                  buffer, bufflen, POS_CONTACT);
-			return 1;
-		}
+	if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+	                              matchoff, matchlen, buffer, bufflen))
+		return 0;
 
-		if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
-				       (*pskb)->len - dataoff,
-		                       buffer, bufflen, POS_VIA))
-			return 0;
-
-		aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
-		                    (*pskb)->len - dataoff, 0);
-		if (!aux)
-			return 0;
-
-		if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
-				   ct_sip_lnlen(aux,
-				   		*dptr + (*pskb)->len - dataoff),
-				   1))
-			return 1;
-
-		return mangle_sip_packet(pskb, ctinfo, ct, dptr,
-					 (*pskb)->len - dataoff,
-		                         buffer, bufflen, POS_CONTACT);
-	}
-	if ((ctinfo) < IP_CT_IS_REPLY) {
-		if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
-				       (*pskb)->len - dataoff,
-		                       buffer, bufflen, POS_VIA))
-			return 0;
-
-		/* Mangle Contact if exists only. - watch udp_nat_mangle()! */
-		mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
-		                  buffer, bufflen, POS_CONTACT);
-		return 1;
-	}
-	/* This mangle requests headers. */
-	return mangle_sip_packet(pskb, ctinfo, ct, dptr,
-	                         ct_sip_lnlen(*dptr,
-				              *dptr + (*pskb)->len - dataoff),
-	                         buffer, bufflen, POS_REQ_HEADER);
+	/* We need to reload this. Thanks Patrick. */
+	*dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+	return 1;
 }
 
 static int mangle_content_len(struct sk_buff **pskb,

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 24/33]: ctnetlink: check for status attribute existence on conntrack creation
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (22 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 23/33]: sip conntrack: better NAT handling Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 25/33]: ctnetlink: rework conntrack fields dumping logic on events Patrick McHardy
                   ` (9 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: ctnetlink: check for status attribute existence on conntrack creation

Check that status flags are available in the netlink message received
to create a new conntrack.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 9f1f643dcb442e2bd19afd3fec8d1a3958cf5629
tree d3cb5590466126d7d97a89a5dfdaff242dce7ad9
parent f344b5c94ce31b63c1c2c31ea04512bc9e3929c5
author Pablo Neira Ayuso <pablo@netfilter.org> Tue, 28 Nov 2006 23:13:14 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:51 +0100

 net/ipv4/netfilter/ip_conntrack_netlink.c |    8 +++++---
 net/netfilter/nf_conntrack_netlink.c      |    8 +++++---
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 3d277aa..d5d2efd 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -945,9 +945,11 @@ ctnetlink_create_conntrack(struct nfattr
 	ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
 	ct->status |= IPS_CONFIRMED;
 
-	err = ctnetlink_change_status(ct, cda);
-	if (err < 0)
-		goto err;
+	if (cda[CTA_STATUS-1]) {
+		err = ctnetlink_change_status(ct, cda);
+		if (err < 0)
+			goto err;
+	}
 
 	if (cda[CTA_PROTOINFO-1]) {
 		err = ctnetlink_change_protoinfo(ct, cda);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 7357b8f..ba77183 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -963,9 +963,11 @@ ctnetlink_create_conntrack(struct nfattr
 	ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
 	ct->status |= IPS_CONFIRMED;
 
-	err = ctnetlink_change_status(ct, cda);
-	if (err < 0)
-		goto err;
+	if (cda[CTA_STATUS-1]) {
+		err = ctnetlink_change_status(ct, cda);
+		if (err < 0)
+			goto err;
+	}
 
 	if (cda[CTA_PROTOINFO-1]) {
 		err = ctnetlink_change_protoinfo(ct, cda);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 25/33]: ctnetlink: rework conntrack fields dumping logic on events
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (23 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 24/33]: ctnetlink: check for status attribute existence on conntrack creation Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 26/33]: nfnetlink_queue: allow changing queue length through netlink Patrick McHardy
                   ` (8 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: ctnetlink: rework conntrack fields dumping logic on events

               |   NEW   | UPDATE  | DESTROY |
     ----------------------------------------|
     tuples    |    Y    |    Y    |    Y    |
     status    |    Y    |    Y    |    N    |
     timeout   |    Y    |    Y    |    N    |
     protoinfo |    S    |    S    |    N    |
     helper    |    S    |    S    |    N    |
     mark      |    S    |    S    |    N    |
     counters  |    F    |    F    |    Y    |

 Leyend:
         Y: yes
         N: no
         S: iif the field is set
	 F: iif overflow

This patch also replace IPCT_HELPINFO by IPCT_HELPER since we want to
track the helper assignation process, not the changes in the private
information held by the helper.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 29bacca329c6e3b2c1db0dcf5e9af0c25f62e499
tree 10e555cb146f9d240e5a0493b6f4c6ec1d96a343
parent 9f1f643dcb442e2bd19afd3fec8d1a3958cf5629
author Pablo Neira Ayuso <pablo@netfilter.org> Tue, 28 Nov 2006 23:13:15 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:51 +0100

 net/ipv4/netfilter/ip_conntrack_netlink.c |   49 ++++++++++++++++-------------
 net/netfilter/nf_conntrack_netlink.c      |   49 ++++++++++++++++-------------
 2 files changed, 54 insertions(+), 44 deletions(-)

diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index d5d2efd..5fcf91d 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -320,8 +320,6 @@ static int ctnetlink_conntrack_event(str
 	} else if (events & (IPCT_NEW | IPCT_RELATED)) {
 		type = IPCTNL_MSG_CT_NEW;
 		flags = NLM_F_CREATE|NLM_F_EXCL;
-		/* dump everything */
-		events = ~0UL;
 		group = NFNLGRP_CONNTRACK_NEW;
 	} else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
 		type = IPCTNL_MSG_CT_NEW;
@@ -356,28 +354,35 @@ static int ctnetlink_conntrack_event(str
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 		goto nfattr_failure;
 	NFA_NEST_END(skb, nest_parms);
-	
-	/* NAT stuff is now a status flag */
-	if ((events & IPCT_STATUS || events & IPCT_NATINFO)
-	    && ctnetlink_dump_status(skb, ct) < 0)
-		goto nfattr_failure;
-	if (events & IPCT_REFRESH
-	    && ctnetlink_dump_timeout(skb, ct) < 0)
-		goto nfattr_failure;
-	if (events & IPCT_PROTOINFO
-	    && ctnetlink_dump_protoinfo(skb, ct) < 0)
-		goto nfattr_failure;
-	if (events & IPCT_HELPINFO
-	    && ctnetlink_dump_helpinfo(skb, ct) < 0)
-		goto nfattr_failure;
 
-	if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
-	    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
-		goto nfattr_failure;
+	if (events & IPCT_DESTROY) {
+		if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+		    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
+			goto nfattr_failure;
+	} else {
+		if (ctnetlink_dump_status(skb, ct) < 0)
+			goto nfattr_failure;
 
-	if (events & IPCT_MARK
-	    && ctnetlink_dump_mark(skb, ct) < 0)
-		goto nfattr_failure;
+		if (ctnetlink_dump_timeout(skb, ct) < 0)
+			goto nfattr_failure;
+
+		if (events & IPCT_PROTOINFO
+		    && ctnetlink_dump_protoinfo(skb, ct) < 0)
+		    	goto nfattr_failure;
+
+		if ((events & IPCT_HELPER || ct->helper)
+		    && ctnetlink_dump_helpinfo(skb, ct) < 0)
+		    	goto nfattr_failure;
+
+		if ((events & IPCT_MARK || ct->mark)
+		    && ctnetlink_dump_mark(skb, ct) < 0)
+		    	goto nfattr_failure;
+
+		if (events & IPCT_COUNTER_FILLING &&
+		    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+		     ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
+			goto nfattr_failure;
+	}
 
 	nlh->nlmsg_len = skb->tail - b;
 	nfnetlink_send(skb, 0, group, 0);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index ba77183..e3a7204 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -331,8 +331,6 @@ static int ctnetlink_conntrack_event(str
 	} else  if (events & (IPCT_NEW | IPCT_RELATED)) {
 		type = IPCTNL_MSG_CT_NEW;
 		flags = NLM_F_CREATE|NLM_F_EXCL;
-		/* dump everything */
-		events = ~0UL;
 		group = NFNLGRP_CONNTRACK_NEW;
 	} else  if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
 		type = IPCTNL_MSG_CT_NEW;
@@ -367,28 +365,35 @@ static int ctnetlink_conntrack_event(str
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 		goto nfattr_failure;
 	NFA_NEST_END(skb, nest_parms);
-	
-	/* NAT stuff is now a status flag */
-	if ((events & IPCT_STATUS || events & IPCT_NATINFO)
-	    && ctnetlink_dump_status(skb, ct) < 0)
-		goto nfattr_failure;
-	if (events & IPCT_REFRESH
-	    && ctnetlink_dump_timeout(skb, ct) < 0)
-		goto nfattr_failure;
-	if (events & IPCT_PROTOINFO
-	    && ctnetlink_dump_protoinfo(skb, ct) < 0)
-		goto nfattr_failure;
-	if (events & IPCT_HELPINFO
-	    && ctnetlink_dump_helpinfo(skb, ct) < 0)
-		goto nfattr_failure;
 
-	if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
-	    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
-		goto nfattr_failure;
+	if (events & IPCT_DESTROY) {
+		if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+		    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
+			goto nfattr_failure;
+	} else {
+		if (ctnetlink_dump_status(skb, ct) < 0)
+			goto nfattr_failure;
 
-	if (events & IPCT_MARK
-	    && ctnetlink_dump_mark(skb, ct) < 0)
-		goto nfattr_failure;
+		if (ctnetlink_dump_timeout(skb, ct) < 0)
+			goto nfattr_failure;
+
+		if (events & IPCT_PROTOINFO
+		    && ctnetlink_dump_protoinfo(skb, ct) < 0)
+		    	goto nfattr_failure;
+
+		if ((events & IPCT_HELPER || nfct_help(ct))
+		    && ctnetlink_dump_helpinfo(skb, ct) < 0)
+		    	goto nfattr_failure;
+
+		if ((events & IPCT_MARK || ct->mark)
+		    && ctnetlink_dump_mark(skb, ct) < 0)
+		    	goto nfattr_failure;
+
+		if (events & IPCT_COUNTER_FILLING &&
+		    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+		     ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
+			goto nfattr_failure;
+	}
 
 	nlh->nlmsg_len = skb->tail - b;
 	nfnetlink_send(skb, 0, group, 0);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 26/33]: nfnetlink_queue: allow changing queue length through netlink
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (24 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 25/33]: ctnetlink: rework conntrack fields dumping logic on events Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 27/33]: nfnetlink_log: remove useless prefix length limitation Patrick McHardy
                   ` (7 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nfnetlink_queue: allow changing queue length through netlink

Signed-off-by: Eric Leblond <eric@inl.fr>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit ffbf4d47cf2bcd15709396b97b609346be6cc7fd
tree 76e5aac04f1750ae27b66eac7baadda66776f6d3
parent 29bacca329c6e3b2c1db0dcf5e9af0c25f62e499
author Eric Leblond <eric@inl.fr> Tue, 28 Nov 2006 23:13:09 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:52 +0100

 include/linux/netfilter/nfnetlink_queue.h |    1 +
 net/netfilter/nfnetlink_queue.c           |    8 ++++++++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index 4beea3d..83e7896 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -82,6 +82,7 @@ enum nfqnl_attr_config {
 	NFQA_CFG_UNSPEC,
 	NFQA_CFG_CMD,			/* nfqnl_msg_config_cmd */
 	NFQA_CFG_PARAMS,		/* nfqnl_msg_config_params */
+	NFQA_CFG_QUEUE_MAXLEN,		/* u_int32_t */
 	__NFQA_CFG_MAX
 };
 #define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 82e4454..a88a017 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -947,6 +947,14 @@ nfqnl_recv_config(struct sock *ctnl, str
 				ntohl(params->copy_range));
 	}
 
+	if (nfqa[NFQA_CFG_QUEUE_MAXLEN-1]) {
+		__be32 *queue_maxlen;
+		queue_maxlen = NFA_DATA(nfqa[NFQA_CFG_QUEUE_MAXLEN-1]);
+		spin_lock_bh(&queue->lock);
+		queue->queue_maxlen = ntohl(*queue_maxlen);
+		spin_unlock_bh(&queue->lock);
+	}
+
 out_put:
 	instance_put(queue);
 	return ret;

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 27/33]: nfnetlink_log: remove useless prefix length limitation
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (25 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 26/33]: nfnetlink_queue: allow changing queue length through netlink Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6 Patrick McHardy
                   ` (6 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: nfnetlink_log: remove useless prefix length limitation

There is no reason for limiting netlink attributes in size.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit bbdbeb2dc5f53eb0ce24e8f78edda1671ef4e54a
tree d6841f882b2e9fa6003fc672c7815771b63f59ab
parent ffbf4d47cf2bcd15709396b97b609346be6cc7fd
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:11 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:52 +0100

 include/linux/netfilter/nfnetlink_log.h |    2 --
 net/netfilter/nfnetlink_log.c           |   19 ++++++++++---------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index 55a2a2b..5966afa 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -32,8 +32,6 @@ struct nfulnl_msg_packet_timestamp {
 	aligned_be64	usec;
 };
 
-#define NFULNL_PREFIXLEN	30	/* just like old log target */
-
 enum nfulnl_attr_type {
 	NFULA_UNSPEC,
 	NFULA_PACKET_HDR,
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index bd3ffa6..d1505dd 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -408,7 +408,7 @@ __build_packet_message(struct nfulnl_ins
 			const struct net_device *indev,
 			const struct net_device *outdev,
 			const struct nf_loginfo *li,
-			const char *prefix)
+			const char *prefix, unsigned int plen)
 {
 	unsigned char *old_tail;
 	struct nfulnl_msg_packet_hdr pmsg;
@@ -432,12 +432,8 @@ __build_packet_message(struct nfulnl_ins
 
 	NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
 
-	if (prefix) {
-		int slen = strlen(prefix);
-		if (slen > NFULNL_PREFIXLEN)
-			slen = NFULNL_PREFIXLEN;
-		NFA_PUT(inst->skb, NFULA_PREFIX, slen, prefix);
-	}
+	if (prefix)
+		NFA_PUT(inst->skb, NFULA_PREFIX, plen, prefix);
 
 	if (indev) {
 		tmp_uint = htonl(indev->ifindex);
@@ -601,6 +597,7 @@ nfulnl_log_packet(unsigned int pf,
 	const struct nf_loginfo *li;
 	unsigned int qthreshold;
 	unsigned int nlbufsiz;
+	unsigned int plen;
 
 	if (li_user && li_user->type == NF_LOG_TYPE_ULOG) 
 		li = li_user;
@@ -616,6 +613,10 @@ nfulnl_log_packet(unsigned int pf,
 		return;
 	}
 
+	plen = 0;
+	if (prefix)
+		plen = strlen(prefix);
+
 	/* all macros expand to constant values at compile time */
 	/* FIXME: do we want to make the size calculation conditional based on
 	 * what is actually present?  way more branches and checks, but more
@@ -630,7 +631,7 @@ #ifdef CONFIG_BRIDGE_NETFILTER
 #endif
 		+ NFA_SPACE(sizeof(u_int32_t))	/* mark */
 		+ NFA_SPACE(sizeof(u_int32_t))	/* uid */
-		+ NFA_SPACE(NFULNL_PREFIXLEN)	/* prefix */
+		+ NFA_SPACE(plen)		/* prefix */
 		+ NFA_SPACE(sizeof(struct nfulnl_msg_packet_hw))
 		+ NFA_SPACE(sizeof(struct nfulnl_msg_packet_timestamp));
 
@@ -701,7 +702,7 @@ #endif
 	inst->qlen++;
 
 	__build_packet_message(inst, skb, data_len, pf,
-				hooknum, in, out, li, prefix);
+				hooknum, in, out, li, prefix, plen);
 
 	/* timer_pending always called within inst->lock, so there
 	 * is no chance of a race here */

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (26 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 27/33]: nfnetlink_log: remove useless prefix length limitation Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-12-03  4:01   ` Yasuyuki KOZAKAI
                     ` (2 more replies)
  2006-11-29  2:09 ` [NETFILTER 29/33]: x_tables: add NFLOG target Patrick McHardy
                   ` (5 subsequent siblings)
  33 siblings, 3 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 49049 bytes --]

[NETFILTER]: x_tables: add port of hashlimit match for IPv4 and IPv6

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 5fbcf255408abf92eac14816032a4ecac6a7f8c1
tree 1149a5a9ddbfbb5bee64daf36a26a4bdac91a5bf
parent bbdbeb2dc5f53eb0ce24e8f78edda1671ef4e54a
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:08 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:53 +0100

 include/linux/netfilter/Kbuild               |    1 
 include/linux/netfilter/xt_hashlimit.h       |   40 +
 include/linux/netfilter_ipv4/ipt_hashlimit.h |   42 -
 net/ipv4/netfilter/Kconfig                   |   14 
 net/ipv4/netfilter/Makefile                  |    1 
 net/ipv4/netfilter/ipt_hashlimit.c           |  733 -------------------------
 net/netfilter/Kconfig                        |   14 
 net/netfilter/Makefile                       |    1 
 net/netfilter/xt_hashlimit.c                 |  772 ++++++++++++++++++++++++++
 9 files changed, 836 insertions(+), 782 deletions(-)

diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index 312bd2f..e379a2d 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -14,6 +14,7 @@ header-y += xt_dscp.h
 header-y += xt_DSCP.h
 header-y += xt_esp.h
 header-y += xt_helper.h
+header-y += xt_hashlimit.h
 header-y += xt_length.h
 header-y += xt_limit.h
 header-y += xt_mac.h
diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h
new file mode 100644
index 0000000..b4556b8
--- /dev/null
+++ b/include/linux/netfilter/xt_hashlimit.h
@@ -0,0 +1,40 @@
+#ifndef _XT_HASHLIMIT_H
+#define _XT_HASHLIMIT_H
+
+/* timings are in milliseconds. */
+#define XT_HASHLIMIT_SCALE 10000
+/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
+   seconds, or one every 59 hours. */
+
+/* details of this structure hidden by the implementation */
+struct xt_hashlimit_htable;
+
+#define XT_HASHLIMIT_HASH_DIP	0x0001
+#define XT_HASHLIMIT_HASH_DPT	0x0002
+#define XT_HASHLIMIT_HASH_SIP	0x0004
+#define XT_HASHLIMIT_HASH_SPT	0x0008
+
+struct hashlimit_cfg {
+	u_int32_t mode;	  /* bitmask of IPT_HASHLIMIT_HASH_* */
+	u_int32_t avg;    /* Average secs between packets * scale */
+	u_int32_t burst;  /* Period multiplier for upper limit. */
+
+	/* user specified */
+	u_int32_t size;		/* how many buckets */
+	u_int32_t max;		/* max number of entries */
+	u_int32_t gc_interval;	/* gc interval */
+	u_int32_t expire;	/* when do entries expire? */
+};
+
+struct xt_hashlimit_info {
+	char name [IFNAMSIZ];		/* name */
+	struct hashlimit_cfg cfg;
+	struct xt_hashlimit_htable *hinfo;
+
+	/* Used internally by the kernel */
+	union {
+		void *ptr;
+		struct xt_hashlimit_info *master;
+	} u;
+};
+#endif /*_XT_HASHLIMIT_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_hashlimit.h b/include/linux/netfilter_ipv4/ipt_hashlimit.h
index ac2cb64..5662120 100644
--- a/include/linux/netfilter_ipv4/ipt_hashlimit.h
+++ b/include/linux/netfilter_ipv4/ipt_hashlimit.h
@@ -1,40 +1,14 @@
 #ifndef _IPT_HASHLIMIT_H
 #define _IPT_HASHLIMIT_H
 
-/* timings are in milliseconds. */
-#define IPT_HASHLIMIT_SCALE 10000
-/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
-   seconds, or one every 59 hours. */
+#include <linux/netfilter/xt_hashlimit.h>
 
-/* details of this structure hidden by the implementation */
-struct ipt_hashlimit_htable;
+#define IPT_HASHLIMIT_SCALE	XT_HASHLIMIT_SCALE
+#define IPT_HASHLIMIT_HASH_DIP	XT_HASHLIMIT_HASH_DIP
+#define IPT_HASHLIMIT_HASH_DPT	XT_HASHLIMIT_HASH_DPT
+#define IPT_HASHLIMIT_HASH_SIP	XT_HASHLIMIT_HASH_SIP
+#define IPT_HASHLIMIT_HASH_SPT	XT_HASHLIMIT_HASH_SPT
 
-#define IPT_HASHLIMIT_HASH_DIP	0x0001
-#define IPT_HASHLIMIT_HASH_DPT	0x0002
-#define IPT_HASHLIMIT_HASH_SIP	0x0004
-#define IPT_HASHLIMIT_HASH_SPT	0x0008
+#define ipt_hashlimit_info xt_hashlimit_info
 
-struct hashlimit_cfg {
-	u_int32_t mode;	  /* bitmask of IPT_HASHLIMIT_HASH_* */
-	u_int32_t avg;    /* Average secs between packets * scale */
-	u_int32_t burst;  /* Period multiplier for upper limit. */
-
-	/* user specified */
-	u_int32_t size;		/* how many buckets */
-	u_int32_t max;		/* max number of entries */
-	u_int32_t gc_interval;	/* gc interval */
-	u_int32_t expire;	/* when do entries expire? */
-};
-
-struct ipt_hashlimit_info {
-	char name [IFNAMSIZ];		/* name */
-	struct hashlimit_cfg cfg;
-	struct ipt_hashlimit_htable *hinfo;
-
-	/* Used internally by the kernel */
-	union {
-		void *ptr;
-		struct ipt_hashlimit_info *master;
-	} u;
-};
-#endif /*_IPT_HASHLIMIT_H*/
+#endif /* _IPT_HASHLIMIT_H */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 4ac5b5c..bc298a3 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -326,20 +326,6 @@ config IP_NF_MATCH_ADDRTYPE
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 
-config IP_NF_MATCH_HASHLIMIT
-	tristate  'hashlimit match support'
-	depends on IP_NF_IPTABLES
-	help
-	  This option adds a new iptables `hashlimit' match.  
-
-	  As opposed to `limit', this match dynamically creates a hash table
-	  of limit buckets, based on your selection of source/destination
-	  ip addresses and/or ports.
-
-	  It enables you to express policies like `10kpps for any given
-	  destination IP' or `500pps from any given source IP'  with a single
-	  IPtables rule.
-
 # `filter', generic and specific targets
 config IP_NF_FILTER
 	tristate "Packet filtering"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 4ce20eb..21359d8 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -53,7 +53,6 @@ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
 
 # matches
-obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
deleted file mode 100644
index 33ccdbf..0000000
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/* iptables match extension to limit the number of packets per second
- * seperately for each hashbucket (sourceip/sourceport/dstip/dstport)
- *
- * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
- *
- * $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $
- *
- * Development of this code was funded by Astaro AG, http://www.astaro.com/
- *
- * based on ipt_limit.c by:
- * Jérôme de Vivie	<devivie@info.enserb.u-bordeaux.fr>
- * Hervé Eychenne	<eychenne@info.enserb.u-bordeaux.fr>
- * Rusty Russell	<rusty@rustcorp.com.au>
- *
- * The general idea is to create a hash table for every dstip and have a
- * seperate limit counter per tuple.  This way you can do something like 'limit
- * the number of syn packets for each of my internal addresses.
- *
- * Ideally this would just be implemented as a general 'hash' match, which would
- * allow us to attach any iptables target to it's hash buckets.  But this is
- * not possible in the current iptables architecture.  As always, pkttables for
- * 2.7.x will help ;)
- */
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/random.h>
-#include <linux/jhash.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/list.h>
-
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_hashlimit.h>
-
-/* FIXME: this is just for IP_NF_ASSERRT */
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/mutex.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("iptables match for limiting per hash-bucket");
-
-/* need to declare this at the top */
-static struct proc_dir_entry *hashlimit_procdir;
-static struct file_operations dl_file_ops;
-
-/* hash table crap */
-
-struct dsthash_dst {
-	__be32 src_ip;
-	__be32 dst_ip;
-	/* ports have to be consecutive !!! */
-	__be16 src_port;
-	__be16 dst_port;
-};
-
-struct dsthash_ent {
-	/* static / read-only parts in the beginning */
-	struct hlist_node node;
-	struct dsthash_dst dst;
-
-	/* modified structure members in the end */
-	unsigned long expires;		/* precalculated expiry time */
-	struct {
-		unsigned long prev;	/* last modification */
-		u_int32_t credit;
-		u_int32_t credit_cap, cost;
-	} rateinfo;
-};
-
-struct ipt_hashlimit_htable {
-	struct hlist_node node;		/* global list of all htables */
-	atomic_t use;
-
-	struct hashlimit_cfg cfg;	/* config */
-
-	/* used internally */
-	spinlock_t lock;		/* lock for list_head */
-	u_int32_t rnd;			/* random seed for hash */
-	int rnd_initialized;
-	struct timer_list timer;	/* timer for gc */
-	atomic_t count;			/* number entries in table */
-
-	/* seq_file stuff */
-	struct proc_dir_entry *pde;
-
-	struct hlist_head hash[0];	/* hashtable itself */
-};
-
-static DEFINE_SPINLOCK(hashlimit_lock);	/* protects htables list */
-static DEFINE_MUTEX(hlimit_mutex);	/* additional checkentry protection */
-static HLIST_HEAD(hashlimit_htables);
-static kmem_cache_t *hashlimit_cachep __read_mostly;
-
-static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
-{
-	return (ent->dst.dst_ip == b->dst_ip 
-		&& ent->dst.dst_port == b->dst_port
-		&& ent->dst.src_port == b->src_port
-		&& ent->dst.src_ip == b->src_ip);
-}
-
-static inline u_int32_t
-hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst)
-{
-	return (jhash_3words((__force u32)dst->dst_ip,
-			    ((__force u32)dst->dst_port<<16 |
-			     (__force u32)dst->src_port),
-			     (__force u32)dst->src_ip, ht->rnd) % ht->cfg.size);
-}
-
-static inline struct dsthash_ent *
-__dsthash_find(const struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
-{
-	struct dsthash_ent *ent;
-	struct hlist_node *pos;
-	u_int32_t hash = hash_dst(ht, dst);
-
-	if (!hlist_empty(&ht->hash[hash]))
-		hlist_for_each_entry(ent, pos, &ht->hash[hash], node) {
-			if (dst_cmp(ent, dst)) {
-				return ent;
-			}
-		}
-	
-	return NULL;
-}
-
-/* allocate dsthash_ent, initialize dst, put in htable and lock it */
-static struct dsthash_ent *
-__dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
-{
-	struct dsthash_ent *ent;
-
-	/* initialize hash with random val at the time we allocate
-	 * the first hashtable entry */
-	if (!ht->rnd_initialized) {
-		get_random_bytes(&ht->rnd, 4);
-		ht->rnd_initialized = 1;
-	}
-
-	if (ht->cfg.max &&
-	    atomic_read(&ht->count) >= ht->cfg.max) {
-		/* FIXME: do something. question is what.. */
-		if (net_ratelimit())
-			printk(KERN_WARNING 
-				"ipt_hashlimit: max count of %u reached\n", 
-				ht->cfg.max);
-		return NULL;
-	}
-
-	ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC);
-	if (!ent) {
-		if (net_ratelimit())
-			printk(KERN_ERR 
-				"ipt_hashlimit: can't allocate dsthash_ent\n");
-		return NULL;
-	}
-
-	atomic_inc(&ht->count);
-
-	ent->dst.dst_ip = dst->dst_ip;
-	ent->dst.dst_port = dst->dst_port;
-	ent->dst.src_ip = dst->src_ip;
-	ent->dst.src_port = dst->src_port;
-
-	hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]);
-
-	return ent;
-}
-
-static inline void 
-__dsthash_free(struct ipt_hashlimit_htable *ht, struct dsthash_ent *ent)
-{
-	hlist_del(&ent->node);
-	kmem_cache_free(hashlimit_cachep, ent);
-	atomic_dec(&ht->count);
-}
-static void htable_gc(unsigned long htlong);
-
-static int htable_create(struct ipt_hashlimit_info *minfo)
-{
-	int i;
-	unsigned int size;
-	struct ipt_hashlimit_htable *hinfo;
-
-	if (minfo->cfg.size)
-		size = minfo->cfg.size;
-	else {
-		size = (((num_physpages << PAGE_SHIFT) / 16384)
-			 / sizeof(struct list_head));
-		if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
-			size = 8192;
-		if (size < 16)
-			size = 16;
-	}
-	/* FIXME: don't use vmalloc() here or anywhere else -HW */
-	hinfo = vmalloc(sizeof(struct ipt_hashlimit_htable)
-			+ (sizeof(struct list_head) * size));
-	if (!hinfo) {
-		printk(KERN_ERR "ipt_hashlimit: Unable to create hashtable\n");
-		return -1;
-	}
-	minfo->hinfo = hinfo;
-
-	/* copy match config into hashtable config */
-	memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
-	hinfo->cfg.size = size;
-	if (!hinfo->cfg.max)
-		hinfo->cfg.max = 8 * hinfo->cfg.size;
-	else if (hinfo->cfg.max < hinfo->cfg.size)
-		hinfo->cfg.max = hinfo->cfg.size;
-
-	for (i = 0; i < hinfo->cfg.size; i++)
-		INIT_HLIST_HEAD(&hinfo->hash[i]);
-
-	atomic_set(&hinfo->count, 0);
-	atomic_set(&hinfo->use, 1);
-	hinfo->rnd_initialized = 0;
-	spin_lock_init(&hinfo->lock);
-	hinfo->pde = create_proc_entry(minfo->name, 0, hashlimit_procdir);
-	if (!hinfo->pde) {
-		vfree(hinfo);
-		return -1;
-	}
-	hinfo->pde->proc_fops = &dl_file_ops;
-	hinfo->pde->data = hinfo;
-
-	init_timer(&hinfo->timer);
-	hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval);
-	hinfo->timer.data = (unsigned long )hinfo;
-	hinfo->timer.function = htable_gc;
-	add_timer(&hinfo->timer);
-
-	spin_lock_bh(&hashlimit_lock);
-	hlist_add_head(&hinfo->node, &hashlimit_htables);
-	spin_unlock_bh(&hashlimit_lock);
-
-	return 0;
-}
-
-static int select_all(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he)
-{
-	return 1;
-}
-
-static int select_gc(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he)
-{
-	return (jiffies >= he->expires);
-}
-
-static void htable_selective_cleanup(struct ipt_hashlimit_htable *ht,
-		 		int (*select)(struct ipt_hashlimit_htable *ht, 
-					      struct dsthash_ent *he))
-{
-	int i;
-
-	IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
-
-	/* lock hash table and iterate over it */
-	spin_lock_bh(&ht->lock);
-	for (i = 0; i < ht->cfg.size; i++) {
-		struct dsthash_ent *dh;
-		struct hlist_node *pos, *n;
-		hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) {
-			if ((*select)(ht, dh))
-				__dsthash_free(ht, dh);
-		}
-	}
-	spin_unlock_bh(&ht->lock);
-}
-
-/* hash table garbage collector, run by timer */
-static void htable_gc(unsigned long htlong)
-{
-	struct ipt_hashlimit_htable *ht = (struct ipt_hashlimit_htable *)htlong;
-
-	htable_selective_cleanup(ht, select_gc);
-
-	/* re-add the timer accordingly */
-	ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval);
-	add_timer(&ht->timer);
-}
-
-static void htable_destroy(struct ipt_hashlimit_htable *hinfo)
-{
-	/* remove timer, if it is pending */
-	if (timer_pending(&hinfo->timer))
-		del_timer(&hinfo->timer);
-
-	/* remove proc entry */
-	remove_proc_entry(hinfo->pde->name, hashlimit_procdir);
-
-	htable_selective_cleanup(hinfo, select_all);
-	vfree(hinfo);
-}
-
-static struct ipt_hashlimit_htable *htable_find_get(char *name)
-{
-	struct ipt_hashlimit_htable *hinfo;
-	struct hlist_node *pos;
-
-	spin_lock_bh(&hashlimit_lock);
-	hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
-		if (!strcmp(name, hinfo->pde->name)) {
-			atomic_inc(&hinfo->use);
-			spin_unlock_bh(&hashlimit_lock);
-			return hinfo;
-		}
-	}
-	spin_unlock_bh(&hashlimit_lock);
-
-	return NULL;
-}
-
-static void htable_put(struct ipt_hashlimit_htable *hinfo)
-{
-	if (atomic_dec_and_test(&hinfo->use)) {
-		spin_lock_bh(&hashlimit_lock);
-		hlist_del(&hinfo->node);
-		spin_unlock_bh(&hashlimit_lock);
-		htable_destroy(hinfo);
-	}
-}
-
-
-/* The algorithm used is the Simple Token Bucket Filter (TBF)
- * see net/sched/sch_tbf.c in the linux source tree
- */
-
-/* Rusty: This is my (non-mathematically-inclined) understanding of
-   this algorithm.  The `average rate' in jiffies becomes your initial
-   amount of credit `credit' and the most credit you can ever have
-   `credit_cap'.  The `peak rate' becomes the cost of passing the
-   test, `cost'.
-
-   `prev' tracks the last packet hit: you gain one credit per jiffy.
-   If you get credit balance more than this, the extra credit is
-   discarded.  Every time the match passes, you lose `cost' credits;
-   if you don't have that many, the test fails.
-
-   See Alexey's formal explanation in net/sched/sch_tbf.c.
-
-   To get the maximum range, we multiply by this factor (ie. you get N
-   credits per jiffy).  We want to allow a rate as low as 1 per day
-   (slowest userspace tool allows), which means
-   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
-*/
-#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
-
-/* Repeated shift and or gives us all 1s, final shift and add 1 gives
- * us the power of 2 below the theoretical max, so GCC simply does a
- * shift. */
-#define _POW2_BELOW2(x) ((x)|((x)>>1))
-#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
-#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
-#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
-#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
-#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
-
-#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
-
-/* Precision saver. */
-static inline u_int32_t
-user2credits(u_int32_t user)
-{
-	/* If multiplying would overflow... */
-	if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
-		/* Divide first. */
-		return (user / IPT_HASHLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
-
-	return (user * HZ * CREDITS_PER_JIFFY) / IPT_HASHLIMIT_SCALE;
-}
-
-static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
-{
-	dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
-					* CREDITS_PER_JIFFY;
-	if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
-		dh->rateinfo.credit = dh->rateinfo.credit_cap;
-}
-
-static int
-hashlimit_match(const struct sk_buff *skb,
-		const struct net_device *in,
-		const struct net_device *out,
-		const struct xt_match *match,
-		const void *matchinfo,
-		int offset,
-		unsigned int protoff,
-		int *hotdrop)
-{
-	struct ipt_hashlimit_info *r = 
-		((struct ipt_hashlimit_info *)matchinfo)->u.master;
-	struct ipt_hashlimit_htable *hinfo = r->hinfo;
-	unsigned long now = jiffies;
-	struct dsthash_ent *dh;
-	struct dsthash_dst dst;
-
-	/* build 'dst' according to hinfo->cfg and current packet */
-	memset(&dst, 0, sizeof(dst));
-	if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DIP)
-		dst.dst_ip = skb->nh.iph->daddr;
-	if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SIP)
-		dst.src_ip = skb->nh.iph->saddr;
-	if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT
-	    ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
-		__be16 _ports[2], *ports;
-
-		switch (skb->nh.iph->protocol) {
-		case IPPROTO_TCP:
-		case IPPROTO_UDP:
-		case IPPROTO_SCTP:
-		case IPPROTO_DCCP:
-			ports = skb_header_pointer(skb, skb->nh.iph->ihl*4,
-						   sizeof(_ports), &_ports);
-			break;
-		default:
-			_ports[0] = _ports[1] = 0;
-			ports = _ports;
-			break;
-		}
-		if (!ports) {
-			/* We've been asked to examine this packet, and we
-		 	  can't.  Hence, no choice but to drop. */
-			*hotdrop = 1;
-			return 0;
-		}
-		if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT)
-			dst.src_port = ports[0];
-		if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT)
-			dst.dst_port = ports[1];
-	} 
-
-	spin_lock_bh(&hinfo->lock);
-	dh = __dsthash_find(hinfo, &dst);
-	if (!dh) {
-		dh = __dsthash_alloc_init(hinfo, &dst);
-
-		if (!dh) {
-			/* enomem... don't match == DROP */
-			if (net_ratelimit())
-				printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
-			spin_unlock_bh(&hinfo->lock);
-			return 0;
-		}
-
-		dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
-
-		dh->rateinfo.prev = jiffies;
-		dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
-							hinfo->cfg.burst);
-		dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
-							hinfo->cfg.burst);
-		dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
-	} else {
-		/* update expiration timeout */
-		dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
-		rateinfo_recalc(dh, now);
-	}
-
-	if (dh->rateinfo.credit >= dh->rateinfo.cost) {
-		/* We're underlimit. */
-		dh->rateinfo.credit -= dh->rateinfo.cost;
-		spin_unlock_bh(&hinfo->lock);
-		return 1;
-	}
-
-       	spin_unlock_bh(&hinfo->lock);
-
-	/* default case: we're overlimit, thus don't match */
-	return 0;
-}
-
-static int
-hashlimit_checkentry(const char *tablename,
-		     const void *inf,
-		     const struct xt_match *match,
-		     void *matchinfo,
-		     unsigned int hook_mask)
-{
-	struct ipt_hashlimit_info *r = matchinfo;
-
-	/* Check for overflow. */
-	if (r->cfg.burst == 0
-	    || user2credits(r->cfg.avg * r->cfg.burst) < 
-	    				user2credits(r->cfg.avg)) {
-		printk(KERN_ERR "ipt_hashlimit: Overflow, try lower: %u/%u\n",
-		       r->cfg.avg, r->cfg.burst);
-		return 0;
-	}
-
-	if (r->cfg.mode == 0 
-	    || r->cfg.mode > (IPT_HASHLIMIT_HASH_DPT
-		          |IPT_HASHLIMIT_HASH_DIP
-			  |IPT_HASHLIMIT_HASH_SIP
-			  |IPT_HASHLIMIT_HASH_SPT))
-		return 0;
-
-	if (!r->cfg.gc_interval)
-		return 0;
-	
-	if (!r->cfg.expire)
-		return 0;
-
-	if (r->name[sizeof(r->name) - 1] != '\0')
-		return 0;
-
-	/* This is the best we've got: We cannot release and re-grab lock,
-	 * since checkentry() is called before ip_tables.c grabs ipt_mutex.  
-	 * We also cannot grab the hashtable spinlock, since htable_create will 
-	 * call vmalloc, and that can sleep.  And we cannot just re-search
-	 * the list of htable's in htable_create(), since then we would
-	 * create duplicate proc files. -HW */
-	mutex_lock(&hlimit_mutex);
-	r->hinfo = htable_find_get(r->name);
-	if (!r->hinfo && (htable_create(r) != 0)) {
-		mutex_unlock(&hlimit_mutex);
-		return 0;
-	}
-	mutex_unlock(&hlimit_mutex);
-
-	/* Ugly hack: For SMP, we only want to use one set */
-	r->u.master = r;
-
-	return 1;
-}
-
-static void
-hashlimit_destroy(const struct xt_match *match, void *matchinfo)
-{
-	struct ipt_hashlimit_info *r = matchinfo;
-
-	htable_put(r->hinfo);
-}
-
-#ifdef CONFIG_COMPAT
-struct compat_ipt_hashlimit_info {
-	char name[IFNAMSIZ];
-	struct hashlimit_cfg cfg;
-	compat_uptr_t hinfo;
-	compat_uptr_t master;
-};
-
-static void compat_from_user(void *dst, void *src)
-{
-	int off = offsetof(struct compat_ipt_hashlimit_info, hinfo);
-
-	memcpy(dst, src, off);
-	memset(dst + off, 0, sizeof(struct compat_ipt_hashlimit_info) - off);
-}
-
-static int compat_to_user(void __user *dst, void *src)
-{
-	int off = offsetof(struct compat_ipt_hashlimit_info, hinfo);
-
-	return copy_to_user(dst, src, off) ? -EFAULT : 0;
-}
-#endif
-
-static struct ipt_match ipt_hashlimit = {
-	.name		= "hashlimit",
-	.match		= hashlimit_match,
-	.matchsize	= sizeof(struct ipt_hashlimit_info),
-#ifdef CONFIG_COMPAT
-	.compatsize	= sizeof(struct compat_ipt_hashlimit_info),
-	.compat_from_user = compat_from_user,
-	.compat_to_user	= compat_to_user,
-#endif
-	.checkentry	= hashlimit_checkentry,
-	.destroy	= hashlimit_destroy,
-	.me		= THIS_MODULE
-};
-
-/* PROC stuff */
-
-static void *dl_seq_start(struct seq_file *s, loff_t *pos)
-{
-	struct proc_dir_entry *pde = s->private;
-	struct ipt_hashlimit_htable *htable = pde->data;
-	unsigned int *bucket;
-
-	spin_lock_bh(&htable->lock);
-	if (*pos >= htable->cfg.size)
-		return NULL;
-
-	bucket = kmalloc(sizeof(unsigned int), GFP_ATOMIC);
-	if (!bucket)
-		return ERR_PTR(-ENOMEM);
-
-	*bucket = *pos;
-	return bucket;
-}
-
-static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-	struct proc_dir_entry *pde = s->private;
-	struct ipt_hashlimit_htable *htable = pde->data;
-	unsigned int *bucket = (unsigned int *)v;
-
-	*pos = ++(*bucket);
-	if (*pos >= htable->cfg.size) {
-		kfree(v);
-		return NULL;
-	}
-	return bucket;
-}
-
-static void dl_seq_stop(struct seq_file *s, void *v)
-{
-	struct proc_dir_entry *pde = s->private;
-	struct ipt_hashlimit_htable *htable = pde->data;
-	unsigned int *bucket = (unsigned int *)v;
-
-	kfree(bucket);
-
-	spin_unlock_bh(&htable->lock);
-}
-
-static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
-{
-	/* recalculate to show accurate numbers */
-	rateinfo_recalc(ent, jiffies);
-
-	return seq_printf(s, "%ld %u.%u.%u.%u:%u->%u.%u.%u.%u:%u %u %u %u\n",
-			(long)(ent->expires - jiffies)/HZ,
-			NIPQUAD(ent->dst.src_ip), ntohs(ent->dst.src_port),
-			NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.dst_port),
-			ent->rateinfo.credit, ent->rateinfo.credit_cap,
-			ent->rateinfo.cost);
-}
-
-static int dl_seq_show(struct seq_file *s, void *v)
-{
-	struct proc_dir_entry *pde = s->private;
-	struct ipt_hashlimit_htable *htable = pde->data;
-	unsigned int *bucket = (unsigned int *)v;
-	struct dsthash_ent *ent;
-	struct hlist_node *pos;
-
-	if (!hlist_empty(&htable->hash[*bucket]))
-		hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node) {
-			if (dl_seq_real_show(ent, s)) {
-				/* buffer was filled and unable to print that tuple */
-				return 1;
-			}
-		}
-	
-	return 0;
-}
-
-static struct seq_operations dl_seq_ops = {
-	.start = dl_seq_start,
-	.next  = dl_seq_next,
-	.stop  = dl_seq_stop,
-	.show  = dl_seq_show
-};
-
-static int dl_proc_open(struct inode *inode, struct file *file)
-{
-	int ret = seq_open(file, &dl_seq_ops);
-
-	if (!ret) {
-		struct seq_file *sf = file->private_data;
-		sf->private = PDE(inode);
-	}
-	return ret;
-}
-
-static struct file_operations dl_file_ops = {
-	.owner   = THIS_MODULE,
-	.open    = dl_proc_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release
-};
-
-static int init_or_fini(int fini)
-{
-	int ret = 0;
-
-	if (fini)
-		goto cleanup;
-
-	if (ipt_register_match(&ipt_hashlimit)) {
-		ret = -EINVAL;
-		goto cleanup_nothing;
-	}
-
-	hashlimit_cachep = kmem_cache_create("ipt_hashlimit",
-					    sizeof(struct dsthash_ent), 0,
-					    0, NULL, NULL);
-	if (!hashlimit_cachep) {
-		printk(KERN_ERR "Unable to create ipt_hashlimit slab cache\n");
-		ret = -ENOMEM;
-		goto cleanup_unreg_match;
-	}
-
-	hashlimit_procdir = proc_mkdir("ipt_hashlimit", proc_net);
-	if (!hashlimit_procdir) {
-		printk(KERN_ERR "Unable to create proc dir entry\n");
-		ret = -ENOMEM;
-		goto cleanup_free_slab;
-	}
-
-	return ret;
-
-cleanup:
-	remove_proc_entry("ipt_hashlimit", proc_net);
-cleanup_free_slab:
-	kmem_cache_destroy(hashlimit_cachep);
-cleanup_unreg_match:
-	ipt_unregister_match(&ipt_hashlimit);
-cleanup_nothing:
-	return ret;
-	
-}
-
-static int __init ipt_hashlimit_init(void)
-{
-	return init_or_fini(0);
-}
-
-static void __exit ipt_hashlimit_fini(void)
-{
-	init_or_fini(1);
-}
-
-module_init(ipt_hashlimit_init);
-module_exit(ipt_hashlimit_fini);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index f619c65..7e61254 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -464,5 +464,19 @@ config NETFILTER_XT_MATCH_TCPMSS
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_HASHLIMIT
+	tristate '"hashlimit" match support'
+	depends on NETFILTER_XTABLES
+	help
+	  This option adds a `hashlimit' match.
+
+	  As opposed to `limit', this match dynamically creates a hash table
+	  of limit buckets, based on your selection of source/destination
+	  addresses and/or ports.
+
+	  It enables you to express policies like `10kpps for any given
+	  destination address' or `500pps from any given source address'
+	  with a single rule.
+
 endmenu
 
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 84d529d..f85811b 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -59,3 +59,4 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTI
 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
new file mode 100644
index 0000000..46de566
--- /dev/null
+++ b/net/netfilter/xt_hashlimit.c
@@ -0,0 +1,772 @@
+/* iptables match extension to limit the number of packets per second
+ * seperately for each hashbucket (sourceip/sourceport/dstip/dstport)
+ *
+ * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
+ *
+ * $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $
+ *
+ * Development of this code was funded by Astaro AG, http://www.astaro.com/
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/jhash.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/xt_hashlimit.h>
+#include <linux/mutex.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("iptables match for limiting per hash-bucket");
+MODULE_ALIAS("ipt_hashlimit");
+MODULE_ALIAS("ip6t_hashlimit");
+
+/* need to declare this at the top */
+static struct proc_dir_entry *hashlimit_procdir4;
+static struct proc_dir_entry *hashlimit_procdir6;
+static struct file_operations dl_file_ops;
+
+/* hash table crap */
+struct dsthash_dst {
+	union {
+		struct {
+			__be32 src;
+			__be32 dst;
+		} ip;
+		struct {
+			__be32 src[4];
+			__be32 dst[4];
+		} ip6;
+	} addr;
+	__be16 src_port;
+	__be16 dst_port;
+};
+
+struct dsthash_ent {
+	/* static / read-only parts in the beginning */
+	struct hlist_node node;
+	struct dsthash_dst dst;
+
+	/* modified structure members in the end */
+	unsigned long expires;		/* precalculated expiry time */
+	struct {
+		unsigned long prev;	/* last modification */
+		u_int32_t credit;
+		u_int32_t credit_cap, cost;
+	} rateinfo;
+};
+
+struct xt_hashlimit_htable {
+	struct hlist_node node;		/* global list of all htables */
+	atomic_t use;
+	int family;
+
+	struct hashlimit_cfg cfg;	/* config */
+
+	/* used internally */
+	spinlock_t lock;		/* lock for list_head */
+	u_int32_t rnd;			/* random seed for hash */
+	int rnd_initialized;
+	unsigned int count;		/* number entries in table */
+	struct timer_list timer;	/* timer for gc */
+
+	/* seq_file stuff */
+	struct proc_dir_entry *pde;
+
+	struct hlist_head hash[0];	/* hashtable itself */
+};
+
+static DEFINE_SPINLOCK(hashlimit_lock);	/* protects htables list */
+static DEFINE_MUTEX(hlimit_mutex);	/* additional checkentry protection */
+static HLIST_HEAD(hashlimit_htables);
+static kmem_cache_t *hashlimit_cachep __read_mostly;
+
+static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
+{
+	return !memcmp(&ent->dst, b, sizeof(ent->dst));
+}
+
+static u_int32_t
+hash_dst(const struct xt_hashlimit_htable *ht, const struct dsthash_dst *dst)
+{
+	return jhash(dst, sizeof(*dst), ht->rnd) % ht->cfg.size;
+}
+
+static struct dsthash_ent *
+dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+{
+	struct dsthash_ent *ent;
+	struct hlist_node *pos;
+	u_int32_t hash = hash_dst(ht, dst);
+
+	if (!hlist_empty(&ht->hash[hash])) {
+		hlist_for_each_entry(ent, pos, &ht->hash[hash], node)
+			if (dst_cmp(ent, dst))
+				return ent;
+	}
+	return NULL;
+}
+
+/* allocate dsthash_ent, initialize dst, put in htable and lock it */
+static struct dsthash_ent *
+dsthash_alloc_init(struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+{
+	struct dsthash_ent *ent;
+
+	/* initialize hash with random val at the time we allocate
+	 * the first hashtable entry */
+	if (!ht->rnd_initialized) {
+		get_random_bytes(&ht->rnd, 4);
+		ht->rnd_initialized = 1;
+	}
+
+	if (ht->cfg.max && ht->count >= ht->cfg.max) {
+		/* FIXME: do something. question is what.. */
+		if (net_ratelimit())
+			printk(KERN_WARNING
+				"xt_hashlimit: max count of %u reached\n",
+				ht->cfg.max);
+		return NULL;
+	}
+
+	ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC);
+	if (!ent) {
+		if (net_ratelimit())
+			printk(KERN_ERR
+				"xt_hashlimit: can't allocate dsthash_ent\n");
+		return NULL;
+	}
+	memcpy(&ent->dst, dst, sizeof(ent->dst));
+
+	hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]);
+	ht->count++;
+	return ent;
+}
+
+static inline void
+dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent)
+{
+	hlist_del(&ent->node);
+	kmem_cache_free(hashlimit_cachep, ent);
+	ht->count--;
+}
+static void htable_gc(unsigned long htlong);
+
+static int htable_create(struct xt_hashlimit_info *minfo, int family)
+{
+	struct xt_hashlimit_htable *hinfo;
+	unsigned int size;
+	unsigned int i;
+
+	if (minfo->cfg.size)
+		size = minfo->cfg.size;
+	else {
+		size = ((num_physpages << PAGE_SHIFT) / 16384) /
+		       sizeof(struct list_head);
+		if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
+			size = 8192;
+		if (size < 16)
+			size = 16;
+	}
+	/* FIXME: don't use vmalloc() here or anywhere else -HW */
+	hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
+			sizeof(struct list_head) * size);
+	if (!hinfo) {
+		printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n");
+		return -1;
+	}
+	minfo->hinfo = hinfo;
+
+	/* copy match config into hashtable config */
+	memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
+	hinfo->cfg.size = size;
+	if (!hinfo->cfg.max)
+		hinfo->cfg.max = 8 * hinfo->cfg.size;
+	else if (hinfo->cfg.max < hinfo->cfg.size)
+		hinfo->cfg.max = hinfo->cfg.size;
+
+	for (i = 0; i < hinfo->cfg.size; i++)
+		INIT_HLIST_HEAD(&hinfo->hash[i]);
+
+	atomic_set(&hinfo->use, 1);
+	hinfo->count = 0;
+	hinfo->family = family;
+	hinfo->rnd_initialized = 0;
+	spin_lock_init(&hinfo->lock);
+	hinfo->pde = create_proc_entry(minfo->name, 0,
+				       family == AF_INET ? hashlimit_procdir4 :
+				       			   hashlimit_procdir6);
+	if (!hinfo->pde) {
+		vfree(hinfo);
+		return -1;
+	}
+	hinfo->pde->proc_fops = &dl_file_ops;
+	hinfo->pde->data = hinfo;
+
+	init_timer(&hinfo->timer);
+	hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval);
+	hinfo->timer.data = (unsigned long )hinfo;
+	hinfo->timer.function = htable_gc;
+	add_timer(&hinfo->timer);
+
+	spin_lock_bh(&hashlimit_lock);
+	hlist_add_head(&hinfo->node, &hashlimit_htables);
+	spin_unlock_bh(&hashlimit_lock);
+
+	return 0;
+}
+
+static int select_all(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+{
+	return 1;
+}
+
+static int select_gc(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+{
+	return (jiffies >= he->expires);
+}
+
+static void htable_selective_cleanup(struct xt_hashlimit_htable *ht,
+		 		int (*select)(struct xt_hashlimit_htable *ht,
+					      struct dsthash_ent *he))
+{
+	unsigned int i;
+
+	/* lock hash table and iterate over it */
+	spin_lock_bh(&ht->lock);
+	for (i = 0; i < ht->cfg.size; i++) {
+		struct dsthash_ent *dh;
+		struct hlist_node *pos, *n;
+		hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) {
+			if ((*select)(ht, dh))
+				dsthash_free(ht, dh);
+		}
+	}
+	spin_unlock_bh(&ht->lock);
+}
+
+/* hash table garbage collector, run by timer */
+static void htable_gc(unsigned long htlong)
+{
+	struct xt_hashlimit_htable *ht = (struct xt_hashlimit_htable *)htlong;
+
+	htable_selective_cleanup(ht, select_gc);
+
+	/* re-add the timer accordingly */
+	ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval);
+	add_timer(&ht->timer);
+}
+
+static void htable_destroy(struct xt_hashlimit_htable *hinfo)
+{
+	/* remove timer, if it is pending */
+	if (timer_pending(&hinfo->timer))
+		del_timer(&hinfo->timer);
+
+	/* remove proc entry */
+	remove_proc_entry(hinfo->pde->name,
+			  hinfo->family == AF_INET ? hashlimit_procdir4 :
+			  			     hashlimit_procdir6);
+	htable_selective_cleanup(hinfo, select_all);
+	vfree(hinfo);
+}
+
+static struct xt_hashlimit_htable *htable_find_get(char *name, int family)
+{
+	struct xt_hashlimit_htable *hinfo;
+	struct hlist_node *pos;
+
+	spin_lock_bh(&hashlimit_lock);
+	hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
+		if (!strcmp(name, hinfo->pde->name) &&
+		    hinfo->family == family) {
+			atomic_inc(&hinfo->use);
+			spin_unlock_bh(&hashlimit_lock);
+			return hinfo;
+		}
+	}
+	spin_unlock_bh(&hashlimit_lock);
+	return NULL;
+}
+
+static void htable_put(struct xt_hashlimit_htable *hinfo)
+{
+	if (atomic_dec_and_test(&hinfo->use)) {
+		spin_lock_bh(&hashlimit_lock);
+		hlist_del(&hinfo->node);
+		spin_unlock_bh(&hashlimit_lock);
+		htable_destroy(hinfo);
+	}
+}
+
+/* The algorithm used is the Simple Token Bucket Filter (TBF)
+ * see net/sched/sch_tbf.c in the linux source tree
+ */
+
+/* Rusty: This is my (non-mathematically-inclined) understanding of
+   this algorithm.  The `average rate' in jiffies becomes your initial
+   amount of credit `credit' and the most credit you can ever have
+   `credit_cap'.  The `peak rate' becomes the cost of passing the
+   test, `cost'.
+
+   `prev' tracks the last packet hit: you gain one credit per jiffy.
+   If you get credit balance more than this, the extra credit is
+   discarded.  Every time the match passes, you lose `cost' credits;
+   if you don't have that many, the test fails.
+
+   See Alexey's formal explanation in net/sched/sch_tbf.c.
+
+   To get the maximum range, we multiply by this factor (ie. you get N
+   credits per jiffy).  We want to allow a rate as low as 1 per day
+   (slowest userspace tool allows), which means
+   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
+*/
+#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
+
+/* Repeated shift and or gives us all 1s, final shift and add 1 gives
+ * us the power of 2 below the theoretical max, so GCC simply does a
+ * shift. */
+#define _POW2_BELOW2(x) ((x)|((x)>>1))
+#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
+#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
+#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
+#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
+#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
+
+#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
+
+/* Precision saver. */
+static inline u_int32_t
+user2credits(u_int32_t user)
+{
+	/* If multiplying would overflow... */
+	if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
+		/* Divide first. */
+		return (user / XT_HASHLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
+
+	return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE;
+}
+
+static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
+{
+	dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY;
+	if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
+		dh->rateinfo.credit = dh->rateinfo.credit_cap;
+	dh->rateinfo.prev = now;
+}
+
+static int
+hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst,
+		   const struct sk_buff *skb, unsigned int protoff)
+{
+	__be16 _ports[2], *ports;
+	int nexthdr;
+
+	memset(dst, 0, sizeof(*dst));
+
+	switch (hinfo->family) {
+	case AF_INET:
+		if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
+			dst->addr.ip.dst = skb->nh.iph->daddr;
+		if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP)
+			dst->addr.ip.src = skb->nh.iph->saddr;
+
+		if (!(hinfo->cfg.mode &
+		      (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
+			return 0;
+		nexthdr = skb->nh.iph->protocol;
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
+			memcpy(&dst->addr.ip6.dst, &skb->nh.ipv6h->daddr,
+			       sizeof(dst->addr.ip6.dst));
+		if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP)
+			memcpy(&dst->addr.ip6.src, &skb->nh.ipv6h->saddr,
+			       sizeof(dst->addr.ip6.src));
+
+		if (!(hinfo->cfg.mode &
+		      (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
+			return 0;
+		nexthdr = ipv6_find_hdr(skb, &protoff, -1, NULL);
+		if (nexthdr < 0)
+			return -1;
+		break;
+#endif
+	default:
+		BUG();
+		return 0;
+	}
+
+	switch (nexthdr) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_SCTP:
+	case IPPROTO_DCCP:
+		ports = skb_header_pointer(skb, protoff, sizeof(_ports),
+					   &_ports);
+		break;
+	default:
+		_ports[0] = _ports[1] = 0;
+		ports = _ports;
+		break;
+	}
+	if (!ports)
+		return -1;
+	if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SPT)
+		dst->src_port = ports[0];
+	if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DPT)
+		dst->dst_port = ports[1];
+	return 0;
+}
+
+static int
+hashlimit_match(const struct sk_buff *skb,
+		const struct net_device *in,
+		const struct net_device *out,
+		const struct xt_match *match,
+		const void *matchinfo,
+		int offset,
+		unsigned int protoff,
+		int *hotdrop)
+{
+	struct xt_hashlimit_info *r =
+		((struct xt_hashlimit_info *)matchinfo)->u.master;
+	struct xt_hashlimit_htable *hinfo = r->hinfo;
+	unsigned long now = jiffies;
+	struct dsthash_ent *dh;
+	struct dsthash_dst dst;
+
+	if (hashlimit_init_dst(hinfo, &dst, skb, protoff) < 0)
+		goto hotdrop;
+
+	spin_lock_bh(&hinfo->lock);
+	dh = dsthash_find(hinfo, &dst);
+	if (!dh) {
+		dh = dsthash_alloc_init(hinfo, &dst);
+		if (!dh) {
+			spin_unlock_bh(&hinfo->lock);
+			goto hotdrop;
+		}
+
+		dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
+		dh->rateinfo.prev = jiffies;
+		dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
+						   hinfo->cfg.burst);
+		dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
+						       hinfo->cfg.burst);
+		dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
+	} else {
+		/* update expiration timeout */
+		dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
+		rateinfo_recalc(dh, now);
+	}
+
+	if (dh->rateinfo.credit >= dh->rateinfo.cost) {
+		/* We're underlimit. */
+		dh->rateinfo.credit -= dh->rateinfo.cost;
+		spin_unlock_bh(&hinfo->lock);
+		return 1;
+	}
+
+       	spin_unlock_bh(&hinfo->lock);
+
+	/* default case: we're overlimit, thus don't match */
+	return 0;
+
+hotdrop:
+	*hotdrop = 1;
+	return 0;
+}
+
+static int
+hashlimit_checkentry(const char *tablename,
+		     const void *inf,
+		     const struct xt_match *match,
+		     void *matchinfo,
+		     unsigned int hook_mask)
+{
+	struct xt_hashlimit_info *r = matchinfo;
+
+	/* Check for overflow. */
+	if (r->cfg.burst == 0 ||
+	    user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
+		printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
+		       r->cfg.avg, r->cfg.burst);
+		return 0;
+	}
+	if (r->cfg.mode == 0 ||
+	    r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
+			   XT_HASHLIMIT_HASH_DIP |
+			   XT_HASHLIMIT_HASH_SIP |
+			   XT_HASHLIMIT_HASH_SPT))
+		return 0;
+	if (!r->cfg.gc_interval)
+		return 0;
+	if (!r->cfg.expire)
+		return 0;
+	if (r->name[sizeof(r->name) - 1] != '\0')
+		return 0;
+
+	/* This is the best we've got: We cannot release and re-grab lock,
+	 * since checkentry() is called before x_tables.c grabs xt_mutex.
+	 * We also cannot grab the hashtable spinlock, since htable_create will
+	 * call vmalloc, and that can sleep.  And we cannot just re-search
+	 * the list of htable's in htable_create(), since then we would
+	 * create duplicate proc files. -HW */
+	mutex_lock(&hlimit_mutex);
+	r->hinfo = htable_find_get(r->name, match->family);
+	if (!r->hinfo && htable_create(r, match->family) != 0) {
+		mutex_unlock(&hlimit_mutex);
+		return 0;
+	}
+	mutex_unlock(&hlimit_mutex);
+
+	/* Ugly hack: For SMP, we only want to use one set */
+	r->u.master = r;
+	return 1;
+}
+
+static void
+hashlimit_destroy(const struct xt_match *match, void *matchinfo)
+{
+	struct xt_hashlimit_info *r = matchinfo;
+
+	htable_put(r->hinfo);
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_xt_hashlimit_info {
+	char name[IFNAMSIZ];
+	struct hashlimit_cfg cfg;
+	compat_uptr_t hinfo;
+	compat_uptr_t master;
+};
+
+static void compat_from_user(void *dst, void *src)
+{
+	int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
+
+	memcpy(dst, src, off);
+	memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off);
+}
+
+static int compat_to_user(void __user *dst, void *src)
+{
+	int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
+
+	return copy_to_user(dst, src, off) ? -EFAULT : 0;
+}
+#endif
+
+static struct xt_match xt_hashlimit[] = {
+	{
+		.name		= "hashlimit",
+		.family		= AF_INET,
+		.match		= hashlimit_match,
+		.matchsize	= sizeof(struct xt_hashlimit_info),
+#ifdef CONFIG_COMPAT
+		.compatsize	= sizeof(struct compat_xt_hashlimit_info),
+		.compat_from_user = compat_from_user,
+		.compat_to_user	= compat_to_user,
+#endif
+		.checkentry	= hashlimit_checkentry,
+		.destroy	= hashlimit_destroy,
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "hashlimit",
+		.family		= AF_INET6,
+		.match		= hashlimit_match,
+		.matchsize	= sizeof(struct xt_hashlimit_info),
+#ifdef CONFIG_COMPAT
+		.compatsize	= sizeof(struct compat_xt_hashlimit_info),
+		.compat_from_user = compat_from_user,
+		.compat_to_user	= compat_to_user,
+#endif
+		.checkentry	= hashlimit_checkentry,
+		.destroy	= hashlimit_destroy,
+		.me		= THIS_MODULE
+	},
+};
+
+/* PROC stuff */
+static void *dl_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct proc_dir_entry *pde = s->private;
+	struct xt_hashlimit_htable *htable = pde->data;
+	unsigned int *bucket;
+
+	spin_lock_bh(&htable->lock);
+	if (*pos >= htable->cfg.size)
+		return NULL;
+
+	bucket = kmalloc(sizeof(unsigned int), GFP_ATOMIC);
+	if (!bucket)
+		return ERR_PTR(-ENOMEM);
+
+	*bucket = *pos;
+	return bucket;
+}
+
+static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct proc_dir_entry *pde = s->private;
+	struct xt_hashlimit_htable *htable = pde->data;
+	unsigned int *bucket = (unsigned int *)v;
+
+	*pos = ++(*bucket);
+	if (*pos >= htable->cfg.size) {
+		kfree(v);
+		return NULL;
+	}
+	return bucket;
+}
+
+static void dl_seq_stop(struct seq_file *s, void *v)
+{
+	struct proc_dir_entry *pde = s->private;
+	struct xt_hashlimit_htable *htable = pde->data;
+	unsigned int *bucket = (unsigned int *)v;
+
+	kfree(bucket);
+	spin_unlock_bh(&htable->lock);
+}
+
+static int dl_seq_real_show(struct dsthash_ent *ent, int family,
+				   struct seq_file *s)
+{
+	/* recalculate to show accurate numbers */
+	rateinfo_recalc(ent, jiffies);
+
+	switch (family) {
+	case AF_INET:
+		return seq_printf(s, "%ld %u.%u.%u.%u:%u->"
+				     "%u.%u.%u.%u:%u %u %u %u\n",
+				 (long)(ent->expires - jiffies)/HZ,
+				 NIPQUAD(ent->dst.addr.ip.src),
+				 ntohs(ent->dst.src_port),
+				 NIPQUAD(ent->dst.addr.ip.dst),
+				 ntohs(ent->dst.dst_port),
+				 ent->rateinfo.credit, ent->rateinfo.credit_cap,
+				 ent->rateinfo.cost);
+	case AF_INET6:
+		return seq_printf(s, "%ld " NIP6_FMT ":%u->"
+				     NIP6_FMT ":%u %u %u %u\n",
+				 (long)(ent->expires - jiffies)/HZ,
+				 NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.src),
+				 ntohs(ent->dst.src_port),
+				 NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.dst),
+				 ntohs(ent->dst.dst_port),
+				 ent->rateinfo.credit, ent->rateinfo.credit_cap,
+				 ent->rateinfo.cost);
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static int dl_seq_show(struct seq_file *s, void *v)
+{
+	struct proc_dir_entry *pde = s->private;
+	struct xt_hashlimit_htable *htable = pde->data;
+	unsigned int *bucket = (unsigned int *)v;
+	struct dsthash_ent *ent;
+	struct hlist_node *pos;
+
+	if (!hlist_empty(&htable->hash[*bucket])) {
+		hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node)
+			if (dl_seq_real_show(ent, htable->family, s))
+				return 1;
+	}
+	return 0;
+}
+
+static struct seq_operations dl_seq_ops = {
+	.start = dl_seq_start,
+	.next  = dl_seq_next,
+	.stop  = dl_seq_stop,
+	.show  = dl_seq_show
+};
+
+static int dl_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &dl_seq_ops);
+
+	if (!ret) {
+		struct seq_file *sf = file->private_data;
+		sf->private = PDE(inode);
+	}
+	return ret;
+}
+
+static struct file_operations dl_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = dl_proc_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+
+static int __init xt_hashlimit_init(void)
+{
+	int err;
+
+	err = xt_register_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+	if (err < 0)
+		goto err1;
+
+	err = -ENOMEM;
+	hashlimit_cachep = kmem_cache_create("xt_hashlimit",
+					    sizeof(struct dsthash_ent), 0, 0,
+					    NULL, NULL);
+	if (!hashlimit_cachep) {
+		printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
+		goto err2;
+	}
+	hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", proc_net);
+	if (!hashlimit_procdir4) {
+		printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
+				"entry\n");
+		goto err3;
+	}
+	hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net);
+	if (!hashlimit_procdir6) {
+		printk(KERN_ERR "xt_hashlimit: tnable to create proc dir "
+				"entry\n");
+		goto err4;
+	}
+	return 0;
+err4:
+	remove_proc_entry("ipt_hashlimit", proc_net);
+err3:
+	kmem_cache_destroy(hashlimit_cachep);
+err2:
+	xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+err1:
+	return err;
+
+}
+
+static void __exit xt_hashlimit_fini(void)
+{
+	remove_proc_entry("ipt_hashlimit", proc_net);
+	remove_proc_entry("ip6t_hashlimit", proc_net);
+	kmem_cache_destroy(hashlimit_cachep);
+	xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+}
+
+module_init(xt_hashlimit_init);
+module_exit(xt_hashlimit_fini);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 29/33]: x_tables: add NFLOG target
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (27 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6 Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 30/33]: ebtables: add --snap-arp option Patrick McHardy
                   ` (4 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: x_tables: add NFLOG target

Add new NFLOG target to allow use of nfnetlink_log for both IPv4 and IPv6.
Currently we have two (unsupported by userspace) hacks in the LOG and ULOG
targets to optionally call to the nflog API. They lack a few features,
namely the IPv4 and IPv6 LOG targets can not specify a number of arguments
related to nfnetlink_log, while the ULOG target is only available for IPv4.
Remove those hacks and add a clean way to use nfnetlink_log.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit a212f14ec0dccdfd5c3f77017dfe3c23fa944d2c
tree 5250c5c39ab3a3acbf1369c4c7e43e22f6c4ed2b
parent 5fbcf255408abf92eac14816032a4ecac6a7f8c1
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:12 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:53 +0100

 include/linux/netfilter/Kbuild          |    1 
 include/linux/netfilter/xt_NFLOG.h      |   18 ++++++
 include/linux/netfilter_ipv4/ipt_LOG.h  |    2 -
 include/linux/netfilter_ipv6/ip6t_LOG.h |    2 -
 net/ipv4/netfilter/ipt_LOG.c            |    9 +--
 net/ipv6/netfilter/ip6t_LOG.c           |    9 +--
 net/netfilter/Kconfig                   |   11 ++++
 net/netfilter/Makefile                  |    1 
 net/netfilter/xt_NFLOG.c                |   86 +++++++++++++++++++++++++++++++
 9 files changed, 123 insertions(+), 16 deletions(-)

diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index e379a2d..6328175 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -22,6 +22,7 @@ header-y += xt_mark.h
 header-y += xt_MARK.h
 header-y += xt_multiport.h
 header-y += xt_NFQUEUE.h
+header-y += xt_NFLOG.h
 header-y += xt_pkttype.h
 header-y += xt_policy.h
 header-y += xt_realm.h
diff --git a/include/linux/netfilter/xt_NFLOG.h b/include/linux/netfilter/xt_NFLOG.h
new file mode 100644
index 0000000..cdcd0ed
--- /dev/null
+++ b/include/linux/netfilter/xt_NFLOG.h
@@ -0,0 +1,18 @@
+#ifndef _XT_NFLOG_TARGET
+#define _XT_NFLOG_TARGET
+
+#define XT_NFLOG_DEFAULT_GROUP		0x1
+#define XT_NFLOG_DEFAULT_THRESHOLD	1
+
+#define XT_NFLOG_MASK			0x0
+
+struct xt_nflog_info {
+	u_int32_t	len;
+	u_int16_t	group;
+	u_int16_t	threshold;
+	u_int16_t	flags;
+	u_int16_t	pad;
+	char		prefix[64];
+};
+
+#endif /* _XT_NFLOG_TARGET */
diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h
index 892f9a3..90fa652 100644
--- a/include/linux/netfilter_ipv4/ipt_LOG.h
+++ b/include/linux/netfilter_ipv4/ipt_LOG.h
@@ -6,7 +6,7 @@ #define IPT_LOG_TCPSEQ		0x01	/* Log TCP 
 #define IPT_LOG_TCPOPT		0x02	/* Log TCP options */
 #define IPT_LOG_IPOPT		0x04	/* Log IP options */
 #define IPT_LOG_UID		0x08	/* Log UID owning local socket */
-#define IPT_LOG_NFLOG		0x10	/* Log using nf_log backend */
+#define IPT_LOG_NFLOG		0x10	/* Unsupported, don't reuse */
 #define IPT_LOG_MASK		0x1f
 
 struct ipt_log_info {
diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h
index 060c1a1..0d0119b 100644
--- a/include/linux/netfilter_ipv6/ip6t_LOG.h
+++ b/include/linux/netfilter_ipv6/ip6t_LOG.h
@@ -6,7 +6,7 @@ #define IP6T_LOG_TCPSEQ		0x01	/* Log TCP
 #define IP6T_LOG_TCPOPT		0x02	/* Log TCP options */
 #define IP6T_LOG_IPOPT		0x04	/* Log IP options */
 #define IP6T_LOG_UID		0x08	/* Log UID owning local socket */
-#define IP6T_LOG_NFLOG		0x10	/* Log using nf_log backend */
+#define IP6T_LOG_NFLOG		0x10	/* Unsupported, don't use */
 #define IP6T_LOG_MASK		0x1f
 
 struct ip6t_log_info {
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 46eee64..c96de16 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -430,13 +430,8 @@ ipt_log_target(struct sk_buff **pskb,
 	li.u.log.level = loginfo->level;
 	li.u.log.logflags = loginfo->logflags;
 
-	if (loginfo->logflags & IPT_LOG_NFLOG)
-		nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
-		              "%s", loginfo->prefix);
-	else
-		ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
-		               loginfo->prefix);
-
+	ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
+	               loginfo->prefix);
 	return IPT_CONTINUE;
 }
 
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index f4857cf..33b1faa 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -440,13 +440,8 @@ ip6t_log_target(struct sk_buff **pskb,
 	li.u.log.level = loginfo->level;
 	li.u.log.logflags = loginfo->logflags;
 
-	if (loginfo->logflags & IP6T_LOG_NFLOG)
-		nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
-		              "%s", loginfo->prefix);
-	else
-		ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
-		                loginfo->prefix);
-
+	ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
+	                loginfo->prefix);
 	return IP6T_CONTINUE;
 }
 
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 7e61254..d191dac 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -184,6 +184,17 @@ config NETFILTER_XT_TARGET_NFQUEUE
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_TARGET_NFLOG
+	tristate '"NFLOG" target support'
+	depends on NETFILTER_XTABLES
+	help
+	  This option enables the NFLOG target, which allows to LOG
+	  messages through the netfilter logging API, which can use
+	  either the old LOG target, the old ULOG target or nfnetlink_log
+	  as backend.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_TARGET_NOTRACK
 	tristate  '"NOTRACK" target support'
 	depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index f85811b..7f0089c 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMAR
 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
new file mode 100644
index 0000000..901ed7a
--- /dev/null
+++ b/net/netfilter/xt_NFLOG.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_NFLOG.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("x_tables NFLOG target");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_NFLOG");
+MODULE_ALIAS("ip6t_NFLOG");
+
+static unsigned int
+nflog_target(struct sk_buff **pskb,
+	     const struct net_device *in, const struct net_device *out,
+	     unsigned int hooknum, const struct xt_target *target,
+	     const void *targinfo)
+{
+	const struct xt_nflog_info *info = targinfo;
+	struct nf_loginfo li;
+
+	li.type		     = NF_LOG_TYPE_ULOG;
+	li.u.ulog.copy_len   = info->len;
+	li.u.ulog.group	     = info->group;
+	li.u.ulog.qthreshold = info->threshold;
+
+	nf_log_packet(target->family, hooknum, *pskb, in, out, &li,
+		      "%s", info->prefix);
+	return XT_CONTINUE;
+}
+
+static int
+nflog_checkentry(const char *tablename, const void *entry,
+		 const struct xt_target *target, void *targetinfo,
+		 unsigned int hookmask)
+{
+	struct xt_nflog_info *info = targetinfo;
+
+	if (info->flags & ~XT_NFLOG_MASK)
+		return 0;
+	if (info->prefix[sizeof(info->prefix) - 1] != '\0')
+		return 0;
+	return 1;
+}
+
+static struct xt_target xt_nflog_target[] = {
+	{
+		.name		= "NFLOG",
+		.family		= AF_INET,
+		.checkentry	= nflog_checkentry,
+		.target		= nflog_target,
+		.targetsize	= sizeof(struct xt_nflog_info),
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "NFLOG",
+		.family		= AF_INET6,
+		.checkentry	= nflog_checkentry,
+		.target		= nflog_target,
+		.targetsize	= sizeof(struct xt_nflog_info),
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init xt_nflog_init(void)
+{
+	return xt_register_targets(xt_nflog_target,
+				   ARRAY_SIZE(xt_nflog_target));
+}
+
+static void __exit xt_nflog_fini(void)
+{
+	xt_unregister_targets(xt_nflog_target, ARRAY_SIZE(xt_nflog_target));
+}
+
+module_init(xt_nflog_init);
+module_exit(xt_nflog_fini);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 30/33]: ebtables: add --snap-arp option
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (28 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 29/33]: x_tables: add NFLOG target Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 31/33]: remove remaining ASSERT_{READ,WRITE}_LOCK Patrick McHardy
                   ` (3 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: ebtables: add --snap-arp option

The attached patch adds --snat-arp support, which makes it possible to
change the source mac address in both the mac header and the arp header
with one rule.

Signed-off-by: Bart De Schuymer <bdschuym@pandora.be>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 80edc7ee5b534c039c0f1839af3ce5348417fd54
tree 1cac381ed8d3463fa5a9c83ba3460a3b139e7d47
parent a212f14ec0dccdfd5c3f77017dfe3c23fa944d2c
author Bart De Schuymer <bdschuym@pandora.be> Tue, 28 Nov 2006 23:13:16 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:53 +0100

 include/linux/netfilter_bridge/ebt_nat.h  |    1 +
 include/linux/netfilter_bridge/ebtables.h |    4 ++++
 net/bridge/netfilter/ebt_mark.c           |    6 +++---
 net/bridge/netfilter/ebt_snat.c           |   27 ++++++++++++++++++++++++---
 4 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/include/linux/netfilter_bridge/ebt_nat.h b/include/linux/netfilter_bridge/ebt_nat.h
index 26fd90d..435b886 100644
--- a/include/linux/netfilter_bridge/ebt_nat.h
+++ b/include/linux/netfilter_bridge/ebt_nat.h
@@ -1,6 +1,7 @@
 #ifndef __LINUX_BRIDGE_EBT_NAT_H
 #define __LINUX_BRIDGE_EBT_NAT_H
 
+#define NAT_ARP_BIT  (0x00000010)
 struct ebt_nat_info
 {
 	unsigned char mac[ETH_ALEN];
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
index e6ea70d..8777526 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -26,6 +26,10 @@ #define EBT_DROP     -2
 #define EBT_CONTINUE -3
 #define EBT_RETURN   -4
 #define NUM_STANDARD_TARGETS   4
+/* ebtables target modules store the verdict inside an int. We can
+ * reclaim a part of this int for backwards compatible extensions.
+ * The 4 lsb are more than enough to store the verdict. */
+#define EBT_VERDICT_BITS 0x0000000F
 
 struct ebt_counter
 {
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 2458638..62d23c7 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -33,7 +33,7 @@ static int ebt_target_mark(struct sk_buf
 	else
 		(*pskb)->mark ^= info->mark;
 
-	return info->target | -16;
+	return info->target | ~EBT_VERDICT_BITS;
 }
 
 static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
@@ -44,13 +44,13 @@ static int ebt_target_mark_check(const c
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
 		return -EINVAL;
-	tmp = info->target | -16;
+	tmp = info->target | ~EBT_VERDICT_BITS;
 	if (BASE_CHAIN && tmp == EBT_RETURN)
 		return -EINVAL;
 	CLEAR_BASE_CHAIN_BIT;
 	if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
 		return -EINVAL;
-	tmp = info->target & -16;
+	tmp = info->target & ~EBT_VERDICT_BITS;
 	if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
 	    tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
 		return -EINVAL;
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index cbb33e2..a507221 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -12,6 +12,8 @@ #include <linux/netfilter_bridge/ebtable
 #include <linux/netfilter_bridge/ebt_nat.h>
 #include <linux/module.h>
 #include <net/sock.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
 
 static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
    const struct net_device *in, const struct net_device *out,
@@ -31,24 +33,43 @@ static int ebt_target_snat(struct sk_buf
 		*pskb = nskb;
 	}
 	memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
-	return info->target;
+	if (!(info->target & NAT_ARP_BIT) &&
+	    eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
+		struct arphdr _ah, *ap;
+
+		ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
+		if (ap == NULL)
+			return EBT_DROP;
+		if (ap->ar_hln != ETH_ALEN)
+			goto out;
+		if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
+			return EBT_DROP;
+	}
+out:
+	return info->target | ~EBT_VERDICT_BITS;
 }
 
 static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
    const struct ebt_entry *e, void *data, unsigned int datalen)
 {
 	struct ebt_nat_info *info = (struct ebt_nat_info *) data;
+	int tmp;
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
 		return -EINVAL;
-	if (BASE_CHAIN && info->target == EBT_RETURN)
+	tmp = info->target | ~EBT_VERDICT_BITS;
+	if (BASE_CHAIN && tmp == EBT_RETURN)
 		return -EINVAL;
 	CLEAR_BASE_CHAIN_BIT;
 	if (strcmp(tablename, "nat"))
 		return -EINVAL;
 	if (hookmask & ~(1 << NF_BR_POST_ROUTING))
 		return -EINVAL;
-	if (INVALID_TARGET)
+
+	if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
+		return -EINVAL;
+	tmp = info->target | EBT_VERDICT_BITS;
+	if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
 		return -EINVAL;
 	return 0;
 }

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 31/33]: remove remaining ASSERT_{READ,WRITE}_LOCK
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (29 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 30/33]: ebtables: add --snap-arp option Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 32/33]: Fix PROC_FS=n warnings Patrick McHardy
                   ` (2 subsequent siblings)
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: remove remaining ASSERT_{READ,WRITE}_LOCK

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit dd917f544f23dd2581635ef3791a51dd7528bbcb
tree b0ae50fd9becd9029845961e1d23d2d3c216ab4e
parent 80edc7ee5b534c039c0f1839af3ce5348417fd54
author Patrick McHardy <kaber@trash.net> Tue, 28 Nov 2006 23:13:06 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:54 +0100

 net/ipv4/netfilter/ip_conntrack_core.c       |    6 ------
 net/ipv4/netfilter/ip_conntrack_proto_gre.c  |    2 --
 net/ipv4/netfilter/ip_conntrack_standalone.c |    4 ----
 net/ipv4/netfilter/ipt_CLUSTERIP.c           |    3 ---
 net/netfilter/nf_conntrack_helper.c          |    3 ---
 5 files changed, 0 insertions(+), 18 deletions(-)

diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 4d1f954..f4b0e68 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -40,9 +40,6 @@ #include <linux/notifier.h>
 
 /* ip_conntrack_lock protects the main hash table, protocol/helper/expected
    registrations, conntrack timers*/
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
@@ -201,7 +198,6 @@ ip_ct_invert_tuple(struct ip_conntrack_t
 /* ip_conntrack_expect helper functions */
 void ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
 {
-	ASSERT_WRITE_LOCK(&ip_conntrack_lock);
 	IP_NF_ASSERT(!timer_pending(&exp->timeout));
 	list_del(&exp->list);
 	CONNTRACK_STAT_INC(expect_delete);
@@ -294,7 +290,6 @@ static void
 clean_from_lists(struct ip_conntrack *ct)
 {
 	DEBUGP("clean_from_lists(%p)\n", ct);
-	ASSERT_WRITE_LOCK(&ip_conntrack_lock);
 	list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
 	list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
 
@@ -373,7 +368,6 @@ __ip_conntrack_find(const struct ip_conn
 	struct ip_conntrack_tuple_hash *h;
 	unsigned int hash = hash_conntrack(tuple);
 
-	ASSERT_READ_LOCK(&ip_conntrack_lock);
 	list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
 		if (tuplehash_to_ctrack(h) != ignored_conntrack &&
 		    ip_ct_tuple_equal(tuple, &h->tuple)) {
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
index 5fe026f..ac1c49e 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -34,8 +34,6 @@ #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 
 static DEFINE_RWLOCK(ip_ct_gre_lock);
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
 
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 2df6753..86efb54 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -28,9 +28,6 @@ #include <net/checksum.h>
 #include <net/ip.h>
 #include <net/route.h>
 
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -139,7 +136,6 @@ static int ct_seq_show(struct seq_file *
 	const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
 	struct ip_conntrack_protocol *proto;
 
-	ASSERT_READ_LOCK(&ip_conntrack_lock);
 	IP_NF_ASSERT(conntrack);
 
 	/* we only want to print DIR_ORIGINAL */
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 7a29d6e..5d43a63 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -40,8 +40,6 @@ #else
 #define DEBUGP
 #endif
 
-#define ASSERT_READ_LOCK(x)
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -123,7 +121,6 @@ __clusterip_config_find(__be32 clusterip
 {
 	struct list_head *pos;
 
-	ASSERT_READ_LOCK(&clusterip_lock);
 	list_for_each(pos, &clusterip_configs) {
 		struct clusterip_config *c = list_entry(pos, 
 					struct clusterip_config, list);
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 5cbe55f..03b3ed8 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -21,9 +21,6 @@ #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 32/33]: Fix PROC_FS=n warnings
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (30 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 31/33]: remove remaining ASSERT_{READ,WRITE}_LOCK Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  2:09 ` [NETFILTER 33/33]: remove the reference to ipchains from Kconfig Patrick McHardy
  2006-11-29  4:09 ` [NETFILTER 00/33]: Netfilter Update David Miller
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: Fix PROC_FS=n warnings

Fix some unused function/variable warnings.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 8c6e0e883d2aa1ae8d07fb774cf8760f7f127ab8
tree e0374ef9545a5a681344d1e03c6bd4842d35dd13
parent dd917f544f23dd2581635ef3791a51dd7528bbcb
author Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:54 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:54 +0100

 net/ipv4/netfilter/ipt_CLUSTERIP.c |   22 +++++++++++++++-------
 net/ipv6/netfilter/ip6_queue.c     |    2 ++
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 5d43a63..0983650 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -167,7 +167,6 @@ clusterip_config_init(struct ipt_cluster
 			struct net_device *dev)
 {
 	struct clusterip_config *c;
-	char buffer[16];
 
 	c = kzalloc(sizeof(*c), GFP_ATOMIC);
 	if (!c)
@@ -184,12 +183,17 @@ clusterip_config_init(struct ipt_cluster
 	atomic_set(&c->entries, 1);
 
 #ifdef CONFIG_PROC_FS
-	/* create proc dir entry */
-	sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
-	c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, clusterip_procdir);
-	if (!c->pde) {
-		kfree(c);
-		return NULL;
+	{
+		char buffer[16];
+
+		/* create proc dir entry */
+		sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+		c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR,
+					   clusterip_procdir);
+		if (!c->pde) {
+			kfree(c);
+			return NULL;
+		}
 	}
 	c->pde->proc_fops = &clusterip_proc_fops;
 	c->pde->data = c;
@@ -202,6 +206,7 @@ #endif
 	return c;
 }
 
+#ifdef CONFIG_PROC_FS
 static int
 clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
 {
@@ -229,6 +234,7 @@ clusterip_del_node(struct clusterip_conf
 
 	return 1;
 }
+#endif
 
 static inline u_int32_t
 clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
@@ -734,8 +740,10 @@ #endif /* CONFIG_PROC_FS */
 		CLUSTERIP_VERSION);
 	return 0;
 
+#ifdef CONFIG_PROC_FS
 cleanup_hook:
 	nf_unregister_hook(&cip_arp_ops);
+#endif /* CONFIG_PROC_FS */
 cleanup_target:
 	ipt_unregister_target(&clusterip_tgt);
 	return ret;
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 21908c9..d4d9f18 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -620,6 +620,7 @@ static ctl_table ipq_root_table[] = {
 	{ .ctl_name = 0 }
 };
 
+#ifdef CONFIG_PROC_FS
 static int
 ipq_get_info(char *buffer, char **start, off_t offset, int length)
 {
@@ -653,6 +654,7 @@ ipq_get_info(char *buffer, char **start,
 		len = 0;
 	return len;
 }
+#endif /* CONFIG_PROC_FS */
 
 static struct nf_queue_handler nfqh = {
 	.name	= "ip6_queue",

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [NETFILTER 33/33]: remove the reference to ipchains from Kconfig
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (31 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 32/33]: Fix PROC_FS=n warnings Patrick McHardy
@ 2006-11-29  2:09 ` Patrick McHardy
  2006-11-29  4:09 ` [NETFILTER 00/33]: Netfilter Update David Miller
  33 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-11-29  2:09 UTC (permalink / raw)
  To: davem; +Cc: netfilter-devel, Patrick McHardy

[NETFILTER]: remove the reference to ipchains from Kconfig

It is time to move on :-)

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 0fefe1556475985067ea1280789bc8f7d6584938
tree f8bec5743ec9a6820f9fa5153940b74eebd54f42
parent 8c6e0e883d2aa1ae8d07fb774cf8760f7f127ab8
author Pablo Neira Ayuso <pablo@netfilter.org> Wed, 29 Nov 2006 02:32:54 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 29 Nov 2006 02:32:54 +0100

 net/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/Kconfig b/net/Kconfig
index 867f950..7dfc949 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -75,7 +75,7 @@ config NETWORK_SECMARK
 	  If you are unsure how to answer this question, answer N.
 
 menuconfig NETFILTER
-	bool "Network packet filtering (replaces ipchains)"
+	bool "Network packet filtering framework (Netfilter)"
 	---help---
 	  Netfilter is a framework for filtering and mangling network packets
 	  that pass through your Linux box.

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [NETFILTER 00/33]: Netfilter Update
  2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
                   ` (32 preceding siblings ...)
  2006-11-29  2:09 ` [NETFILTER 33/33]: remove the reference to ipchains from Kconfig Patrick McHardy
@ 2006-11-29  4:09 ` David Miller
  33 siblings, 0 replies; 38+ messages in thread
From: David Miller @ 2006-11-29  4:09 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

From: Patrick McHardy <kaber@trash.net>
Date: Wed, 29 Nov 2006 03:08:43 +0100 (MET)

> following is a large netfilter update for 2.6.20. It contains some
> cleanup of the nf_conntrack code and nf_conntrack sysctl/proc
> compatibility with ip_conntrack, which both move a lot of code
> around. Besides that there are some small enhancements for
> nfnetlink_queue, nfnetlink_log and ctnetlink, a port of the hashlimit
> match to xtables, a new NFLOG target for using the address family
> independant nfnetlink_log mechanism, a set of patches to clean up
> the SIP helper and fix multiple issues with the NAT helper, and a
> few assorted fixes.
> 
> These patches contain all NAT unrelated parts from my nf_nat tree,
> which is now down to about 10 patches adding NAT support and
> ports of all helpers. I hope to get them ready for submission within
> a week.
> 
> Please apply, thanks.
> 
> PS: You can (hopefully) also pull these changes from
> http://people.netfilter.org/~kaber/nf-2.6.20.git

Looks good, and the pull worked fine for me, thanks.
Pushed out to the net-2.6.20 tree.

Thanks again.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6
  2006-11-29  2:09 ` [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6 Patrick McHardy
@ 2006-12-03  4:01   ` Yasuyuki KOZAKAI
       [not found]   ` <200612030401.kB341wWd013916@toshiba.co.jp>
       [not found]   ` <200612030401.kB341wVQ010254@toshiba.co.jp>
  2 siblings, 0 replies; 38+ messages in thread
From: Yasuyuki KOZAKAI @ 2006-12-03  4:01 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel, davem


Hi, Patrick,

From: Patrick McHardy <kaber@trash.net>
Date: Wed, 29 Nov 2006 03:09:27 +0100 (MET)

> [NETFILTER]: x_tables: add port of hashlimit match for IPv4 and IPv6

ipv6_find_hdr() is in ip6_tables.c, then why about CONFIG_IP6_NF_IPTABLES ?

>From 2e05f9f301105d1b34bfda4b5826fb676b1e2c06 Mon Sep 17 00:00:00 2001
From: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Date: Sun, 3 Dec 2006 04:23:39 +0900
Subject: [NETFILTER]: xtables: fixes warning on compilation of hashlimit

To use ipv6_find_hdr(), IP6_NF_IPTABLES is necessary.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
---
 net/netfilter/xt_hashlimit.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 46de566..604d7fe 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -388,7 +388,7 @@ hashlimit_init_dst(struct xt_hashlimit_h
 			return 0;
 		nexthdr = skb->nh.iph->protocol;
 		break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
 	case AF_INET6:
 		if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
 			memcpy(&dst->addr.ip6.dst, &skb->nh.ipv6h->daddr,
-- 
1.4.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6
       [not found]   ` <200612030401.kB341wWd013916@toshiba.co.jp>
@ 2006-12-03  6:19     ` David Miller
  0 siblings, 0 replies; 38+ messages in thread
From: David Miller @ 2006-12-03  6:19 UTC (permalink / raw)
  To: yasuyuki.kozakai; +Cc: netfilter-devel, kaber

From: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
Date: Sun, 03 Dec 2006 13:01:56 +0900 (JST)

> Subject: [NETFILTER]: xtables: fixes warning on compilation of hashlimit
> 
> To use ipv6_find_hdr(), IP6_NF_IPTABLES is necessary.
> 
> Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>

I've applied this patch as well.

Thanks everyone.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6
       [not found]   ` <200612030401.kB341wVQ010254@toshiba.co.jp>
@ 2006-12-03 15:44     ` Patrick McHardy
  0 siblings, 0 replies; 38+ messages in thread
From: Patrick McHardy @ 2006-12-03 15:44 UTC (permalink / raw)
  To: Yasuyuki KOZAKAI; +Cc: netfilter-devel, davem

Yasuyuki KOZAKAI wrote:
> Hi, Patrick,
> 
> From: Patrick McHardy <kaber@trash.net>
> Date: Wed, 29 Nov 2006 03:09:27 +0100 (MET)
> 
> 
>>[NETFILTER]: x_tables: add port of hashlimit match for IPv4 and IPv6
> 
> 
> ipv6_find_hdr() is in ip6_tables.c, then why about CONFIG_IP6_NF_IPTABLES ?

Thanks for catching this, I tried compiling without IPv6 and it
broke, but apparently I didn't really think when fixing it :)

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2006-12-03 15:44 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-29  2:08 [NETFILTER 00/33]: Netfilter Update Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 01/33]: nf_conntrack: split out expectation handling Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 02/33]: nf_conntrack: split out helper handling Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 03/33]: nf_conntrack: split out the event cache Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 04/33]: nf_conntrack: split out protocol handling Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 05/33]: More __read_mostly annotations Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 06/33]: nf_conntrack: rename struct nf_conntrack_protocol Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 07/33]: nf_conntrack: more sanity checks in protocol registration/unregistration Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 08/33]: nf_conntrack: remove ASSERT_{READ,WRITE}_LOCK Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 09/33]: nf_conntrack: minor __nf_ct_refresh_acct() whitespace cleanup Patrick McHardy
2006-11-29  2:08 ` [NETFILTER 10/33]: nf_conntrack: remove unused struct list_head from protocols Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 11/33]: nf_conntrack: reduce timer updates in __nf_ct_refresh_acct() Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 12/33]: nf_conntrack_ftp: fix missing helper mask initilization Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 13/33]: nf_conntrack: move extern declaration to header files Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 14/33]: nf_conntrack: automatic sysctl registation for conntrack protocols Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 15/33]: nf_conntrack: move conntrack protocol sysctls to individual modules Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 16/33]: nf_conntrack: sysctl compatibility with old connection tracking Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 17/33]: nf_conntrack: /proc " Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 18/33]: conntrack: add '_get' to {ip, nf}_conntrack_expect_find Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 19/33]: ip_conntrack: fix NAT helper unload races Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 20/33]: sip conntrack: minor cleanup Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 21/33]: sip conntrack: do case insensitive SIP header search Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 22/33]: sip conntrack: make header shortcuts optional Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 23/33]: sip conntrack: better NAT handling Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 24/33]: ctnetlink: check for status attribute existence on conntrack creation Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 25/33]: ctnetlink: rework conntrack fields dumping logic on events Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 26/33]: nfnetlink_queue: allow changing queue length through netlink Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 27/33]: nfnetlink_log: remove useless prefix length limitation Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 28/33]: x_tables: add port of hashlimit match for IPv4 and IPv6 Patrick McHardy
2006-12-03  4:01   ` Yasuyuki KOZAKAI
     [not found]   ` <200612030401.kB341wWd013916@toshiba.co.jp>
2006-12-03  6:19     ` David Miller
     [not found]   ` <200612030401.kB341wVQ010254@toshiba.co.jp>
2006-12-03 15:44     ` Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 29/33]: x_tables: add NFLOG target Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 30/33]: ebtables: add --snap-arp option Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 31/33]: remove remaining ASSERT_{READ,WRITE}_LOCK Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 32/33]: Fix PROC_FS=n warnings Patrick McHardy
2006-11-29  2:09 ` [NETFILTER 33/33]: remove the reference to ipchains from Kconfig Patrick McHardy
2006-11-29  4:09 ` [NETFILTER 00/33]: Netfilter Update David Miller

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.