Skip to contentSkip to conversation

: SIP helper update

PATCH In review Patrick McHardy 3 participants 38 messages Mar 25, 2008 – Mar 26, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover : SIP helper update

Hi Dave,

these patches for 2.6.26 contain a large update for the SIP connection tracking helper, fixing a number of issues with the current helper and improving robustness. A rough overview of the patches follows, the details are in the individual changelog entries:

- Fix NAT mapping setup order to make the NAT core properly detect clashes with existing connections

- Properly adjust the data pointer and length after packet mangling

- Parser enhancements: follow specification more closely (case sensitivity, header encoding, whitespace rules, ...)

- Optionally create signalling expectations for incoming calls from other endpoints than the registrar

- Support for RTCP expectations and multiple media channels

- Optionally create wildcard RTP/RTCP expectations for incoming media from other peers than the registrar

- "Expectation classes" for isolating signalling, audio and video expectations from each other

- Replacement of text-based header translation in NAT helper by binary address translation, support for updating rport=, received= and mport= Via-parameters

- RTP routing optimization for making RTP streams between two "internal" endpoints flow directly between the two endpoints in case the (external) registrar tries to make direct RTP setup

The patches are also available in a git-tree for your convencience at:

git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.26-sip.git

Please apply or pull, thanks.

 include/linux/netfilter.h                   |    9 +
 include/linux/netfilter/nf_conntrack_sip.h  |  185 +++-
 include/net/netfilter/nf_conntrack.h        |    7 +-
 include/net/netfilter/nf_conntrack_expect.h |   22 +-
 include/net/netfilter/nf_conntrack_helper.h |    5 +-
 include/net/netfilter/nf_conntrack_tuple.h  |   53 +-
 net/ipv4/netfilter/ipt_CLUSTERIP.c          |    2 +-
 net/ipv4/netfilter/nf_nat_sip.c             |  556 +++++++----
 net/ipv4/netfilter/nf_nat_snmp_basic.c      |   12 +-
 net/netfilter/nf_conntrack_amanda.c         |   14 +-
 net/netfilter/nf_conntrack_expect.c         |   81 ++-
 net/netfilter/nf_conntrack_ftp.c            |   10 +-
 net/netfilter/nf_conntrack_h323_main.c      |   66 +-
 net/netfilter/nf_conntrack_helper.c         |    3 +-
 net/netfilter/nf_conntrack_irc.c            |   10 +-
 net/netfilter/nf_conntrack_netbios_ns.c     |    9 +-
 net/netfilter/nf_conntrack_pptp.c           |   14 +-
 net/netfilter/nf_conntrack_sane.c           |   11 +-
 net/netfilter/nf_conntrack_sip.c            | 1386 +++++++++++++++++++++------
 net/netfilter/nf_conntrack_tftp.c           |   11 +-
 20 files changed, 1877 insertions(+), 589 deletions(-)

Patrick McHardy (32):
[NETFILTER]: ipt_CLUSTERIP: fix non-existant macro-name
[NETFILTER]: nf_conntrack: fix NF_CT_TUPLE_DUMP for IPv4
[NETFILTER]: nf_conntrack_expect: constify nf_ct_expect_init arguments [NETFILTER]: nf_conntrack_expect: show NF_CT_EXPECT_PERMANENT flag in /proc [NETFILTER]: nf_conntrack_expect: support inactive expectations [NETFILTER]: nf_conntrack: introduce expectation classes and policies [NETFILTER]: Add nf_inet_addr_cmp()
[NETFILTER]: nf_nat_sip: fix NAT setup order
[NETFILTER]: nf_conntrack_sip: fix some off-by-ones
[NETFILTER]: nf_conntrack_sip: adjust dptr and datalen after packet mangling [NETFILTER]: nf_conntrack_sip: remove redundant function arguments [NETFILTER]: nf_conntrack_sip: use strlen/strcmp
[NETFILTER]: nf_conntrack_sip: add seperate SDP header parsing function [NETFILTER]: nf_conntrack_sip: kill request URI "header" definitions [NETFILTER]: nf_conntrack_sip: parse SIP headers properly [NETFILTER]: nf_conntrack_sip: introduce SIP-URI parsing helper [NETFILTER]: nf_nat_sip: get rid of text based header translation [NETFILTER]: nf_conntrack_sip: move SDP parsing to seperate function [NETFILTER]: nf_conntrack_sip: support method specific request/response handling [NETFILTER]: nf_conntrack_sip: perform NAT after parsing
[NETFILTER]: nf_conntrack_sip: process ACK and PRACK methods [NETFILTER]: nf_conntrack_sip: flush expectations on call termination [NETFILTER]: nf_conntrack_sip: introduce URI and header parameter parsing helpers [NETFILTER]: nf_nat_sip: translate all Via headers
[NETFILTER]: nf_nat_sip: translate all Contact headers
[NETFILTER]: nf_conntrack_sip: create signalling expectations [NETFILTER]: nf_conntrack_sip: allow media expectations with wildcard source address [NETFILTER]: nf_conntrack_sip: create RTCP expectations
[NETFILTER]: nf_nat_sip: split up SDP mangling
[NETFILTER]: nf_conntrack_sip: support multiple media channels [NETFILTER]: nf_conntrack_sip: RTP routing optimization
[NETFILTER]: nf_conntrack_sip: update copyright

#1 lore raw

PATCH 1/32 : ipt_CLUSTERIP: fix non-existant macro-name

[NETFILTER]: ipt_CLUSTERIP: fix non-existant macro-name

With nf_conntrack DUMP_TUPLE got renamed to NF_CT_DUMP_TUPLE, fix CLUSTERIP to use the proper macro name.

---
commit 9f6e380c98a01aa41754fa04ae5b11a11987a69a
tree 42c74ac2a2fe17df5cc61c734bb0462804d35c8c
parent 7cbca67c073263c179f605bdbbdc565ab29d801d
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:35 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:35 +0100

 net/ipv4/netfilter/ipt_CLUSTERIP.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
net/ipv4/netfilter/ipt_CLUSTERIP.c +1 -1
index c6cf84c..1b10f36 100644
@@ -332,7 +332,7 @@ clusterip_tg(struct sk_buff *skb, const struct net_device *in,
 	}
 
 #ifdef DEBUG
-	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+	NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 #endif
 	pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
 	if (!clusterip_responsible(cipinfo->config, hash)) {
#2 lore raw

PATCH 2/32 : nf_conntrack: fix NF_CT_TUPLE_DUMP for IPv4

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack: fix NF_CT_TUPLE_DUMP for IPv4

NF_CT_TUPLE_DUMP prints IPv4 addresses as IPv6, fix this and use printk (guarded by #ifdef DEBUG) directly instead of pr_debug since the tuple is usually printed at the end of line and we don't want to include a log-level.

---
commit 80c9efadd8bc6e868922106b37742c8ab70ea804
tree 8300964a0ff77ca48ae85bec539a2231c7a89a31
parent 9f6e380c98a01aa41754fa04ae5b11a11987a69a
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:36 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:36 +0100

 include/net/netfilter/nf_conntrack_tuple.h |   38 ++++++++++++++++++++++++----
 1 files changed, 33 insertions(+), 5 deletions(-)
include/net/netfilter/nf_conntrack_tuple.h +33 -5
index e69ab2e..d9b53dd 100644
@@ -113,11 +113,39 @@ struct nf_conntrack_tuple_mask
 
 #ifdef __KERNEL__
 
-#define NF_CT_DUMP_TUPLE(tp)						     \
-pr_debug("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",	     \
-	 (tp), (tp)->src.l3num, (tp)->dst.protonum,			     \
-	 NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
-	 NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
+static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
+{
+#ifdef DEBUG
+	printk("tuple %p: %u " NIPQUAD_FMT ":%hu -> " NIPQUAD_FMT ":%hu\n",
+	       t, t->dst.protonum,
+	       NIPQUAD(t->src.u3.ip), ntohs(t->src.u.all),
+	       NIPQUAD(t->dst.u3.ip), ntohs(t->dst.u.all));
+#endif
+}
+
+static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
+{
+#ifdef DEBUG
+	printk("tuple %p: %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",
+	       t, t->dst.protonum,
+	       NIP6(*(struct in6_addr *)t->src.u3.all), ntohs(t->src.u.all),
+	       NIP6(*(struct in6_addr *)t->dst.u3.all), ntohs(t->dst.u.all));
+#endif
+}
+
+static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
+{
+	switch (t->src.l3num) {
+	case AF_INET:
+		nf_ct_dump_tuple_ip(t);
+		break;
+	case AF_INET6:
+		nf_ct_dump_tuple_ipv6(t);
+		break;
+	}
+}
+
+#define NF_CT_DUMP_TUPLE(tp)	nf_ct_dump_tuple(tp)
 
 /* If we're the first tuple, it's the original dir. */
 #define NF_CT_DIRECTION(h)						\
#3 lore raw

Re: [NETFILTER 02/32]: nf_conntrack: fix NF_CT_TUPLE_DUMP for IPv4

Quoted 4 lines · Patrick McHardy
include/net/netfilter/nf_conntrack_tuple.h +4 -0
+
+static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
+{
+	switch (t->src.l3num) {

include/net/netfilter/nf_conntrack_tuple.h struct nf_conntrack_tuple_mask · line 148

Quoted 10 lines
include/net/netfilter/nf_conntrack_tuple.h +10 -0
+	case AF_INET:
+		nf_ct_dump_tuple_ip(t);
+		break;
+	case AF_INET6:
+		nf_ct_dump_tuple_ipv6(t);
+		break;
+	}
+}
+
+#define NF_CT_DUMP_TUPLE(tp)	nf_ct_dump_tuple(tp)

I think it would be wiser just to remove this macro and convert all kernel users to lowercase -- there are only kernel users I guess, since include/net/ is not exported to userspace AFAICS.

#4 lore raw

Re: [NETFILTER 02/32]: nf_conntrack: fix NF_CT_TUPLE_DUMP for IPv4

Quoted 13 lines · Jan Engelhardt
Quoted 11 lines · Patrick McHardy
include/net/netfilter/nf_conntrack_tuple.h +11 -0
+
+static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
+{
+    switch (t->src.l3num) {
+    case AF_INET:
+        nf_ct_dump_tuple_ip(t);
+        break;
+    case AF_INET6:
+        nf_ct_dump_tuple_ipv6(t);
+        break;
+    }
Quoted 9 lines

include/net/netfilter/nf_conntrack_tuple.h struct nf_conntrack_tuple_mask · line 148

Quoted 3 lines
include/net/netfilter/nf_conntrack_tuple.h +3 -0
+}
+
+#define NF_CT_DUMP_TUPLE(tp)    nf_ct_dump_tuple(tp)

I think it would be wiser just to remove this macro and convert all kernel users to lowercase -- there are only kernel users I guess, since include/net/ is not exported to userspace AFAICS.

Sure, please go ahead :)

#5 lore raw

PATCH 3/32 : nf_conntrack_expect: constify nf_ct_expect_init arguments

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_expect: constify nf_ct_expect_init arguments

---
commit ee8406f54b255b347c08802fb39c13c2865234dc
tree 1de164bc0d51b676aad5b317050664b9b4b504f6
parent 80c9efadd8bc6e868922106b37742c8ab70ea804
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:38 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:38 +0100

 include/net/netfilter/nf_conntrack_expect.h |    6 +++---
 net/netfilter/nf_conntrack_expect.c         |    6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)
include/net/netfilter/nf_conntrack_expect.h +3 -3
index cb608a1..f1bdcb4 100644
@@ -75,9 +75,9 @@ void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
    nf_ct_expect_related.  You will have to call put afterwards. */
 struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
 void nf_ct_expect_init(struct nf_conntrack_expect *, int,
-		       union nf_inet_addr *,
-		       union nf_inet_addr *,
-		       u_int8_t, __be16 *, __be16 *);
+		       const union nf_inet_addr *,
+		       const union nf_inet_addr *,
+		       u_int8_t, const __be16 *, const __be16 *);
 void nf_ct_expect_put(struct nf_conntrack_expect *exp);
 int nf_ct_expect_related(struct nf_conntrack_expect *expect);
 
net/netfilter/nf_conntrack_expect.c +3 -3
index 684ec9c..740d94d 100644
@@ -229,9 +229,9 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
 EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
 
 void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
-		       union nf_inet_addr *saddr,
-		       union nf_inet_addr *daddr,
-		       u_int8_t proto, __be16 *src, __be16 *dst)
+		       const union nf_inet_addr *saddr,
+		       const union nf_inet_addr *daddr,
+		       u_int8_t proto, const __be16 *src, const __be16 *dst)
 {
 	int len;
 
#6 lore raw

PATCH 4/32 : nf_conntrack_expect: show NF_CT_EXPECT_PERMANENT flag in /proc

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_expect: show NF_CT_EXPECT_PERMANENT flag in /proc

---
commit c17414dd75203d003a75a024de4ad736a64bc3e5
tree 061681c3626d0d535020efecbb578080883820a9
parent ee8406f54b255b347c08802fb39c13c2865234dc
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:39 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:39 +0100

 net/netfilter/nf_conntrack_expect.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
net/netfilter/nf_conntrack_expect.c +4 -0
index 740d94d..4c05a58 100644
@@ -475,6 +475,10 @@ static int exp_seq_show(struct seq_file *s, void *v)
 		    __nf_ct_l3proto_find(expect->tuple.src.l3num),
 		    __nf_ct_l4proto_find(expect->tuple.src.l3num,
 				       expect->tuple.dst.protonum));
+
+	if (expect->flags & NF_CT_EXPECT_PERMANENT)
+		seq_printf(s, "PERMANENT ");
+
 	return seq_putc(s, '\n');
 }
 
#7 lore raw

PATCH 5/32 : nf_conntrack_expect: support inactive expectations

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_expect: support inactive expectations

This is useful for the SIP helper and signalling expectations. We don't want to create a full-blown expectation with a wildcard as source based on a single UDP packet, but need to know the final port anyways. With inactive expectations we can register the expectation and reserve the tuple, but wait for confirmation from the registrar before activating it.

---
commit da5c5564d2082bff6fe8e9cc5e4df3ffdac1887d
tree 72922ee7ea0a6913c61d7f5f555be77e727cfb7c
parent c17414dd75203d003a75a024de4ad736a64bc3e5
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:41 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:41 +0100

 include/net/netfilter/nf_conntrack_expect.h |    3 ++-
 net/netfilter/nf_conntrack_expect.c         |   25 +++++++++++++++++++++----
 2 files changed, 23 insertions(+), 5 deletions(-)
include/net/netfilter/nf_conntrack_expect.h +2 -1
index f1bdcb4..47c28dd 100644
@@ -53,7 +53,8 @@ struct nf_conntrack_expect
 	struct rcu_head rcu;
 };
 
-#define NF_CT_EXPECT_PERMANENT 0x1
+#define NF_CT_EXPECT_PERMANENT	0x1
+#define NF_CT_EXPECT_INACTIVE	0x2
 
 int nf_conntrack_expect_init(void);
 void nf_conntrack_expect_fini(void);
net/netfilter/nf_conntrack_expect.c +21 -4
index 4c05a58..882602f 100644
@@ -126,9 +126,21 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
 struct nf_conntrack_expect *
 nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
 {
-	struct nf_conntrack_expect *exp;
+	struct nf_conntrack_expect *i, *exp = NULL;
+	struct hlist_node *n;
+	unsigned int h;
+
+	if (!nf_ct_expect_count)
+		return NULL;
 
-	exp = __nf_ct_expect_find(tuple);
+	h = nf_ct_expect_dst_hash(tuple);
+	hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
+		if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
+		    nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
+			exp = i;
+			break;
+		}
+	}
 	if (!exp)
 		return NULL;
 
@@ -460,6 +472,7 @@ static int exp_seq_show(struct seq_file *s, void *v)
 {
 	struct nf_conntrack_expect *expect;
 	struct hlist_node *n = v;
+	char *delim = "";
 
 	expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
 
@@ -476,8 +489,12 @@ static int exp_seq_show(struct seq_file *s, void *v)
 		    __nf_ct_l4proto_find(expect->tuple.src.l3num,
 				       expect->tuple.dst.protonum));
 
-	if (expect->flags & NF_CT_EXPECT_PERMANENT)
-		seq_printf(s, "PERMANENT ");
+	if (expect->flags & NF_CT_EXPECT_PERMANENT) {
+		seq_printf(s, "PERMANENT");
+		delim = ",";
+	}
+	if (expect->flags & NF_CT_EXPECT_INACTIVE)
+		seq_printf(s, "%sINACTIVE", delim);
 
 	return seq_putc(s, '\n');
 }
#8 lore raw

PATCH 6/32 : nf_conntrack: introduce expectation classes and policies

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack: introduce expectation classes and policies

Introduce expectation classes and policies. An expectation class is used to distinguish different types of expectations by the same helper (for example audio/video/t.120). The expectation policy is used to hold the maximum number of expectations and the initial timeout for each class.

The individual classes are isolated from each other, which means that for example an audio expectation will only evict other audio expectations.

---
commit 48bb8ab5591cab986a2850facf33998357db3b10
tree 11145198c9ca2ef44dbb2898a2cd9e18a56b17c2
parent da5c5564d2082bff6fe8e9cc5e4df3ffdac1887d
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:43 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:43 +0100

 include/net/netfilter/nf_conntrack.h        |    5 ++
 include/net/netfilter/nf_conntrack_expect.h |   13 +++++
 include/net/netfilter/nf_conntrack_helper.h |    5 +-
 net/ipv4/netfilter/nf_nat_snmp_basic.c      |   12 +++--
 net/netfilter/nf_conntrack_amanda.c         |   14 ++++--
 net/netfilter/nf_conntrack_expect.c         |   50 ++++++++++++++------
 net/netfilter/nf_conntrack_ftp.c            |   10 +++-
 net/netfilter/nf_conntrack_h323_main.c      |   66 +++++++++++++++++----------
 net/netfilter/nf_conntrack_helper.c         |    3 +
 net/netfilter/nf_conntrack_irc.c            |   10 +++-
 net/netfilter/nf_conntrack_netbios_ns.c     |    9 +++-
 net/netfilter/nf_conntrack_pptp.c           |   14 ++++--
 net/netfilter/nf_conntrack_sane.c           |   11 +++--
 net/netfilter/nf_conntrack_sip.c            |   10 +++-
 net/netfilter/nf_conntrack_tftp.c           |   11 +++--
 15 files changed, 166 insertions(+), 77 deletions(-)
include/net/netfilter/nf_conntrack.h +4 -1
index 90b3e7f..9228771 100644
@@ -75,6 +75,9 @@ do {									\
 
 struct nf_conntrack_helper;
 
+/* Must be kept in sync with the classes defined by helpers */
+#define NF_CT_MAX_EXPECT_CLASSES	1
+
 /* nf_conn feature for connections that have a helper */
 struct nf_conn_help {
 	/* Helper. if any */
@@ -85,7 +88,7 @@ struct nf_conn_help {
 	struct hlist_head expectations;
 
 	/* Current number of expected connections */
-	unsigned int expecting;
+	u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
 };
 
 
include/net/netfilter/nf_conntrack_expect.h +12 -1
index 47c28dd..dfdf4b4 100644
@@ -41,6 +41,9 @@ struct nf_conntrack_expect
 	/* Flags */
 	unsigned int flags;
 
+	/* Expectation class */
+	unsigned int class;
+
 #ifdef CONFIG_NF_NAT_NEEDED
 	__be32 saved_ip;
 	/* This is the original per-proto part, used to map the
@@ -53,6 +56,14 @@ struct nf_conntrack_expect
 	struct rcu_head rcu;
 };
 
+struct nf_conntrack_expect_policy
+{
+	unsigned int	max_expected;
+	unsigned int	timeout;
+};
+
+#define NF_CT_EXPECT_CLASS_DEFAULT	0
+
 #define NF_CT_EXPECT_PERMANENT	0x1
 #define NF_CT_EXPECT_INACTIVE	0x2
 
@@ -75,7 +86,7 @@ void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
 /* Allocate space for an expectation: this is mandatory before calling
    nf_ct_expect_related.  You will have to call put afterwards. */
 struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
-void nf_ct_expect_init(struct nf_conntrack_expect *, int,
+void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, int,
 		       const union nf_inet_addr *,
 		       const union nf_inet_addr *,
 		       u_int8_t, const __be16 *, const __be16 *);
include/net/netfilter/nf_conntrack_helper.h +2 -3
index 4ca125e..f8060ab 100644
@@ -20,9 +20,7 @@ struct nf_conntrack_helper
 
 	const char *name;		/* name of the module */
 	struct module *me;		/* pointer to self */
-	unsigned int max_expected;	/* Maximum number of concurrent 
-					 * expected connections */
-	unsigned int timeout;		/* timeout for expecteds */
+	const struct nf_conntrack_expect_policy *expect_policy;
 
 	/* Tuple of things we will help (compared against server response) */
 	struct nf_conntrack_tuple tuple;
@@ -37,6 +35,7 @@ struct nf_conntrack_helper
 	void (*destroy)(struct nf_conn *ct);
 
 	int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
+	unsigned int expect_class_max;
 };
 
 extern struct nf_conntrack_helper *
net/ipv4/netfilter/nf_nat_snmp_basic.c +8 -4
index 540ce6a..000e080 100644
@@ -50,6 +50,7 @@
 #include <net/udp.h>
 
 #include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_nat_helper.h>
 
@@ -1267,11 +1268,15 @@ static int help(struct sk_buff *skb, unsigned int protoff,
 	return ret;
 }
 
+static const struct nf_conntrack_expect_policy snmp_exp_policy = {
+	.max_expected	= 0,
+	.timeout	= 180,
+};
+
 static struct nf_conntrack_helper snmp_helper __read_mostly = {
-	.max_expected		= 0,
-	.timeout		= 180,
 	.me			= THIS_MODULE,
 	.help			= help,
+	.expect_policy		= &snmp_exp_policy,
 	.name			= "snmp",
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(SNMP_PORT),
@@ -1279,10 +1284,9 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = {
 };
 
 static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
-	.max_expected		= 0,
-	.timeout		= 180,
 	.me			= THIS_MODULE,
 	.help			= help,
+	.expect_policy		= &snmp_exp_policy,
 	.name			= "snmp_trap",
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(SNMP_TRAP_PORT),
net/netfilter/nf_conntrack_amanda.c +9 -5
index 7b8239c..d14585a 100644
@@ -148,7 +148,8 @@ static int amanda_help(struct sk_buff *skb,
 			goto out;
 		}
 		tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, family,
+				  &tuple->src.u3, &tuple->dst.u3,
 				  IPPROTO_TCP, NULL, &port);
 
 		nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
@@ -164,26 +165,29 @@ out:
 	return ret;
 }
 
+static const struct nf_conntrack_expect_policy amanda_exp_policy = {
+	.max_expected		= 3,
+	.timeout		= 180,
+};
+
 static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
 	{
 		.name			= "amanda",
-		.max_expected		= 3,
-		.timeout		= 180,
 		.me			= THIS_MODULE,
 		.help			= amanda_help,
 		.tuple.src.l3num	= AF_INET,
 		.tuple.src.u.udp.port	= __constant_htons(10080),
 		.tuple.dst.protonum	= IPPROTO_UDP,
+		.expect_policy		= &amanda_exp_policy,
 	},
 	{
 		.name			= "amanda",
-		.max_expected		= 3,
-		.timeout		= 180,
 		.me			= THIS_MODULE,
 		.help			= amanda_help,
 		.tuple.src.l3num	= AF_INET6,
 		.tuple.src.u.udp.port	= __constant_htons(10080),
 		.tuple.dst.protonum	= IPPROTO_UDP,
+		.expect_policy		= &amanda_exp_policy,
 	},
 };
 
net/netfilter/nf_conntrack_expect.c +33 -17

130 lines not on this page · raw message

net/netfilter/nf_conntrack_ftp.c +7 -3
index 6770baf..7eff876 100644
@@ -483,7 +483,7 @@ static int help(struct sk_buff *skb,
 		daddr = &cmd.u3;
 	}
 
-	nf_ct_expect_init(exp, cmd.l3num,
+	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num,
 			  &ct->tuplehash[!dir].tuple.src.u3, daddr,
 			  IPPROTO_TCP, NULL, &cmd.u.tcp.port);
 
@@ -517,6 +517,11 @@ out_update_nl:
 static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
 static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly;
 
+static const struct nf_conntrack_expect_policy ftp_exp_policy = {
+	.max_expected	= 1,
+	.timeout	= 5 * 60,
+};
+
 /* don't make this __exit, since it's called from __init ! */
 static void nf_conntrack_ftp_fini(void)
 {
@@ -556,8 +561,7 @@ static int __init nf_conntrack_ftp_init(void)
 		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].max_expected = 1;
-			ftp[i][j].timeout = 5 * 60;	/* 5 Minutes */
+			ftp[i][j].expect_policy = &ftp_exp_policy;
 			ftp[i][j].me = THIS_MODULE;
 			ftp[i][j].help = help;
 			tmpname = &ftp_names[i][j][0];
net/netfilter/nf_conntrack_h323_main.c +42 -24

172 lines not on this page · raw message

net/netfilter/nf_conntrack_helper.c +2 -1
index b1fd21c..e350f56 100644
@@ -110,7 +110,8 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
 	unsigned int h = helper_hash(&me->tuple);
 
-	BUG_ON(me->timeout == 0);
+	BUG_ON(me->expect_policy == NULL);
+	BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
 
 	mutex_lock(&nf_ct_helper_mutex);
 	hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
net/netfilter/nf_conntrack_irc.c +7 -3
index c336b07..02f21cb 100644
@@ -187,7 +187,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
 			}
 			tuple = &ct->tuplehash[!dir].tuple;
 			port = htons(dcc_port);
-			nf_ct_expect_init(exp, tuple->src.l3num,
+			nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
+					  tuple->src.l3num,
 					  NULL, &tuple->dst.u3,
 					  IPPROTO_TCP, NULL, &port);
 
@@ -210,6 +211,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
 
 static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
 static char irc_names[MAX_PORTS][sizeof("irc-65535")] __read_mostly;
+static struct nf_conntrack_expect_policy irc_exp_policy;
 
 static void nf_conntrack_irc_fini(void);
 
@@ -223,6 +225,9 @@ static int __init nf_conntrack_irc_init(void)
 		return -EINVAL;
 	}
 
+	irc_exp_policy.max_expected = max_dcc_channels;
+	irc_exp_policy.timeout = dcc_timeout;
+
 	irc_buffer = kmalloc(65536, GFP_KERNEL);
 	if (!irc_buffer)
 		return -ENOMEM;
@@ -235,8 +240,7 @@ static int __init nf_conntrack_irc_init(void)
 		irc[i].tuple.src.l3num = AF_INET;
 		irc[i].tuple.src.u.tcp.port = htons(ports[i]);
 		irc[i].tuple.dst.protonum = IPPROTO_TCP;
-		irc[i].max_expected = max_dcc_channels;
-		irc[i].timeout = dcc_timeout;
+		irc[i].expect_policy = &irc_exp_policy;
 		irc[i].me = THIS_MODULE;
 		irc[i].help = help;
 
net/netfilter/nf_conntrack_netbios_ns.c +7 -2
index 60dedad..08404e6 100644
@@ -86,6 +86,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
 
 	exp->expectfn             = NULL;
 	exp->flags                = NF_CT_EXPECT_PERMANENT;
+	exp->class		  = NF_CT_EXPECT_CLASS_DEFAULT;
 	exp->helper               = NULL;
 
 	nf_ct_expect_related(exp);
@@ -96,19 +97,23 @@ out:
 	return NF_ACCEPT;
 }
 
+static struct nf_conntrack_expect_policy exp_policy = {
+	.max_expected	= 1,
+};
+
 static struct nf_conntrack_helper helper __read_mostly = {
 	.name			= "netbios-ns",
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(NMBD_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.max_expected		= 1,
 	.me			= THIS_MODULE,
 	.help			= help,
+	.expect_policy		= &exp_policy,
 };
 
 static int __init nf_conntrack_netbios_ns_init(void)
 {
-	helper.timeout = timeout;
+	exp_policy.timeout = timeout;
 	return nf_conntrack_helper_register(&helper);
 }
 
net/netfilter/nf_conntrack_pptp.c +10 -4
index b5cb8e8..8fd8347 100644
@@ -208,7 +208,8 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
 
 	/* original direction, PNS->PAC */
 	dir = IP_CT_DIR_ORIGINAL;
-	nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
+	nf_ct_expect_init(exp_orig, NF_CT_EXPECT_CLASS_DEFAULT,
+			  ct->tuplehash[dir].tuple.src.l3num,
 			  &ct->tuplehash[dir].tuple.src.u3,
 			  &ct->tuplehash[dir].tuple.dst.u3,
 			  IPPROTO_GRE, &peer_callid, &callid);
@@ -216,7 +217,8 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
 
 	/* reply direction, PAC->PNS */
 	dir = IP_CT_DIR_REPLY;
-	nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
+	nf_ct_expect_init(exp_reply, NF_CT_EXPECT_CLASS_DEFAULT,
+			  ct->tuplehash[dir].tuple.src.l3num,
 			  &ct->tuplehash[dir].tuple.src.u3,
 			  &ct->tuplehash[dir].tuple.dst.u3,
 			  IPPROTO_GRE, &callid, &peer_callid);
@@ -575,17 +577,21 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,
 	return ret;
 }
 
+static const struct nf_conntrack_expect_policy pptp_exp_policy = {
+	.max_expected	= 2,
+	.timeout	= 5 * 60,
+};
+
 /* control protocol helper */
 static struct nf_conntrack_helper pptp __read_mostly = {
 	.name			= "pptp",
 	.me			= THIS_MODULE,
-	.max_expected		= 2,
-	.timeout		= 5 * 60,
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.tcp.port	= __constant_htons(PPTP_CONTROL_PORT),
 	.tuple.dst.protonum	= IPPROTO_TCP,
 	.help			= conntrack_pptp_help,
 	.destroy		= pptp_destroy_siblings,
+	.expect_policy		= &pptp_exp_policy,
 };
 
 static int __init nf_conntrack_pptp_init(void)
net/netfilter/nf_conntrack_sane.c +8 -3
index a70051d..7542e25 100644
@@ -143,7 +143,8 @@ static int help(struct sk_buff *skb,
 	}
 
 	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-	nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, family,
+			  &tuple->src.u3, &tuple->dst.u3,
 			  IPPROTO_TCP, NULL, &reply->port);
 
 	pr_debug("nf_ct_sane: expect: ");
@@ -163,6 +164,11 @@ out:
 static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
 static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly;
 
+static const struct nf_conntrack_expect_policy sane_exp_policy = {
+	.max_expected	= 1,
+	.timeout	= 5 * 60,
+};
+
 /* don't make this __exit, since it's called from __init ! */
 static void nf_conntrack_sane_fini(void)
 {
@@ -200,8 +206,7 @@ static int __init nf_conntrack_sane_init(void)
 		for (j = 0; j < 2; j++) {
 			sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
 			sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
-			sane[i][j].max_expected = 1;
-			sane[i][j].timeout = 5 * 60;	/* 5 Minutes */
+			sane[i][j].expect_policy = &sane_exp_policy;
 			sane[i][j].me = THIS_MODULE;
 			sane[i][j].help = help;
 			tmpname = &sane_names[i][j][0];
net/netfilter/nf_conntrack_sip.c +7 -3
index c521c89..0021d5b 100644
@@ -380,7 +380,7 @@ static int set_expected_rtp(struct sk_buff *skb,
 	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL)
 		return NF_DROP;
-	nf_ct_expect_init(exp, family,
+	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, family,
 			  &ct->tuplehash[!dir].tuple.src.u3, addr,
 			  IPPROTO_UDP, NULL, &port);
 
@@ -476,6 +476,11 @@ out:
 static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;
 static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly;
 
+static const struct nf_conntrack_expect_policy sip_exp_policy = {
+	.max_expected	= 2,
+	.timeout	= 3 * 60,
+};
+
 static void nf_conntrack_sip_fini(void)
 {
 	int i, j;
@@ -505,8 +510,7 @@ static int __init nf_conntrack_sip_init(void)
 		for (j = 0; j < 2; j++) {
 			sip[i][j].tuple.dst.protonum = IPPROTO_UDP;
 			sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
-			sip[i][j].max_expected = 2;
-			sip[i][j].timeout = 3 * 60; /* 3 minutes */
+			sip[i][j].expect_policy = &sip_exp_policy;
 			sip[i][j].me = THIS_MODULE;
 			sip[i][j].help = sip_help;
 
net/netfilter/nf_conntrack_tftp.c +8 -3
index bd2e800..a28341b 100644
@@ -63,7 +63,8 @@ static int tftp_help(struct sk_buff *skb,
 		if (exp == NULL)
 			return NF_DROP;
 		tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, family,
+				  &tuple->src.u3, &tuple->dst.u3,
 				  IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
 
 		pr_debug("expect: ");
@@ -92,6 +93,11 @@ static int tftp_help(struct sk_buff *skb,
 static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly;
 static char tftp_names[MAX_PORTS][2][sizeof("tftp-65535")] __read_mostly;
 
+static const struct nf_conntrack_expect_policy tftp_exp_policy = {
+	.max_expected	= 1,
+	.timeout	= 5 * 60,
+};
+
 static void nf_conntrack_tftp_fini(void)
 {
 	int i, j;
@@ -118,8 +124,7 @@ static int __init nf_conntrack_tftp_init(void)
 		for (j = 0; j < 2; j++) {
 			tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
 			tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
-			tftp[i][j].max_expected = 1;
-			tftp[i][j].timeout = 5 * 60; /* 5 minutes */
+			tftp[i][j].expect_policy = &tftp_exp_policy;
 			tftp[i][j].me = THIS_MODULE;
 			tftp[i][j].help = tftp_help;
 
#9 lore raw

Re: [NETFILTER 06/32]: nf_conntrack: introduce expectation classes and policies

net/netfilter/nf_conntrack_h323_main.c static int h245_help(struct sk_buff *skb, unsigned int protoff, · line 622

Quoted 6 lines · Patrick McHardy

/****************************************************************************/

net/netfilter/nf_conntrack_h323_main.c +5 -0
+static const struct nf_conntrack_expect_policy h245_exp_policy = {
+	.max_expected	= H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
+	.timeout	= 240,
+};
+

Developer questions: what does ->max_expected limit? Expectations for one connection, or for the whole helper module?

net/netfilter/nf_conntrack_helper.c int nf_conntrack_helper_register(struct nf_conntrack_helper *me) · line 117

Quoted 10 lines
net/netfilter/nf_conntrack_helper.c +2 -1
@@ -110,7 +110,8 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
 	unsigned int h = helper_hash(&me->tuple);
 
-	BUG_ON(me->timeout == 0);
+	BUG_ON(me->expect_policy == NULL);
+	BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
 
 	mutex_lock(&nf_ct_helper_mutex);
 	hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);

A zero timeout triggered a BUG_ON in nf_conntrack_helper_register, now this check is gone!?

#10 lore raw

Re: [NETFILTER 06/32]: nf_conntrack: introduce expectation classes and policies

Quoted 6 lines · Jan Engelhardt
Quoted 2 lines · Patrick McHardy

/****************************************************************************/

Quoted 8 lines

net/netfilter/nf_conntrack_h323_main.c static int h245_help(struct sk_buff *skb, unsigned int protoff, · line 622

Quoted 5 lines
net/netfilter/nf_conntrack_h323_main.c +5 -0
+static const struct nf_conntrack_expect_policy h245_exp_policy = {
+    .max_expected    = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
+    .timeout    = 240,
+};
+

Developer questions: what does ->max_expected limit? Expectations for one connection, or for the whole helper module?

Unfulfilled expectations per conntrack.

Quoted 9 lines
Quoted 9 lines
net/netfilter/nf_conntrack_helper.c +2 -1
@@ -110,7 +110,8 @@ int nf_conntrack_helper_register(struct 
 nf_conntrack_helper *me)
 {
    unsigned int h = helper_hash(&me->tuple);
 
-    BUG_ON(me->timeout == 0);
+    BUG_ON(me->expect_policy == NULL);
+    BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
 
Quoted 5 lines
Quoted 2 lines
net/netfilter/nf_conntrack_helper.c +0 -0
    mutex_lock(&nf_ct_helper_mutex);
    hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);

A zero timeout triggered a BUG_ON in nf_conntrack_helper_register, now this check is gone!?

Yes, it requires iterating through the policies, which is too much trouble for checking a developer bug (and no module in the kernel does this). In fact the SNMP NAT helper sets a fake timeout to avoid triggering the BUG_ON since it never registers any expectations.

#11 lore raw

PATCH 7/32 : Add nf_inet_addr_cmp()

In reply to Patrick McHardy

[NETFILTER]: Add nf_inet_addr_cmp()

---
commit 14d510e3026c99ebd8531e8ea0acb574545b5c42
tree aca9464205040aa5daa25a50a0e98443f905eb0b
parent 48bb8ab5591cab986a2850facf33998357db3b10
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:45 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 13:44:45 +0100

 include/linux/netfilter.h                  |    9 +++++++++
 include/net/netfilter/nf_conntrack_tuple.h |   15 +++------------
 2 files changed, 12 insertions(+), 12 deletions(-)
include/linux/netfilter.h +9 -0
index f0680c2..89e6c72 100644
@@ -61,6 +61,15 @@ union nf_inet_addr {
 #ifdef __KERNEL__
 #ifdef CONFIG_NETFILTER
 
+static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1,
+				   const union nf_inet_addr *a2)
+{
+	return a1->all[0] == a2->all[0] &&
+	       a1->all[1] == a2->all[1] &&
+	       a1->all[2] == a2->all[2] &&
+	       a1->all[3] == a2->all[3];
+}
+
 extern void netfilter_init(void);
 
 /* Largest hook number + 1 */
include/net/netfilter/nf_conntrack_tuple.h +3 -12
index d9b53dd..168c917 100644
@@ -163,10 +163,7 @@ struct nf_conntrack_tuple_hash
 static inline int __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
 					  const struct nf_conntrack_tuple *t2)
 { 
-	return (t1->src.u3.all[0] == t2->src.u3.all[0] &&
-		t1->src.u3.all[1] == t2->src.u3.all[1] &&
-		t1->src.u3.all[2] == t2->src.u3.all[2] &&
-		t1->src.u3.all[3] == t2->src.u3.all[3] &&
+	return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) &&
 		t1->src.u.all == t2->src.u.all &&
 		t1->src.l3num == t2->src.l3num);
 }
@@ -174,10 +171,7 @@ static inline int __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
 static inline int __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
 					  const struct nf_conntrack_tuple *t2)
 {
-	return (t1->dst.u3.all[0] == t2->dst.u3.all[0] &&
-		t1->dst.u3.all[1] == t2->dst.u3.all[1] &&
-		t1->dst.u3.all[2] == t2->dst.u3.all[2] &&
-		t1->dst.u3.all[3] == t2->dst.u3.all[3] &&
+	return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) &&
 		t1->dst.u.all == t2->dst.u.all &&
 		t1->dst.protonum == t2->dst.protonum);
 }
@@ -192,10 +186,7 @@ static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
 static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
 					 const struct nf_conntrack_tuple_mask *m2)
 {
-	return (m1->src.u3.all[0] == m2->src.u3.all[0] &&
-		m1->src.u3.all[1] == m2->src.u3.all[1] &&
-		m1->src.u3.all[2] == m2->src.u3.all[2] &&
-		m1->src.u3.all[3] == m2->src.u3.all[3] &&
+	return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) &&
 		m1->src.u.all == m2->src.u.all);
 }
 
#12 lore raw

PATCH 8/32 : nf_nat_sip: fix NAT setup order

In reply to Patrick McHardy

[NETFILTER]: nf_nat_sip: fix NAT setup order

We need to set up the destination NAT mapping before the source NAT mapping, so the NAT core gets to see the final tuple and can decide whether the source port needs to be remapped.

---
commit b76b0afe5818cb9aac50d57e0be319935f58ed64
tree aecf418e8d77a75e0fdbf8250a2e9fe028131c13
parent 14d510e3026c99ebd8531e8ea0acb574545b5c42
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:44:48 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:53 +0100

 net/ipv4/netfilter/nf_nat_sip.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)
net/ipv4/netfilter/nf_nat_sip.c +6 -6
index b4c8d49..84d8b49 100644
@@ -224,17 +224,17 @@ static void ip_nat_sdp_expect(struct nf_conn *ct,
 	/* This must be a fresh one. */
 	BUG_ON(ct->status & IPS_NAT_DONE_MASK);
 
-	/* Change src to where master sends to */
-	range.flags = IP_NAT_RANGE_MAP_IPS;
-	range.min_ip = range.max_ip
-		= ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
-	nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
-
 	/* For DST manip, map port here to where it's expected. */
 	range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
 	range.min = range.max = exp->saved_proto;
 	range.min_ip = range.max_ip = exp->saved_ip;
 	nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
+
+	/* Change src to where master sends to */
+	range.flags = IP_NAT_RANGE_MAP_IPS;
+	range.min_ip = range.max_ip
+		= ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+	nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
 }
 
 /* So, this packet has hit the connection tracking matching code.
#13 lore raw

PATCH 9/32 : nf_conntrack_sip: fix some off-by-ones

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: fix some off-by-ones

"limit" marks the first character outside the bounds.

---
commit 3e654acbb82002c6fdc57573c8167ade5608dbd3
tree e04d2649131a18732f66d253366d9d3962a5d1bc
parent b76b0afe5818cb9aac50d57e0be319935f58ed64
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:44:50 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:54 +0100

 net/netfilter/nf_conntrack_sip.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)
net/netfilter/nf_conntrack_sip.c +8 -8
index 0021d5b..016e1c1 100644
@@ -192,10 +192,10 @@ int ct_sip_lnlen(const char *line, const char *limit)
 {
 	const char *k = line;
 
-	while ((line <= limit) && (*line == '\r' || *line == '\n'))
+	while ((line < limit) && (*line == '\r' || *line == '\n'))
 		line++;
 
-	while (line <= limit) {
+	while (line < limit) {
 		if (*line == '\r' || *line == '\n')
 			break;
 		line++;
@@ -211,7 +211,7 @@ const char *ct_sip_search(const char *needle, const char *haystack,
 {
 	const char *limit = haystack + (haystack_len - needle_len);
 
-	while (haystack <= limit) {
+	while (haystack < limit) {
 		if (case_sensitive) {
 			if (strncmp(haystack, needle, needle_len) == 0)
 				return haystack;
@@ -229,7 +229,7 @@ static int digits_len(const struct nf_conn *ct, const char *dptr,
 		      const char *limit, int *shift)
 {
 	int len = 0;
-	while (dptr <= limit && isdigit(*dptr)) {
+	while (dptr < limit && isdigit(*dptr)) {
 		dptr++;
 		len++;
 	}
@@ -240,7 +240,7 @@ static int digits_len(const struct nf_conn *ct, const char *dptr,
 static int skp_digits_len(const struct nf_conn *ct, const char *dptr,
 			  const char *limit, int *shift)
 {
-	for (; dptr <= limit && *dptr == ' '; dptr++)
+	for (; dptr < limit && *dptr == ' '; dptr++)
 		(*shift)++;
 
 	return digits_len(ct, dptr, limit, shift);
@@ -302,13 +302,13 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
 	/* Search for @, but stop at the end of the line.
 	 * We are inside a sip: URI, so we don't need to worry about
 	 * continuation lines. */
-	while (dptr <= limit &&
+	while (dptr < limit &&
 	       *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
 		(*shift)++;
 		dptr++;
 	}
 
-	if (dptr <= limit && *dptr == '@') {
+	if (dptr < limit && *dptr == '@') {
 		dptr++;
 		(*shift)++;
 	} else {
@@ -332,7 +332,7 @@ int ct_sip_get_info(const struct nf_conn *ct,
 
 	limit = dptr + (dlen - hnfo->lnlen);
 
-	while (dptr <= limit) {
+	while (dptr < limit) {
 		if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
 		    (hnfo->sname == NULL ||
 		     strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
#14 lore raw

PATCH 10/32 : nf_conntrack_sip: adjust dptr and datalen after packet mangling

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: adjust dptr and datalen after packet mangling

After mangling the packet, the pointer to the data and the length of the data portion may change and need to be adjusted.

Use double data pointers and a pointer to the length everywhere and add a helper function to the NAT helper for performing the adjustments.

---
commit cc0d0b162f0e36ddfd0b9fbed58a39a2d1561fb6
tree 653d23b2e4bb220d75bba2ffd358aec10a99d937
parent 3e654acbb82002c6fdc57573c8167ade5608dbd3
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:44:52 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:54 +0100

 include/linux/netfilter/nf_conntrack_sip.h |    6 +-
 net/ipv4/netfilter/nf_nat_sip.c            |   91 +++++++++++++++-------------
 net/netfilter/nf_conntrack_sip.c           |   14 ++--
 3 files changed, 60 insertions(+), 51 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +4 -2
index 8e5ce1c..9d0dbfb 100644
@@ -24,11 +24,13 @@ enum sip_header_pos {
 extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
 				       enum ip_conntrack_info ctinfo,
 				       struct nf_conn *ct,
-				       const char **dptr);
+				       const char **dptr,
+				       unsigned int *datalen);
 extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 				       enum ip_conntrack_info ctinfo,
 				       struct nf_conntrack_expect *exp,
-				       const char *dptr);
+				       const char **dptr,
+				       unsigned int *datalen);
 
 extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
                            size_t dlen, unsigned int *matchoff,
net/ipv4/netfilter/nf_nat_sip.c +48 -43

191 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +8 -6
index 016e1c1..fa0d559 100644
@@ -39,13 +39,15 @@ MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
 unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
 				enum ip_conntrack_info ctinfo,
 				struct nf_conn *ct,
-				const char **dptr) __read_mostly;
+				const char **dptr,
+				unsigned int *datalen) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
 
 unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 				enum ip_conntrack_info ctinfo,
 				struct nf_conntrack_expect *exp,
-				const char *dptr) __read_mostly;
+				const char **dptr,
+				unsigned int *datalen) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_sdp_hook);
 
 static int digits_len(const struct nf_conn *, const char *, const char *, int *);
@@ -369,7 +371,7 @@ static int set_expected_rtp(struct sk_buff *skb,
 			    enum ip_conntrack_info ctinfo,
 			    union nf_inet_addr *addr,
 			    __be16 port,
-			    const char *dptr)
+			    const char **dptr, unsigned int *datalen)
 {
 	struct nf_conntrack_expect *exp;
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@@ -386,7 +388,7 @@ static int set_expected_rtp(struct sk_buff *skb,
 
 	nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
 	if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
-		ret = nf_nat_sdp(skb, ctinfo, exp, dptr);
+		ret = nf_nat_sdp(skb, ctinfo, exp, dptr, datalen);
 	else {
 		if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
@@ -429,7 +431,7 @@ static int sip_help(struct sk_buff *skb,
 
 	nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
 	if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
-		if (!nf_nat_sip(skb, ctinfo, ct, &dptr)) {
+		if (!nf_nat_sip(skb, ctinfo, ct, &dptr, &datalen)) {
 			ret = NF_DROP;
 			goto out;
 		}
@@ -466,7 +468,7 @@ static int sip_help(struct sk_buff *skb,
 				goto out;
 			}
 			ret = set_expected_rtp(skb, ct, ctinfo, &addr,
-					       htons(port), dptr);
+					       htons(port), &dptr, &datalen);
 		}
 	}
 out:
#15 lore raw

PATCH 11/32 : nf_conntrack_sip: remove redundant function arguments

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: remove redundant function arguments

The conntrack reference and ctinfo can be derived from the packet.

---
commit 596c3f5c075a54207dcf8dffb108031e736861ba
tree f85551406a7aec725da39f443fd02043af28e5ca
parent cc0d0b162f0e36ddfd0b9fbed58a39a2d1561fb6
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:44:53 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:54 +0100

 include/linux/netfilter/nf_conntrack_sip.h |    7 +---
 net/ipv4/netfilter/nf_nat_sip.c            |   49 ++++++++++++++--------------
 net/netfilter/nf_conntrack_sip.c           |   24 ++++++--------
 3 files changed, 37 insertions(+), 43 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +2 -5
index 9d0dbfb..b94de3d 100644
@@ -22,15 +22,12 @@ enum sip_header_pos {
 };
 
 extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
-				       enum ip_conntrack_info ctinfo,
-				       struct nf_conn *ct,
 				       const char **dptr,
 				       unsigned int *datalen);
 extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
-				       enum ip_conntrack_info ctinfo,
-				       struct nf_conntrack_expect *exp,
 				       const char **dptr,
-				       unsigned int *datalen);
+				       unsigned int *datalen,
+				       struct nf_conntrack_expect *exp);
 
 extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
                            size_t dlen, unsigned int *matchoff,
net/ipv4/netfilter/nf_nat_sip.c +25 -24

113 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +10 -14
index fa0d559..38e1e7a 100644
@@ -37,17 +37,14 @@ module_param(sip_timeout, uint, 0600);
 MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
 
 unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
-				enum ip_conntrack_info ctinfo,
-				struct nf_conn *ct,
 				const char **dptr,
 				unsigned int *datalen) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
 
 unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
-				enum ip_conntrack_info ctinfo,
-				struct nf_conntrack_expect *exp,
 				const char **dptr,
-				unsigned int *datalen) __read_mostly;
+				unsigned int *datalen,
+				struct nf_conntrack_expect *exp) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_sdp_hook);
 
 static int digits_len(const struct nf_conn *, const char *, const char *, int *);
@@ -367,13 +364,12 @@ int ct_sip_get_info(const struct nf_conn *ct,
 EXPORT_SYMBOL_GPL(ct_sip_get_info);
 
 static int set_expected_rtp(struct sk_buff *skb,
-			    struct nf_conn *ct,
-			    enum ip_conntrack_info ctinfo,
-			    union nf_inet_addr *addr,
-			    __be16 port,
-			    const char **dptr, unsigned int *datalen)
+			    const char **dptr, unsigned int *datalen,
+			    union nf_inet_addr *addr, __be16 port)
 {
 	struct nf_conntrack_expect *exp;
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 	int family = ct->tuplehash[!dir].tuple.src.l3num;
 	int ret;
@@ -388,7 +384,7 @@ static int set_expected_rtp(struct sk_buff *skb,
 
 	nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
 	if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
-		ret = nf_nat_sdp(skb, ctinfo, exp, dptr, datalen);
+		ret = nf_nat_sdp(skb, dptr, datalen, exp);
 	else {
 		if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
@@ -431,7 +427,7 @@ static int sip_help(struct sk_buff *skb,
 
 	nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
 	if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
-		if (!nf_nat_sip(skb, ctinfo, ct, &dptr, &datalen)) {
+		if (!nf_nat_sip(skb, &dptr, &datalen)) {
 			ret = NF_DROP;
 			goto out;
 		}
@@ -467,8 +463,8 @@ static int sip_help(struct sk_buff *skb,
 				ret = NF_DROP;
 				goto out;
 			}
-			ret = set_expected_rtp(skb, ct, ctinfo, &addr,
-					       htons(port), &dptr, &datalen);
+			ret = set_expected_rtp(skb, &dptr, &datalen,
+					       &addr, htons(port));
 		}
 	}
 out:
#16 lore raw

PATCH 12/32 : nf_conntrack_sip: use strlen/strcmp

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: use strlen/strcmp

Replace sizeof/memcmp by strlen/strcmp. Use case-insensitive comparison for SIP methods and the SIP/2.0 string, as specified in RFC 3261.

---
commit 7fc3c23d9817c4086c5bff587d614136ba5dfc80
tree 887b6f2cb2f08cfd94c985960f465c45a82a3b02
parent 596c3f5c075a54207dcf8dffb108031e736861ba
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:44:55 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:54 +0100

 net/ipv4/netfilter/nf_nat_sip.c  |   12 ++++++------
 net/netfilter/nf_conntrack_sip.c |   12 ++++++------
 2 files changed, 12 insertions(+), 12 deletions(-)
net/ipv4/netfilter/nf_nat_sip.c +6 -6
index acaa7d4..dd1b2d8 100644
@@ -94,12 +94,12 @@ static int map_sip_addr(struct sk_buff *skb,
 
 	if ((matchlen == map->addr[dir].srciplen ||
 	     matchlen == map->addr[dir].srclen) &&
-	    memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
+	    strncmp(*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) {
+		   strncmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
 		addr    = map->addr[!dir].src;
 		addrlen = map->addr[!dir].srclen;
 	} else
@@ -117,20 +117,20 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 	enum sip_header_pos pos;
 	struct addr_map map;
 
-	if (*datalen < sizeof("SIP/2.0") - 1)
+	if (*datalen < strlen("SIP/2.0"))
 		return NF_ACCEPT;
 
 	addr_map_init(ct, &map);
 
 	/* Basic rules: requests and responses. */
-	if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
+	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 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)
+		if (*datalen >= strlen("REGISTER") &&
+		    strnicmp(*dptr, "REGISTER", strlen("REGISTER")) == 0)
 			pos = POS_REG_REQ_URI;
 		else
 			pos = POS_REQ_URI;
net/netfilter/nf_conntrack_sip.c +6 -6
index 38e1e7a..cf19a70 100644
@@ -434,15 +434,15 @@ static int sip_help(struct sk_buff *skb,
 	}
 
 	datalen = skb->len - dataoff;
-	if (datalen < sizeof("SIP/2.0 200") - 1)
+	if (datalen < strlen("SIP/2.0 200"))
 		goto out;
 
 	/* RTP info only in some SDP pkts */
-	if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
-	    memcmp(dptr, "UPDATE", sizeof("UPDATE") - 1) != 0 &&
-	    memcmp(dptr, "SIP/2.0 180", sizeof("SIP/2.0 180") - 1) != 0 &&
-	    memcmp(dptr, "SIP/2.0 183", sizeof("SIP/2.0 183") - 1) != 0 &&
-	    memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
+	if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 &&
+	    strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 &&
+	    strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 0 &&
+	    strnicmp(dptr, "SIP/2.0 183", strlen("SIP/2.0 183")) != 0 &&
+	    strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) {
 		goto out;
 	}
 	/* Get address and port from SDP packet. */
#17 lore raw

PATCH 13/32 : nf_conntrack_sip: add seperate SDP header parsing function

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: add seperate SDP header parsing function

SDP and SIP headers are quite different, SIP can have continuation lines, leading and trailing whitespace after the colon and is mostly case-insensitive while SDP headers always begin on a new line and are followed by an equal sign and the value, without any whitespace.

Introduce new SDP header parsing function and convert all users that used the SIP header parsing function. This will allow to properly deal with the special SIP cases in the SIP header parsing function later.

---
commit 3a7cda6054cd6374b0b18b72e71404b5ca7b2155
tree ff4c8e34c71a5151b9122f91b8bb5dc1334cc4f4
parent 7fc3c23d9817c4086c5bff587d614136ba5dfc80
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:44:57 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:54 +0100

 include/linux/netfilter/nf_conntrack_sip.h |   49 ++++++++-
 net/ipv4/netfilter/nf_nat_sip.c            |   69 ++++++------
 net/netfilter/nf_conntrack_sip.c           |  159 +++++++++++++++++-----------
 3 files changed, 169 insertions(+), 108 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +43 -6
index b94de3d..9131cbc 100644
@@ -13,12 +13,42 @@ enum sip_header_pos {
 	POS_VIA,
 	POS_CONTACT,
 	POS_CONTENT,
-	POS_MEDIA,
-	POS_OWNER_IP4,
-	POS_CONNECTION_IP4,
-	POS_OWNER_IP6,
-	POS_CONNECTION_IP6,
-	POS_SDP_HEADER,
+};
+
+struct sip_header {
+	const char	*name;
+	const char	*cname;
+	const char	*search;
+	unsigned int	len;
+	unsigned int	clen;
+	unsigned int	slen;
+	int		(*match_len)(const struct nf_conn *ct,
+				     const char *dptr, const char *limit,
+				     int *shift);
+};
+
+#define __SIP_HDR(__name, __cname, __search, __match)			\
+{									\
+	.name		= (__name),					\
+	.len		= sizeof(__name) - 1,				\
+	.cname		= (__cname),					\
+	.clen		= (__cname) ? sizeof(__cname) - 1 : 0,		\
+	.search		= (__search),					\
+	.slen		= (__search) ? sizeof(__search) - 1 : 0,	\
+	.match_len	= (__match),					\
+}
+
+#define SDP_HDR(__name, __search, __match) \
+	__SIP_HDR(__name, NULL, __search, __match)
+
+enum sdp_header_types {
+	SDP_HDR_UNSPEC,
+	SDP_HDR_VERSION,
+	SDP_HDR_OWNER_IP4,
+	SDP_HDR_CONNECTION_IP4,
+	SDP_HDR_OWNER_IP6,
+	SDP_HDR_CONNECTION_IP6,
+	SDP_HDR_MEDIA,
 };
 
 extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
@@ -36,5 +66,12 @@ 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,
 				 int case_sensitive);
+
+extern int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
+				 unsigned int dataoff, unsigned int datalen,
+				 enum sdp_header_types type,
+				 enum sdp_header_types term,
+				 unsigned int *matchoff, unsigned int *matchlen);
+
 #endif /* __KERNEL__ */
 #endif /* __NF_CONNTRACK_SIP_H__ */
net/ipv4/netfilter/nf_nat_sip.c +32 -37

101 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +94 -65

189 lines not on this page · raw message

#18 lore raw

PATCH 14/32 : nf_conntrack_sip: kill request URI "header" definitions

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: kill request URI "header" definitions

The request URI is not a header and needs to be treated differently than real SIP headers. Add a seperate function for parsing it and get rid of the POS_REQ_URI/POS_REG_REQ_URI definitions.

---
commit 6b8ae4462dcdaf5c0e28ea5750f391efb738fab1
tree a59c883431a99d5eb65b0ce5039f5cccda8631ab
parent 3a7cda6054cd6374b0b18b72e71404b5ca7b2155
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:44:58 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:55 +0100

 include/linux/netfilter/nf_conntrack_sip.h |    5 +-
 net/ipv4/netfilter/nf_nat_sip.c            |   46 +++++++++++---------
 net/netfilter/nf_conntrack_sip.c           |   64 ++++++++++++++++++++++------
 3 files changed, 77 insertions(+), 38 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +3 -2
index 9131cbc..480b26f 100644
@@ -6,8 +6,6 @@
 #define SIP_TIMEOUT	3600
 
 enum sip_header_pos {
-	POS_REG_REQ_URI,
-	POS_REQ_URI,
 	POS_FROM,
 	POS_TO,
 	POS_VIA,
@@ -59,6 +57,9 @@ extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 				       unsigned int *datalen,
 				       struct nf_conntrack_expect *exp);
 
+extern int ct_sip_parse_request(const struct nf_conn *ct,
+				const char *dptr, unsigned int datalen,
+				unsigned int *matchoff, unsigned int *matchlen);
 extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
                            size_t dlen, unsigned int *matchoff,
                            unsigned int *matchlen, enum sip_header_pos pos);
net/ipv4/netfilter/nf_nat_sip.c +24 -22

75 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +50 -14

82 lines not on this page · raw message

#19 lore raw

PATCH 15/32 : nf_conntrack_sip: parse SIP headers properly

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: parse SIP headers properly

Introduce new function for SIP header parsing that properly deals with continuation lines and whitespace in headers and use it.

---
commit 0b864cf59cb6bfb74677aa9c631b7c8df53016a2
tree fa5dc291dbd565fc7167a3e2415e54f3aecdfd04
parent 6b8ae4462dcdaf5c0e28ea5750f391efb738fab1
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:00 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:55 +0100

 include/linux/netfilter/nf_conntrack_sip.h |   30 ++-
 net/ipv4/netfilter/nf_nat_sip.c            |   18 +-
 net/netfilter/nf_conntrack_sip.c           |  271 +++++++++++++---------------
 3 files changed, 151 insertions(+), 168 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +15 -15
index 480b26f..ccc7014 100644
@@ -5,14 +5,6 @@
 #define SIP_PORT	5060
 #define SIP_TIMEOUT	3600
 
-enum sip_header_pos {
-	POS_FROM,
-	POS_TO,
-	POS_VIA,
-	POS_CONTACT,
-	POS_CONTENT,
-};
-
 struct sip_header {
 	const char	*name;
 	const char	*cname;
@@ -36,9 +28,20 @@ struct sip_header {
 	.match_len	= (__match),					\
 }
 
+#define SIP_HDR(__name, __cname, __search, __match) \
+	__SIP_HDR(__name, __cname, __search, __match)
+
 #define SDP_HDR(__name, __search, __match) \
 	__SIP_HDR(__name, NULL, __search, __match)
 
+enum sip_header_types {
+	SIP_HDR_FROM,
+	SIP_HDR_TO,
+	SIP_HDR_CONTACT,
+	SIP_HDR_VIA,
+	SIP_HDR_CONTENT_LENGTH,
+};
+
 enum sdp_header_types {
 	SDP_HDR_UNSPEC,
 	SDP_HDR_VERSION,
@@ -60,13 +63,10 @@ extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 extern int ct_sip_parse_request(const struct nf_conn *ct,
 				const char *dptr, unsigned int datalen,
 				unsigned int *matchoff, unsigned int *matchlen);
-extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
-                           size_t dlen, unsigned int *matchoff,
-                           unsigned int *matchlen, 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,
-				 int case_sensitive);
+extern int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
+			     unsigned int dataoff, unsigned int datalen,
+			     enum sip_header_types type,
+			     unsigned int *matchoff, unsigned int *matchlen);
 
 extern int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
 				 unsigned int dataoff, unsigned int datalen,
net/ipv4/netfilter/nf_nat_sip.c +9 -9
index 60151b5..c13e438 100644
@@ -108,14 +108,14 @@ static int map_addr(struct sk_buff *skb,
 
 static int map_sip_addr(struct sk_buff *skb,
 			const char **dptr, unsigned int *datalen,
-			enum sip_header_pos pos, struct addr_map *map)
+			enum sip_header_types type, struct addr_map *map)
 {
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	unsigned int matchlen, matchoff;
 
-	if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
-			    pos) <= 0)
+	if (ct_sip_get_header(ct, *dptr, 0, *datalen, type,
+			      &matchoff, &matchlen) <= 0)
 		return 1;
 	return map_addr(skb, dptr, datalen, matchoff, matchlen, map);
 }
@@ -141,10 +141,10 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 			return NF_DROP;
 	}
 
-	if (!map_sip_addr(skb, dptr, datalen, POS_FROM, &map) ||
-	    !map_sip_addr(skb, dptr, datalen, POS_TO, &map) ||
-	    !map_sip_addr(skb, dptr, datalen, POS_VIA, &map) ||
-	    !map_sip_addr(skb, dptr, datalen, POS_CONTACT, &map))
+	if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM, &map) ||
+	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO, &map) ||
+	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_VIA, &map) ||
+	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_CONTACT, &map))
 		return NF_DROP;
 	return NF_ACCEPT;
 }
@@ -166,8 +166,8 @@ static int mangle_content_len(struct sk_buff *skb,
 	c_len = *datalen - matchoff + strlen("v=");
 
 	/* Now, update SDP length */
-	if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
-			    POS_CONTENT) <= 0)
+	if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH,
+			      &matchoff, &matchlen) <= 0)
 		return 0;
 
 	buflen = sprintf(buffer, "%u", c_len);
net/netfilter/nf_conntrack_sip.c +127 -144

302 lines not on this page · raw message

#20 lore raw

PATCH 16/32 : nf_conntrack_sip: introduce SIP-URI parsing helper

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: introduce SIP-URI parsing helper

Introduce a helper function to parse a SIP-URI in a header value, optionally iterating through all headers of this kind.

---
commit de9ecf6505dca564ede9b602715f8686e855f7bb
tree 86f40bda2cb52f719f51ffed5832f8ad629e42a1
parent 0b864cf59cb6bfb74677aa9c631b7c8df53016a2
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:02 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:55 +0100

 include/linux/netfilter/nf_conntrack_sip.h |    5 +
 net/netfilter/nf_conntrack_sip.c           |  107 ++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+), 0 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +5 -0
index ccc7014..87bc6f7 100644
@@ -67,6 +67,11 @@ extern int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
 			     unsigned int dataoff, unsigned int datalen,
 			     enum sip_header_types type,
 			     unsigned int *matchoff, unsigned int *matchlen);
+extern int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
+				   unsigned int *dataoff, unsigned int datalen,
+				   enum sip_header_types type, int *in_header,
+				   unsigned int *matchoff, unsigned int *matchlen,
+				   union nf_inet_addr *addr, __be16 *port);
 
 extern int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
 				 unsigned int dataoff, unsigned int datalen,
net/netfilter/nf_conntrack_sip.c +107 -0

119 lines not on this page · raw message

#21 lore raw

PATCH 17/32 : nf_nat_sip: get rid of text based header translation

In reply to Patrick McHardy

[NETFILTER]: nf_nat_sip: get rid of text based header translation

Use the URI parsing helper to get the numerical addresses and get rid of the text based header translation.

---
commit fc9fe43590fd51627254f5c2aab859f23976b383
tree 1948e8fc9655147f474ffbd29f0c386c08376f11
parent de9ecf6505dca564ede9b602715f8686e855f7bb
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:03 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:55 +0100

 include/linux/netfilter/nf_conntrack_sip.h |    3 +
 net/ipv4/netfilter/nf_nat_sip.c            |  100 +++++++++++-----------------
 net/netfilter/nf_conntrack_sip.c           |   27 ++++++--
 3 files changed, 62 insertions(+), 68 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +2 -1
index 87bc6f7..68a0d6a 100644
@@ -62,7 +62,8 @@ extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 
 extern int ct_sip_parse_request(const struct nf_conn *ct,
 				const char *dptr, unsigned int datalen,
-				unsigned int *matchoff, unsigned int *matchlen);
+				unsigned int *matchoff, unsigned int *matchlen,
+				union nf_inet_addr *addr, __be16 *port);
 extern int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
 			     unsigned int dataoff, unsigned int datalen,
 			     enum sip_header_types type,
net/ipv4/netfilter/nf_nat_sip.c +38 -62

146 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +22 -5
index a74d76a..f20fa2d 100644
@@ -151,10 +151,12 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
  */
 int ct_sip_parse_request(const struct nf_conn *ct,
 			 const char *dptr, unsigned int datalen,
-			 unsigned int *matchoff, unsigned int *matchlen)
+			 unsigned int *matchoff, unsigned int *matchlen,
+			 union nf_inet_addr *addr, __be16 *port)
 {
-	const char *start = dptr, *limit = dptr + datalen;
+	const char *start = dptr, *limit = dptr + datalen, *end;
 	unsigned int mlen;
+	unsigned int p;
 	int shift = 0;
 
 	/* Skip method and following whitespace */
@@ -173,10 +175,25 @@ int ct_sip_parse_request(const struct nf_conn *ct,
 		if (strnicmp(dptr, "sip:", strlen("sip:")) == 0)
 			break;
 	}
-	*matchlen = skp_epaddr_len(ct, dptr, limit, &shift);
-	if (!*matchlen)
+	if (!skp_epaddr_len(ct, dptr, limit, &shift))
 		return 0;
-	*matchoff = dptr - start + shift;
+	dptr += shift;
+
+	if (!parse_addr(ct, dptr, &end, addr, limit))
+		return -1;
+	if (end < limit && *end == ':') {
+		end++;
+		p = simple_strtoul(end, (char **)&end, 10);
+		if (p < 1024 || p > 65535)
+			return -1;
+		*port = htons(p);
+	} else
+		*port = htons(SIP_PORT);
+
+	if (end == dptr)
+		return 0;
+	*matchoff = dptr - start;
+	*matchlen = end - dptr;
 	return 1;
 }
 EXPORT_SYMBOL_GPL(ct_sip_parse_request);
#22 lore raw

PATCH 18/32 : nf_conntrack_sip: move SDP parsing to seperate function

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: move SDP parsing to seperate function

---
commit 19639f6bcaed278e3fbc60d69f573e5c117bc4f2
tree aa2dfd07bf03862400f034b44af3874449b92d52
parent fc9fe43590fd51627254f5c2aab859f23976b383
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:05 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:56 +0100

 net/netfilter/nf_conntrack_sip.c |   84 +++++++++++++++++++-------------------
 1 files changed, 43 insertions(+), 41 deletions(-)
net/netfilter/nf_conntrack_sip.c +43 -41
index f20fa2d..96bedb5 100644
@@ -565,19 +565,49 @@ static int set_expected_rtp(struct sk_buff *skb,
 	return ret;
 }
 
+static int process_sdp(struct sk_buff *skb,
+		       const char **dptr, unsigned int *datalen)
+{
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+	unsigned int matchoff, matchlen;
+	union nf_inet_addr addr;
+	unsigned int port;
+	enum sdp_header_types type;
+
+	/* Get address and port from SDP packet. */
+	type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
+				   SDP_HDR_CONNECTION_IP6;
+
+	if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
+				  type, SDP_HDR_UNSPEC,
+				  &matchoff, &matchlen) <= 0)
+		return NF_ACCEPT;
+
+	/* We'll drop only if there are parse problems. */
+	if (!parse_addr(ct, *dptr + matchoff, NULL, &addr, *dptr + *datalen))
+		return NF_DROP;
+
+	if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
+				  SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
+				  &matchoff, &matchlen) <= 0)
+		return NF_ACCEPT;
+
+	port = simple_strtoul(*dptr + matchoff, NULL, 10);
+	if (port < 1024 || port > 65535)
+		return NF_DROP;
+
+	return set_expected_rtp(skb, dptr, datalen, &addr, htons(port));
+}
+
 static int sip_help(struct sk_buff *skb,
 		    unsigned int protoff,
 		    struct nf_conn *ct,
 		    enum ip_conntrack_info ctinfo)
 {
-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
-	union nf_inet_addr addr;
 	unsigned int dataoff, datalen;
 	const char *dptr;
-	int ret = NF_ACCEPT;
-	unsigned int matchoff, matchlen;
-	u_int16_t port;
-	enum sdp_header_types type;
 	typeof(nf_nat_sip_hook) nf_nat_sip;
 
 	/* No Data ? */
@@ -591,56 +621,28 @@ static int sip_help(struct sk_buff *skb,
 		dptr = skb->data + dataoff;
 	else {
 		pr_debug("Copy of skbuff not supported yet.\n");
-		goto out;
+		return NF_ACCEPT;
 	}
 
 	nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
 	if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
-		if (!nf_nat_sip(skb, &dptr, &datalen)) {
-			ret = NF_DROP;
-			goto out;
-		}
+		if (!nf_nat_sip(skb, &dptr, &datalen))
+			return NF_DROP;
 	}
 
 	datalen = skb->len - dataoff;
 	if (datalen < strlen("SIP/2.0 200"))
-		goto out;
+		return NF_ACCEPT;
 
 	/* RTP info only in some SDP pkts */
 	if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 &&
 	    strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 &&
 	    strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 0 &&
 	    strnicmp(dptr, "SIP/2.0 183", strlen("SIP/2.0 183")) != 0 &&
-	    strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) {
-		goto out;
-	}
-	/* Get address and port from SDP packet. */
-	type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
-				   SDP_HDR_CONNECTION_IP6;
-	if (ct_sip_get_sdp_header(ct, dptr, 0, datalen, type, SDP_HDR_UNSPEC,
-				  &matchoff, &matchlen) > 0) {
+	    strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0)
+		return NF_ACCEPT;
 
-		/* We'll drop only if there are parse problems. */
-		if (!parse_addr(ct, dptr + matchoff, NULL, &addr,
-				dptr + datalen)) {
-			ret = NF_DROP;
-			goto out;
-		}
-		if (ct_sip_get_sdp_header(ct, dptr, 0, datalen,
-					  SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
-					  &matchoff, &matchlen) > 0) {
-
-			port = simple_strtoul(dptr + matchoff, NULL, 10);
-			if (port < 1024) {
-				ret = NF_DROP;
-				goto out;
-			}
-			ret = set_expected_rtp(skb, &dptr, &datalen,
-					       &addr, htons(port));
-		}
-	}
-out:
-	return ret;
+	return process_sdp(skb, &dptr, &datalen);
 }
 
 static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;
#23 lore raw

PATCH 19/32 : nf_conntrack_sip: support method specific request/response handling

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: support method specific request/response handling

Add support for per-method request/response handlers and perform SDP parsing for INVITE/UPDATE requests and for all informational and successful responses.

---
commit 607087bf4071e8b15660d0ef2dbed696697a4516
tree cdebc3c60b5346536a993586c2004d7215d4f5ed
parent 19639f6bcaed278e3fbc60d69f573e5c117bc4f2
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:06 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:56 +0100

 include/linux/netfilter/nf_conntrack_sip.h |   20 +++++
 net/netfilter/nf_conntrack_sip.c           |  107 +++++++++++++++++++++++++---
 2 files changed, 117 insertions(+), 10 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +20 -0
index 68a0d6a..da93e80 100644
@@ -5,6 +5,25 @@
 #define SIP_PORT	5060
 #define SIP_TIMEOUT	3600
 
+struct sip_handler {
+	const char	*method;
+	unsigned int	len;
+	int		(*request)(struct sk_buff *skb,
+				   const char **dptr, unsigned int *datalen,
+				   unsigned int cseq);
+	int		(*response)(struct sk_buff *skb,
+				    const char **dptr, unsigned int *datalen,
+				    unsigned int cseq, unsigned int code);
+};
+
+#define SIP_HANDLER(__method, __request, __response)			\
+{									\
+	.method		= (__method),					\
+	.len		= sizeof(__method) - 1,				\
+	.request	= (__request),					\
+	.response	= (__response),					\
+}
+
 struct sip_header {
 	const char	*name;
 	const char	*cname;
@@ -35,6 +54,7 @@ struct sip_header {
 	__SIP_HDR(__name, NULL, __search, __match)
 
 enum sip_header_types {
+	SIP_HDR_CSEQ,
 	SIP_HDR_FROM,
 	SIP_HDR_TO,
 	SIP_HDR_CONTACT,
net/netfilter/nf_conntrack_sip.c +97 -10

131 lines not on this page · raw message

#24 lore raw

PATCH 20/32 : nf_conntrack_sip: perform NAT after parsing

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: perform NAT after parsing

Perform NAT last after parsing the packet. This makes no difference currently, but is needed when dealing with registrations to make sure we seen the unNATed addresses.

---
commit bbec485758c30e4c7bc04dbc387ed9cea676bc24
tree bb37b6940482c64c306f55c1aec3fd8103e7c5a4
parent 607087bf4071e8b15660d0ef2dbed696697a4516
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:08 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:56 +0100

 net/ipv4/netfilter/nf_nat_sip.c  |    3 ---
 net/netfilter/nf_conntrack_sip.c |   19 +++++++++++--------
 2 files changed, 11 insertions(+), 11 deletions(-)
net/ipv4/netfilter/nf_nat_sip.c +0 -3
index 5b4a5cd..b442810 100644
@@ -104,9 +104,6 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 	union nf_inet_addr addr;
 	__be16 port;
 
-	if (*datalen < strlen("SIP/2.0"))
-		return NF_ACCEPT;
-
 	/* Basic rules: requests and responses. */
 	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
 		if (ct_sip_parse_request(ct, *dptr, *datalen,
net/netfilter/nf_conntrack_sip.c +11 -8
index 1be949f..29a37d2 100644
@@ -700,6 +700,7 @@ static int sip_help(struct sk_buff *skb,
 {
 	unsigned int dataoff, datalen;
 	const char *dptr;
+	int ret;
 	typeof(nf_nat_sip_hook) nf_nat_sip;
 
 	/* No Data ? */
@@ -716,20 +717,22 @@ static int sip_help(struct sk_buff *skb,
 		return NF_ACCEPT;
 	}
 
-	nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
-	if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
-		if (!nf_nat_sip(skb, &dptr, &datalen))
-			return NF_DROP;
-	}
-
 	datalen = skb->len - dataoff;
 	if (datalen < strlen("SIP/2.0 200"))
 		return NF_ACCEPT;
 
 	if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
-		return process_sip_request(skb, &dptr, &datalen);
+		ret = process_sip_request(skb, &dptr, &datalen);
 	else
-		return process_sip_response(skb, &dptr, &datalen);
+		ret = process_sip_response(skb, &dptr, &datalen);
+
+	if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
+		nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
+		if (nf_nat_sip && !nf_nat_sip(skb, &dptr, &datalen))
+			ret = NF_DROP;
+	}
+
+	return ret;
 }
 
 static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;
#25 lore raw

PATCH 21/32 : nf_conntrack_sip: process ACK and PRACK methods

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: process ACK and PRACK methods

Both may contains SDP offers/answers.

---
commit fc1d4b6b9937a801590c454b68317734a809be0b
tree c4b167a12ff72abae20998cb0be31157306b4ba8
parent bbec485758c30e4c7bc04dbc387ed9cea676bc24
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:09 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:56 +0100

 net/netfilter/nf_conntrack_sip.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
net/netfilter/nf_conntrack_sip.c +13 -0
index 29a37d2..71f744a 100644
@@ -624,9 +624,22 @@ static int process_update_response(struct sk_buff *skb,
 	return NF_ACCEPT;
 }
 
+static int process_prack_response(struct sk_buff *skb,
+				  const char **dptr, unsigned int *datalen,
+				  unsigned int cseq, unsigned int code)
+{
+	if ((code >= 100 && code <= 199) ||
+	    (code >= 200 && code <= 299))
+		return process_sdp(skb, dptr, datalen, cseq);
+
+	return NF_ACCEPT;
+}
+
 static const struct sip_handler sip_handlers[] = {
 	SIP_HANDLER("INVITE", process_sdp, process_invite_response),
 	SIP_HANDLER("UPDATE", process_sdp, process_update_response),
+	SIP_HANDLER("ACK", process_sdp, NULL),
+	SIP_HANDLER("PRACK", process_sdp, process_prack_response),
 };
 
 static int process_sip_response(struct sk_buff *skb,
#26 lore raw

PATCH 22/32 : nf_conntrack_sip: flush expectations on call termination

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: flush expectations on call termination

Flush the RTP expectations we've created when a call is hung up or terminated otherwise.

---
commit 26599b7c1bd613fbb4f397ebfb64fd01a5f34068
tree 70f97fa632aa7a92787d0e8e527269099fb04769
parent fc1d4b6b9937a801590c454b68317734a809be0b
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:11 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:57 +0100

 net/netfilter/nf_conntrack_sip.c |   52 +++++++++++++++++++++++++++++++++++---
 1 files changed, 48 insertions(+), 4 deletions(-)
net/netfilter/nf_conntrack_sip.c +48 -4
index 71f744a..8e7e5b4 100644
@@ -17,6 +17,7 @@
 #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 <linux/netfilter/nf_conntrack_sip.h>
@@ -533,6 +534,22 @@ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
 }
 EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header);
 
+static void flush_expectations(struct nf_conn *ct)
+{
+	struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n, *next;
+
+	spin_lock_bh(&nf_conntrack_lock);
+	hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
+		if (!del_timer(&exp->timeout))
+			continue;
+		nf_ct_unlink_expect(exp);
+		nf_ct_expect_put(exp);
+	}
+	spin_unlock_bh(&nf_conntrack_lock);
+}
+
 static int set_expected_rtp(struct sk_buff *skb,
 			    const char **dptr, unsigned int *datalen,
 			    union nf_inet_addr *addr, __be16 port)
@@ -606,32 +623,58 @@ static int process_invite_response(struct sk_buff *skb,
 				   const char **dptr, unsigned int *datalen,
 				   unsigned int cseq, unsigned int code)
 {
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+
 	if ((code >= 100 && code <= 199) ||
 	    (code >= 200 && code <= 299))
 		return process_sdp(skb, dptr, datalen, cseq);
-
-	return NF_ACCEPT;
+	else {
+		flush_expectations(ct);
+		return NF_ACCEPT;
+	}
 }
 
 static int process_update_response(struct sk_buff *skb,
 				   const char **dptr, unsigned int *datalen,
 				   unsigned int cseq, unsigned int code)
 {
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+
 	if ((code >= 100 && code <= 199) ||
 	    (code >= 200 && code <= 299))
 		return process_sdp(skb, dptr, datalen, cseq);
-
-	return NF_ACCEPT;
+	else {
+		flush_expectations(ct);
+		return NF_ACCEPT;
+	}
 }
 
 static int process_prack_response(struct sk_buff *skb,
 				  const char **dptr, unsigned int *datalen,
 				  unsigned int cseq, unsigned int code)
 {
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+
 	if ((code >= 100 && code <= 199) ||
 	    (code >= 200 && code <= 299))
 		return process_sdp(skb, dptr, datalen, cseq);
+	else {
+		flush_expectations(ct);
+		return NF_ACCEPT;
+	}
+}
+
+static int process_bye_request(struct sk_buff *skb,
+			       const char **dptr, unsigned int *datalen,
+			       unsigned int cseq)
+{
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 
+	flush_expectations(ct);
 	return NF_ACCEPT;
 }
 
@@ -640,6 +683,7 @@ static const struct sip_handler sip_handlers[] = {
 	SIP_HANDLER("UPDATE", process_sdp, process_update_response),
 	SIP_HANDLER("ACK", process_sdp, NULL),
 	SIP_HANDLER("PRACK", process_sdp, process_prack_response),
+	SIP_HANDLER("BYE", process_bye_request, NULL),
 };
 
 static int process_sip_response(struct sk_buff *skb,
#27 lore raw

PATCH 23/32 : nf_conntrack_sip: introduce URI and header parameter parsing helpers

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: introduce URI and header parameter parsing helpers

Introduce URI and header parameter parsing helpers. These are needed by the conntrack helper to parse expiration values in Contact: header parameters and by the NAT helper to properly update the Via-header rport=, received= and maddr= parameters.

---
commit 2a21cab1320505abe9059adb8d42a130ea36e15b
tree 9dd17f5ddaf115146c65f6c3c2fddbcd88ac8b27
parent 26599b7c1bd613fbb4f397ebfb64fd01a5f34068
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:13 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:57 +0100

 include/linux/netfilter/nf_conntrack_sip.h |   10 +++++
 net/netfilter/nf_conntrack_sip.c           |   58 ++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 0 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +10 -0
index da93e80..87e4028 100644
@@ -93,6 +93,16 @@ extern int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
 				   enum sip_header_types type, int *in_header,
 				   unsigned int *matchoff, unsigned int *matchlen,
 				   union nf_inet_addr *addr, __be16 *port);
+extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
+				      unsigned int dataoff, unsigned int datalen,
+				      const char *name,
+				      unsigned int *matchoff, unsigned int *matchlen,
+				      union nf_inet_addr *addr);
+extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
+					unsigned int off, unsigned int datalen,
+					const char *name,
+					unsigned int *matchoff, unsigned int *matchen,
+					unsigned int *val);
 
 extern int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
 				 unsigned int dataoff, unsigned int datalen,
net/netfilter/nf_conntrack_sip.c +58 -0

64 lines not on this page · raw message

#28 lore raw

PATCH 24/32 : nf_nat_sip: translate all Via headers

In reply to Patrick McHardy

[NETFILTER]: nf_nat_sip: translate all Via headers

Update maddr=, received= and rport= Via-header parameters refering to the signalling connection.

---
commit eda29246d061965c8943f1a5954b056b3dc189fa
tree 958772517ac6a2e081c15db10e77c171c508fd8a
parent 2a21cab1320505abe9059adb8d42a130ea36e15b
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:14 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:57 +0100

 net/ipv4/netfilter/nf_nat_sip.c |   74 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 73 insertions(+), 1 deletions(-)
net/ipv4/netfilter/nf_nat_sip.c +73 -1
index b442810..71a4adc 100644
@@ -100,9 +100,11 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 {
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 	unsigned int matchoff, matchlen;
 	union nf_inet_addr addr;
 	__be16 port;
+	int request;
 
 	/* Basic rules: requests and responses. */
 	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
@@ -112,11 +114,81 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 		    !map_addr(skb, dptr, datalen, matchoff, matchlen,
 			      &addr, port))
 			return NF_DROP;
+		request = 1;
+	} else
+		request = 0;
+
+	/* Translate topmost Via header and parameters */
+	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
+				    SIP_HDR_VIA, NULL, &matchoff, &matchlen,
+				    &addr, &port) > 0) {
+		unsigned int matchend, poff, plen, buflen, n;
+		char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+
+		/* We're only interested in headers related to this
+		 * connection */
+		if (request) {
+			if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip ||
+			    port != ct->tuplehash[dir].tuple.src.u.udp.port)
+				goto next;
+		} else {
+			if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip ||
+			    port != ct->tuplehash[dir].tuple.dst.u.udp.port)
+				goto next;
+		}
+
+		if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
+			      &addr, port))
+			return NF_DROP;
+
+		matchend = matchoff + matchlen;
+
+		/* The maddr= parameter (RFC 2361) specifies where to send
+		 * the reply. */
+		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
+					       "maddr=", &poff, &plen,
+					       &addr) > 0 &&
+		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
+		    addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
+			__be32 ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+			buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+			if (!mangle_packet(skb, dptr, datalen, poff, plen,
+					   buffer, buflen))
+				return NF_DROP;
+		}
+
+		/* The received= parameter (RFC 2361) contains the address
+		 * from which the server received the request. */
+		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
+					       "received=", &poff, &plen,
+					       &addr) > 0 &&
+		    addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
+		    addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
+			__be32 ip = ct->tuplehash[!dir].tuple.src.u3.ip;
+			buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+			if (!mangle_packet(skb, dptr, datalen, poff, plen,
+					   buffer, buflen))
+				return NF_DROP;
+		}
+
+		/* The rport= parameter (RFC 3581) contains the port number
+		 * from which the server received the request. */
+		if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen,
+						 "rport=", &poff, &plen,
+						 &n) > 0 &&
+		    htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port &&
+		    htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
+			__be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
+			buflen = sprintf(buffer, "%u", ntohs(p));
+			if (!mangle_packet(skb, dptr, datalen, poff, plen,
+					   buffer, buflen))
+				return NF_DROP;
+		}
 	}
 
+next:
 	if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) ||
 	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO) ||
-	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_VIA) ||
 	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_CONTACT))
 		return NF_DROP;
 	return NF_ACCEPT;
#29 lore raw

PATCH 25/32 : nf_nat_sip: translate all Contact headers

In reply to Patrick McHardy

[NETFILTER]: nf_nat_sip: translate all Contact headers

The SIP message may contain multiple Contact: addresses referring to the NATed endpoint, translate all of them.

---
commit 8f15ab436de825574920db877a18917979712df4
tree 062b48ee051c4599b0425722c389c6eea4426b5c
parent eda29246d061965c8943f1a5954b056b3dc189fa
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:16 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:58 +0100

 net/ipv4/netfilter/nf_nat_sip.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)
net/ipv4/netfilter/nf_nat_sip.c +15 -4
index 71a4adc..b443618 100644
@@ -101,10 +101,10 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-	unsigned int matchoff, matchlen;
+	unsigned int dataoff, matchoff, matchlen;
 	union nf_inet_addr addr;
 	__be16 port;
-	int request;
+	int request, in_header;
 
 	/* Basic rules: requests and responses. */
 	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
@@ -187,9 +187,20 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
 	}
 
 next:
+	/* Translate Contact headers */
+	dataoff = 0;
+	in_header = 0;
+	while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen,
+				       SIP_HDR_CONTACT, &in_header,
+				       &matchoff, &matchlen,
+				       &addr, &port) > 0) {
+		if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
+			      &addr, port))
+			return NF_DROP;
+	}
+
 	if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) ||
-	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO) ||
-	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_CONTACT))
+	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO))
 		return NF_DROP;
 	return NF_ACCEPT;
 }
#30 lore raw

PATCH 26/32 : nf_conntrack_sip: create signalling expectations

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: create signalling expectations

Create expectations for incoming signalling connections when seeing a REGISTER request. This is needed when the registrar uses a different source port number for signalling messages and for receiving incoming calls from other endpoints than the registrar.

---
commit ddd1dea3c44ea5bfd6d63048ad5013f27c76136a
tree 71939d7d4cc84e8a28b4510ebe0f4e15a3e7011e
parent 8f15ab436de825574920db877a18917979712df4
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:17 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:58 +0100

 include/linux/netfilter/nf_conntrack_sip.h |   18 ++
 include/net/netfilter/nf_conntrack.h       |    4 
 net/ipv4/netfilter/nf_nat_sip.c            |  111 +++++++++++--
 net/netfilter/nf_conntrack_sip.c           |  232 +++++++++++++++++++++++++++-
 4 files changed, 332 insertions(+), 33 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +18 -0
index 87e4028..7cc84ed 100644
@@ -5,6 +5,17 @@
 #define SIP_PORT	5060
 #define SIP_TIMEOUT	3600
 
+struct nf_ct_sip_master {
+	unsigned int	register_cseq;
+};
+
+enum sip_expectation_classes {
+	SIP_EXPECT_SIGNALLING,
+	SIP_EXPECT_AUDIO,
+	__SIP_EXPECT_MAX
+};
+#define SIP_EXPECT_MAX	(__SIP_EXPECT_MAX - 1)
+
 struct sip_handler {
 	const char	*method;
 	unsigned int	len;
@@ -59,6 +70,7 @@ enum sip_header_types {
 	SIP_HDR_TO,
 	SIP_HDR_CONTACT,
 	SIP_HDR_VIA,
+	SIP_HDR_EXPIRES,
 	SIP_HDR_CONTENT_LENGTH,
 };
 
@@ -75,6 +87,12 @@ enum sdp_header_types {
 extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
 				       const char **dptr,
 				       unsigned int *datalen);
+extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
+					      const char **dptr,
+					      unsigned int *datalen,
+					      struct nf_conntrack_expect *exp,
+					      unsigned int matchoff,
+					      unsigned int matchlen);
 extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 				       const char **dptr,
 				       unsigned int *datalen,
include/net/netfilter/nf_conntrack.h +3 -1
index 9228771..4a4f870 100644
@@ -46,6 +46,7 @@ union nf_conntrack_expect_proto {
 #include <linux/netfilter/nf_conntrack_pptp.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
 #include <linux/netfilter/nf_conntrack_sane.h>
+#include <linux/netfilter/nf_conntrack_sip.h>
 
 /* per conntrack: application helper private data */
 union nf_conntrack_help {
@@ -54,6 +55,7 @@ union nf_conntrack_help {
 	struct nf_ct_pptp_master ct_pptp_info;
 	struct nf_ct_h323_master ct_h323_info;
 	struct nf_ct_sane_master ct_sane_info;
+	struct nf_ct_sip_master ct_sip_info;
 };
 
 #include <linux/types.h>
@@ -76,7 +78,7 @@ do {									\
 struct nf_conntrack_helper;
 
 /* Must be kept in sync with the classes defined by helpers */
-#define NF_CT_MAX_EXPECT_CLASSES	1
+#define NF_CT_MAX_EXPECT_CLASSES	2
 
 /* nf_conn feature for connections that have a helper */
 struct nf_conn_help {
net/ipv4/netfilter/nf_nat_sip.c +89 -22

143 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +222 -10

314 lines not on this page · raw message

#31 lore raw

PATCH 27/32 : nf_conntrack_sip: allow media expectations with wildcard source address

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: allow media expectations with wildcard source address

Media streams can come from anywhere, add a module parameter which controls whether wildcard expectations or expectations between the two signalling endpoints are created.

Since the same media description sent on multiple connections may results in multiple identical expections when using a wildcard source, we need to check whether a similar expectation already exists for a different connection before attempting to register it.

---
commit 61ca069c85c8b4a110143b1a1ae3263d6dd60945
tree 09a09361781b17e5bbf9bde939eab99656761b0a
parent ddd1dea3c44ea5bfd6d63048ad5013f27c76136a
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:19 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:58 +0100

 net/netfilter/nf_conntrack_sip.c |   45 +++++++++++++++++++++++++++++++++++---
 1 files changed, 41 insertions(+), 4 deletions(-)
net/netfilter/nf_conntrack_sip.c +41 -4
index 043aa55..813aa8c 100644
@@ -42,6 +42,11 @@ module_param(sip_direct_signalling, int, 0600);
 MODULE_PARM_DESC(sip_direct_signalling, "expect incoming calls from registrar "
 					"only (default 1)");
 
+static int sip_direct_media __read_mostly = 1;
+module_param(sip_direct_media, int, 0600);
+MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
+				   "endpoints only (default 1)");
+
 unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
 				const char **dptr,
 				unsigned int *datalen) __read_mostly;
@@ -656,21 +661,53 @@ static void flush_expectations(struct nf_conn *ct, bool media)
 
 static int set_expected_rtp(struct sk_buff *skb,
 			    const char **dptr, unsigned int *datalen,
-			    union nf_inet_addr *addr, __be16 port)
+			    union nf_inet_addr *daddr, __be16 port)
 {
 	struct nf_conntrack_expect *exp;
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	union nf_inet_addr *saddr;
+	struct nf_conntrack_tuple tuple;
 	int family = ct->tuplehash[!dir].tuple.src.l3num;
-	int ret;
+	int skip_expect = 0, ret;
 	typeof(nf_nat_sdp_hook) nf_nat_sdp;
 
+	saddr = NULL;
+	if (sip_direct_media) {
+		if (!nf_inet_addr_cmp(daddr, &ct->tuplehash[dir].tuple.src.u3))
+			return NF_ACCEPT;
+		saddr = &ct->tuplehash[!dir].tuple.src.u3;
+	}
+
+	/* We need to check whether the registration exists before attempting
+	 * to register it since we can see the same media description multiple
+	 * times on different connections in case multiple endpoints receive
+	 * the same call.
+	 */
+	memset(&tuple, 0, sizeof(tuple));
+	if (saddr)
+		tuple.src.u3 = *saddr;
+	tuple.src.l3num		= family;
+	tuple.dst.protonum	= IPPROTO_UDP;
+	tuple.dst.u3		= *daddr;
+	tuple.dst.u.udp.port	= port;
+
+	rcu_read_lock();
+	exp = __nf_ct_expect_find(&tuple);
+	if (exp && exp->master != ct &&
+	    nfct_help(exp->master)->helper == nfct_help(ct)->helper &&
+	    exp->class == SIP_EXPECT_AUDIO)
+		skip_expect = 1;
+	rcu_read_unlock();
+
+	if (skip_expect)
+		return NF_ACCEPT;
+
 	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL)
 		return NF_DROP;
-	nf_ct_expect_init(exp, SIP_EXPECT_AUDIO, family,
-			  &ct->tuplehash[!dir].tuple.src.u3, addr,
+	nf_ct_expect_init(exp, SIP_EXPECT_AUDIO, family, saddr, daddr,
 			  IPPROTO_UDP, NULL, &port);
 
 	nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
#32 lore raw

PATCH 28/32 : nf_conntrack_sip: create RTCP expectations

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: create RTCP expectations

Create expectations for the RTCP connections in addition to RTP connections.

---
commit bd085bafc458c50d639e3997fdff52fc457173ba
tree a4874ee96d70bb10f8dfadd1838065616dad240c
parent 61ca069c85c8b4a110143b1a1ae3263d6dd60945
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:20 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:58 +0100

 include/linux/netfilter/nf_conntrack_sip.h |    3 +
 net/ipv4/netfilter/nf_nat_sip.c            |   42 +++++++++++++-------
 net/netfilter/nf_conntrack_sip.c           |   58 ++++++++++++++++++----------
 3 files changed, 66 insertions(+), 37 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +2 -1
index 7cc84ed..6ddf95f 100644
@@ -96,7 +96,8 @@ extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
 extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 				       const char **dptr,
 				       unsigned int *datalen,
-				       struct nf_conntrack_expect *exp);
+				       struct nf_conntrack_expect *rtp_exp,
+				       struct nf_conntrack_expect *rtcp_exp);
 
 extern int ct_sip_parse_request(const struct nf_conn *ct,
 				const char *dptr, unsigned int datalen,
net/ipv4/netfilter/nf_nat_sip.c +26 -16

64 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +38 -20

100 lines not on this page · raw message

#33 lore raw

PATCH 29/32 : nf_nat_sip: split up SDP mangling

In reply to Patrick McHardy

[NETFILTER]: nf_nat_sip: split up SDP mangling

The SDP connection addresses may be contained in the payload multiple times (in the session description and/or once per media description), currently only the session description is properly updated. Split up SDP mangling so the function setting up expectations only updates the media port, update connection addresses from media descriptions while parsing them and at the end update the session description when the final addresses are known.

---
commit 1f7d1e1804a04963595888f07e17453d2d5996f4
tree 8de0e5051019fd66f1ca956efd63b6465d4fae7d
parent bd085bafc458c50d639e3997fdff52fc457173ba
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:22 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:59 +0100

 include/linux/netfilter/nf_conntrack_sip.h |   25 ++++-
 net/ipv4/netfilter/nf_nat_sip.c            |  121 +++++++++++++++++-------
 net/netfilter/nf_conntrack_sip.c           |  142 +++++++++++++++++++++++-----
 3 files changed, 219 insertions(+), 69 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +20 -5
index 6ddf95f..eca3ad3 100644
@@ -93,11 +93,26 @@ extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
 					      struct nf_conntrack_expect *exp,
 					      unsigned int matchoff,
 					      unsigned int matchlen);
-extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
-				       const char **dptr,
-				       unsigned int *datalen,
-				       struct nf_conntrack_expect *rtp_exp,
-				       struct nf_conntrack_expect *rtcp_exp);
+extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
+					    const char **dptr,
+					    unsigned int dataoff,
+					    unsigned int *datalen,
+					    enum sdp_header_types type,
+					    enum sdp_header_types term,
+					    const union nf_inet_addr *addr);
+extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
+					       const char **dptr,
+					       unsigned int dataoff,
+					       unsigned int *datalen,
+					       const union nf_inet_addr *addr);
+extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
+					     const char **dptr,
+					     unsigned int *datalen,
+					     struct nf_conntrack_expect *rtp_exp,
+					     struct nf_conntrack_expect *rtcp_exp,
+					     unsigned int mediaoff,
+					     unsigned int medialen,
+					     union nf_inet_addr *rtp_addr);
 
 extern int ct_sip_parse_request(const struct nf_conn *ct,
 				const char *dptr, unsigned int datalen,
net/ipv4/netfilter/nf_nat_sip.c +84 -37

192 lines not on this page · raw message

net/netfilter/nf_conntrack_sip.c +115 -27

190 lines not on this page · raw message

#34 lore raw

PATCH 30/32 : nf_conntrack_sip: support multiple media channels

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: support multiple media channels

Add support for multiple media channels and use it to create expectations for video streams when present.

---
commit 1c04320897b232a4b7dd89c123469f6c6de911ae
tree 74dd9d95ee604f0b907b138d2a1c214cf87a95e6
parent 1f7d1e1804a04963595888f07e17453d2d5996f4
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:24 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:59 +0100

 include/linux/netfilter/nf_conntrack_sip.h |   14 +++
 include/net/netfilter/nf_conntrack.h       |    2 
 net/netfilter/nf_conntrack_sip.c           |  121 +++++++++++++++++++++-------
 3 files changed, 105 insertions(+), 32 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +14 -0
index eca3ad3..71fa3eb 100644
@@ -12,10 +12,24 @@ struct nf_ct_sip_master {
 enum sip_expectation_classes {
 	SIP_EXPECT_SIGNALLING,
 	SIP_EXPECT_AUDIO,
+	SIP_EXPECT_VIDEO,
 	__SIP_EXPECT_MAX
 };
 #define SIP_EXPECT_MAX	(__SIP_EXPECT_MAX - 1)
 
+struct sdp_media_type {
+	const char			*name;
+	unsigned int			len;
+	enum sip_expectation_classes	class;
+};
+
+#define SDP_MEDIA_TYPE(__name, __class)					\
+{									\
+	.name	= (__name),						\
+	.len	= sizeof(__name) - 1,					\
+	.class	= (__class),						\
+}
+
 struct sip_handler {
 	const char	*method;
 	unsigned int	len;
include/net/netfilter/nf_conntrack.h +1 -1
index 4a4f870..a3567a7 100644
@@ -78,7 +78,7 @@ do {									\
 struct nf_conntrack_helper;
 
 /* Must be kept in sync with the classes defined by helpers */
-#define NF_CT_MAX_EXPECT_CLASSES	2
+#define NF_CT_MAX_EXPECT_CLASSES	3
 
 /* nf_conn feature for connections that have a helper */
 struct nf_conn_help {
net/netfilter/nf_conntrack_sip.c +90 -31

195 lines not on this page · raw message

#35 lore raw

PATCH 31/32 : nf_conntrack_sip: RTP routing optimization

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: RTP routing optimization

Optimize call routing between NATed endpoints: when an external registrar sends a media description that contains an existing RTP expectation from a different SNATed connection, the gatekeeper is trying to route the call directly between the two endpoints.

We assume both endpoints can reach each other directly and "un-NAT" the addresses, which makes the media stream go between the two endpoints directly.

---
commit 5b4954e2047534f6f4347597a68cb7f09a3389ea
tree 22ea8eda5dde1d76c2a11adc273c16691fcfdb90
parent 1c04320897b232a4b7dd89c123469f6c6de911ae
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 12:45:25 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:09:59 +0100

 include/linux/netfilter/nf_conntrack_sip.h |    6 +++
 net/ipv4/netfilter/nf_nat_sip.c            |    3 +
 net/netfilter/nf_conntrack_sip.c           |   59 +++++++++++++++++++++++-----
 3 files changed, 58 insertions(+), 10 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +6 -0
index 71fa3eb..5da04e5 100644
@@ -114,6 +114,12 @@ extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
 					    enum sdp_header_types type,
 					    enum sdp_header_types term,
 					    const union nf_inet_addr *addr);
+extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
+					    const char **dptr,
+					    unsigned int *datalen,
+					    unsigned int matchoff,
+					    unsigned int matchlen,
+					    u_int16_t port);
 extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
 					       const char **dptr,
 					       unsigned int dataoff,
net/ipv4/netfilter/nf_nat_sip.c +3 -0
index 4429069..bcddccd 100644
@@ -461,6 +461,7 @@ static void __exit nf_nat_sip_fini(void)
 	rcu_assign_pointer(nf_nat_sip_hook, NULL);
 	rcu_assign_pointer(nf_nat_sip_expect_hook, NULL);
 	rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL);
+	rcu_assign_pointer(nf_nat_sdp_port_hook, NULL);
 	rcu_assign_pointer(nf_nat_sdp_session_hook, NULL);
 	rcu_assign_pointer(nf_nat_sdp_media_hook, NULL);
 	synchronize_rcu();
@@ -471,11 +472,13 @@ static int __init nf_nat_sip_init(void)
 	BUG_ON(nf_nat_sip_hook != NULL);
 	BUG_ON(nf_nat_sip_expect_hook != NULL);
 	BUG_ON(nf_nat_sdp_addr_hook != NULL);
+	BUG_ON(nf_nat_sdp_port_hook != NULL);
 	BUG_ON(nf_nat_sdp_session_hook != NULL);
 	BUG_ON(nf_nat_sdp_media_hook != NULL);
 	rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
 	rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect);
 	rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
+	rcu_assign_pointer(nf_nat_sdp_port_hook, ip_nat_sdp_port);
 	rcu_assign_pointer(nf_nat_sdp_session_hook, ip_nat_sdp_session);
 	rcu_assign_pointer(nf_nat_sdp_media_hook, ip_nat_sdp_media);
 	return 0;
net/netfilter/nf_conntrack_sip.c +49 -10

97 lines not on this page · raw message

#36 lore raw

PATCH 32/32 : nf_conntrack_sip: update copyright

In reply to Patrick McHardy

[NETFILTER]: nf_conntrack_sip: update copyright

---
commit 5ada5a1adfeb1f7fdad61d02add18a4e47750b30
tree c41e7b0d5568d855a6afecdd92d0c244478a6c94
parent 5b4954e2047534f6f4347597a68cb7f09a3389ea
author Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:43:46 +0100 committer Patrick McHardy <[email protected]> Tue, 25 Mar 2008 14:43:46 +0100

 net/ipv4/netfilter/nf_nat_sip.c  |    2 ++
 net/netfilter/nf_conntrack_sip.c |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)
net/ipv4/netfilter/nf_nat_sip.c +2 -0
index bcddccd..4334d5c 100644
@@ -2,6 +2,8 @@
  *
  * (C) 2005 by Christian Hentschel <[email protected]>
  * based on RR's ip_nat_ftp.c and other modules.
+ * (C) 2007 United Security Providers
+ * (C) 2007, 2008 Patrick McHardy <[email protected]>
  *
  * 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
net/netfilter/nf_conntrack_sip.c +2 -0
index 57de22c..da5dec6 100644
@@ -2,6 +2,8 @@
  *
  * (C) 2005 by Christian Hentschel <[email protected]>
  * based on RR's ip_conntrack_ftp.c and other modules.
+ * (C) 2007 United Security Providers
+ * (C) 2007, 2008 Patrick McHardy <[email protected]>
  *
  * 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
maintainer
#37 lore raw
In reply to Patrick McHardy

From: Patrick McHardy <[email protected]>
Date: Tue, 25 Mar 2008 15:14:50 +0100 (MET)

Quoted 4 lines

these patches for 2.6.26 contain a large update for the SIP connection tracking helper, fixing a number of issues with the current helper and improving robustness. A rough overview of the patches follows, the details are in the individual changelog entries:

All applied and pushed out to net-2.6.26, thanks!