All of lore.kernel.org
 help / color / mirror / Atom feed
* lockhelp.h missing
@ 2005-07-22  5:34 Jérôme Poulin
  2005-07-22  5:56 ` Patrick McHardy
  0 siblings, 1 reply; 7+ messages in thread
From: Jérôme Poulin @ 2005-07-22  5:34 UTC (permalink / raw)
  To: netfilter-devel

I've got latest kernel 2.6.13-r1 with andrew morton patch mm1 and
applied latest patch-o-matic-ng (2005-07-21 today) with ./runme extra
which successfully applied.

When compiling the kernel I get some bad result (quoted some errors
below) because of the lockhelp.h file missing in kernel builds greater
or equal to 2.6.12.

This error repeats for each file including ip_conntrack_mms.h after
removing lockhelp.h from the #include
---------------------
In file included from include/linux/netfilter_ipv4/ip_conntrack.h:94,
                 from net/ipv4/netfilter/ip_conntrack_h323_core.c:17:
include/linux/netfilter_ipv4/ip_conntrack_mms.h:8: warning: type
defaults to `int' in declaration of `DECLARE_LOCK_EXTERN'
include/linux/netfilter_ipv4/ip_conntrack_mms.h:8: warning: parameter
names (without types) in function declaration
include/linux/netfilter_ipv4/ip_conntrack_mms.h:8: warning: data
definition has no type or storage class
------------

Same for this one after touch-ing the file so it doesn't generate
errors about the missing #include
-----------
net/ipv4/netfilter/ip_conntrack_h323_h225.c: In function `h225_help':
net/ipv4/netfilter/ip_conntrack_h323_h225.c:382: warning: implicit
declaration of function `LOCK_BH'
net/ipv4/netfilter/ip_conntrack_h323_h225.c:382: error: `ip_h225_lock'
undeclared (first use in this function)
net/ipv4/netfilter/ip_conntrack_h323_h225.c:382: error: (Each
undeclared identifier is reported only once
net/ipv4/netfilter/ip_conntrack_h323_h225.c:382: error: for each
function it appears in.)
net/ipv4/netfilter/ip_conntrack_h323_h225.c:390: warning: implicit
declaration of function `UNLOCK_BH'
net/ipv4/netfilter/ip_conntrack_h323_h225.c: At top level:
net/ipv4/netfilter/ip_conntrack_h323_h225.c:28: warning:
'DECLARE_LOCK' declared `static' but never defined
make[3]: *** [net/ipv4/netfilter/ip_conntrack_h323_h225.o] Error 1
--------------

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

* Re: lockhelp.h missing
  2005-07-22  5:34 lockhelp.h missing Jérôme Poulin
@ 2005-07-22  5:56 ` Patrick McHardy
  2005-07-22 12:52   ` Sven Schuster
  0 siblings, 1 reply; 7+ messages in thread
From: Patrick McHardy @ 2005-07-22  5:56 UTC (permalink / raw)
  To: Jérôme Poulin; +Cc: netfilter-devel

Jérôme Poulin schrieb:
> I've got latest kernel 2.6.13-r1 with andrew morton patch mm1 and
> applied latest patch-o-matic-ng (2005-07-21 today) with ./runme extra
> which successfully applied.
> 
> When compiling the kernel I get some bad result (quoted some errors
> below) because of the lockhelp.h file missing in kernel builds greater
> or equal to 2.6.12.
> 
> This error repeats for each file including ip_conntrack_mms.h after
> removing lockhelp.h from the #include

lockhelp.h got killed, some patches in pomng still need to be updated.
I'll happily take patches ..

Regards
Patrick

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

* Re: lockhelp.h missing
  2005-07-22  5:56 ` Patrick McHardy
@ 2005-07-22 12:52   ` Sven Schuster
       [not found]     ` <debc30fc0507230238427b0290@mail.gmail.com>
  0 siblings, 1 reply; 7+ messages in thread
From: Sven Schuster @ 2005-07-22 12:52 UTC (permalink / raw)
  To: netfilter-devel


[-- Attachment #1.1: Type: text/plain, Size: 906 bytes --]


Hi Jérôme, hi Patrick,

On Fri, Jul 22, 2005 at 07:56:10AM +0200, Patrick McHardy told us:
> lockhelp.h got killed, some patches in pomng still need to be updated.
> I'll happily take patches ..

attached you'll find a patch against current pom-ng svn updating the
mms-conntrack-nat helper for linux 2.6.12. Jérôme, could you please
apply that patch with

cd /place/where/pom-ng/is
patch -p1 </location/of/mms-2.6.12.patch

then reapply that patch to your kernel, rebuild and test it?? I have
compile-tested this patch with 2.6.13-rc3-mm1 but I don't have the
possibility to test it.
If I find some more free time I'll try to take a look at the other
patchlets.


kind regards

Sven

> 
> Regards
> Patrick
> 
> 

--
Linux zion 2.6.13-rc3-mm1 #6 PREEMPT Mon Jul 18 19:42:52 CEST 2005 i686 athlon i386 GNU/Linux
14:49:02 up  6:57,  1 user,  load average: 0.01, 0.30, 0.33

[-- Attachment #1.2: mms-2.6.12.patch --]
[-- Type: text/plain, Size: 24814 bytes --]

diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd	2005-07-03 22:40:06.000000000 +0200
@@ -0,0 +1,2 @@
+	/* insert conntrack helper private data (master) here */
+	struct ip_ct_mms_master ct_mms_info;
diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2 pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2	2005-07-03 22:40:06.000000000 +0200
@@ -0,0 +1,2 @@
+/* Add protocol helper include file here */
+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_mms.h pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_mms.h
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_mms.h	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_mms.h	2005-07-22 14:02:32.000000000 +0200
@@ -0,0 +1,36 @@
+#ifndef _IP_CONNTRACK_MMS_H
+#define _IP_CONNTRACK_MMS_H
+/* MMS tracking. */
+
+#ifdef __KERNEL__
+
+extern spinlock_t ip_mms_lock;
+
+#define MMS_PORT                         1755
+#define MMS_SRV_MSG_ID                   196610
+
+#define MMS_SRV_MSG_OFFSET               36
+#define MMS_SRV_UNICODE_STRING_OFFSET    60
+#define MMS_SRV_CHUNKLENLV_OFFSET        16
+#define MMS_SRV_CHUNKLENLM_OFFSET        32
+#define MMS_SRV_MESSAGELENGTH_OFFSET     8
+
+/* This structure is per expected connection */
+struct ip_ct_mms_expect {
+	u_int32_t offset;
+	u_int32_t len;
+	u_int32_t padding;
+	u_int16_t port;
+};
+
+/* This structure exists only once per master */
+struct ip_ct_mms_master {
+};
+
+struct ip_conntrack_expect;
+extern unsigned int (*ip_nat_mms_hook)(struct sk_buff **pskb,
+				       enum ip_conntrack_info ctinfo,
+				       const struct ip_ct_mms_expect *exp_mms_info,
+				       struct ip_conntrack_expect *exp);
+#endif
+#endif /* _IP_CONNTRACK_MMS_H */
diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_mms.c pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_mms.c
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_mms.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_mms.c	2005-07-22 10:32:22.000000000 +0200
@@ -0,0 +1,352 @@
+/* MMS extension for IP connection tracking
+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
+ * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
+ *
+ * ip_conntrack_mms.c v0.3 2002-09-22
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      Module load syntax:
+ *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
+ *
+ *      Please give the ports of all MMS servers You wish to connect to.
+ *      If you don't specify ports, the default will be TCP port 1755.
+ *
+ *      More info on MMS protocol, firewalls and NAT:
+ *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
+ *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
+ *
+ *      The SDP project people are reverse-engineering MMS:
+ *      http://get.to/sdp
+ *
+ *  2005-02-13: Harald Welte <laforge@netfilter.org>
+ *  	- port to 2.6.x
+ *  	- update to work with post 2.6.11 helper API changes
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <linux/ctype.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
+
+
+#define MAX_PORTS 8
+static int ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, int, &ports_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers of MMS");
+
+static char mms_buffer[65536];
+static DEFINE_SPINLOCK(mms_buffer_lock);
+
+unsigned int (*ip_nat_mms_hook)(struct sk_buff **pskb,
+				enum ip_conntrack_info ctinfo,
+				const struct ip_ct_mms_expect *exp_mms_info,
+				struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL(ip_nat_mms_hook);
+
+#if 0 
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
+MODULE_LICENSE("GPL");
+
+/* #define isdigit(c) (c >= '0' && c <= '9') */
+
+/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
+static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
+{
+	int i;
+	for (i = 0; i < unicode_size; ++i) {
+		string[i] = (char)(unicode[i]);
+	}
+	string[unicode_size] = 0x00;
+}
+
+__inline static int atoi(char *s) 
+{
+	int i=0;
+	while (isdigit(*s)) {
+		i = i*10 + *(s++) - '0';
+	}
+	return i;
+}
+
+/* convert ip address string like "192.168.0.10" to unsigned int */
+__inline static u_int32_t asciiiptoi(char *s)
+{
+	unsigned int i, j, k;
+
+	for(i=k=0; k<3; ++k, ++s, i<<=8) {
+		i+=atoi(s);
+		for(j=0; (*(++s) != '.') && (j<3); ++j)
+			;
+	}
+	i+=atoi(s);
+	return ntohl(i);
+}
+
+int parse_mms(const char *data, 
+	      const unsigned int datalen,
+	      u_int32_t *mms_ip,
+	      u_int16_t *mms_proto,
+	      u_int16_t *mms_port,
+	      char **mms_string_b,
+	      char **mms_string_e,
+	      char **mms_padding_e)
+{
+	int unicode_size, i;
+	char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
+	char getlengthstring[28];
+	
+	for(unicode_size=0; 
+	    (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
+	    unicode_size++)
+		if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
+			return -1; /* out of bounds - incomplete packet */
+	
+	unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
+	DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
+	
+	/* IP address ? */
+	*mms_ip = asciiiptoi(tempstring+2);
+	
+	i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
+		
+	/* protocol ? */
+	if(strncmp(tempstring+3+i, "TCP", 3)==0)
+		*mms_proto = IPPROTO_TCP;
+	else if(strncmp(tempstring+3+i, "UDP", 3)==0)
+		*mms_proto = IPPROTO_UDP;
+
+	/* port ? */
+	*mms_port = atoi(tempstring+7+i);
+
+	/* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
+	   unicode string, one to the end of the string, and one to the end 
+	   of the packet, since we must keep track of the number of bytes 
+	   between end of the unicode string and the end of packet (padding) */
+	*mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
+	*mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
+	*mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
+	return 0;
+}
+
+
+/* FIXME: This should be in userspace.  Later. */
+static int help(struct sk_buff **pskb,
+		struct ip_conntrack *ct,
+		enum ip_conntrack_info ctinfo)
+{
+	int ret = NF_DROP;
+	struct tcphdr _tcph, *th;
+	char *data, *mb_ptr;
+	unsigned int datalen, dataoff;
+
+
+	//struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
+	//unsigned int tcplen = len - iph->ihl * 4;
+	//unsigned int datalen = tcplen - tcph->doff * 4;
+	int dir = CTINFO2DIR(ctinfo);
+	struct ip_conntrack_expect *exp;
+	struct ip_ct_mms_expect _emmi, *exp_mms_info = &_emmi;
+	
+	u_int32_t mms_ip;
+	u_int16_t mms_proto;
+	char mms_proto_string[8];
+	u_int16_t mms_port;
+	char *mms_string_b, *mms_string_e, *mms_padding_e;
+	     
+	/* Until there's been traffic both ways, don't look in packets. */
+	if (ctinfo != IP_CT_ESTABLISHED
+	    && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
+		DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
+		return NF_ACCEPT;
+	}
+
+	/* Not whole TCP header? */
+	th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (!th)
+		return NF_ACCEPT;
+
+	/* No data ? */
+	dataoff = (*pskb)->nh.iph->ihl*4 + th->doff*4;
+	datalen = (*pskb)->len - dataoff;
+	if (dataoff >= (*pskb)->len)
+		return NF_ACCEPT;
+
+	spin_lock_bh(&mms_buffer_lock);
+	mb_ptr = skb_header_pointer(*pskb, dataoff,
+				    (*pskb)->len - dataoff, mms_buffer);
+	BUG_ON(mb_ptr == NULL);
+
+	data = mb_ptr;
+
+#if 0
+	/* Checksum invalid?  Ignore. */
+	/* FIXME: Source route IP option packets --RR */
+	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
+	    csum_partial((char *)tcph, tcplen, 0))) {
+		DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
+		       tcph, tcplen, NIPQUAD(iph->saddr),
+		       NIPQUAD(iph->daddr));
+		return NF_ACCEPT;
+	}
+#endif
+	
+	/* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP
+	 * payload */
+
+	/* FIXME: There is an issue with only looking at this packet: before
+	 * this packet, the client has already sent a packet to the server with
+	 * the server's hostname according to the client (think of it as the
+	 * "Host: " header in HTTP/1.1). The server will break the connection
+	 * if this doesn't correspond to its own host header. The client can
+	 * also connect to an IP address; if it's the server's IP address, it
+	 * will not break the connection. When doing DNAT on a connection where
+	 * the client uses a server's IP address, the nat module should detect
+	 * this and change this string accordingly to the DNATed address. This
+	 * should probably be done by checking for an IP address, then storing
+	 * it as a member of struct ip_ct_mms_expect and checking for it in
+	 * ip_nat_mms...
+	 */
+	if ((MMS_SRV_MSG_OFFSET < datalen) && 
+	    ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
+		DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
+		       (u8)*(data+36), (u8)*(data+37), 
+		       (u8)*(data+38), (u8)*(data+39),
+		       datalen);
+		if (parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
+		             &mms_string_b, &mms_string_e, &mms_padding_e))
+			if (net_ratelimit())
+				/* FIXME: more verbose debugging ? */
+				printk(KERN_WARNING
+				       "ip_conntrack_mms: Unable to parse "
+				       "data payload\n");
+
+		sprintf(mms_proto_string, "(%u)", mms_proto);
+		DEBUGP("ip_conntrack_mms: adding %s expectation "
+		       "%u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
+		       mms_proto == IPPROTO_TCP ? "TCP"
+		       : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
+		       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
+		       NIPQUAD(mms_ip),
+		       mms_port);
+		
+		/* it's possible that the client will just ask the server to
+		 * tunnel the stream over the same TCP session (from port
+		 * 1755): there's shouldn't be a need to add an expectation in
+		 * that case, but it makes NAT packet mangling so much easier
+		 * */
+
+		DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
+
+		exp = ip_conntrack_expect_alloc();
+		if (!exp) {
+			ret = NF_DROP;
+			goto out;
+		}
+		
+		exp_mms_info->offset  = (mms_string_b - data);
+		exp_mms_info->len     = (mms_string_e  - mms_string_b);
+		exp_mms_info->padding = (mms_padding_e - mms_string_e);
+		exp_mms_info->port    = mms_port;
+		
+		DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), "
+		       "len=%d, padding=%u\n", exp->seq, (mms_string_e - data),
+		       exp_mms_info->len, exp_mms_info->padding);
+		
+		exp->tuple = ((struct ip_conntrack_tuple)
+		              { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
+		              { mms_ip,
+		                { .tcp = { (__u16) ntohs(mms_port) } },
+		                mms_proto } }
+		             );
+		exp->mask  = ((struct ip_conntrack_tuple)
+		             { { 0xFFFFFFFF, { 0 } },
+		               { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+		exp->expectfn = NULL;
+		exp->master = ct;
+
+		if (ip_nat_mms_hook)
+			ret = ip_nat_mms_hook(pskb, ctinfo, exp_mms_info, exp);
+		else if (ip_conntrack_expect_related(exp) != 0) {
+			ip_conntrack_expect_free(exp);
+			ret = NF_DROP;
+		}
+		goto out;
+	}
+out:
+	spin_unlock_bh(&mms_buffer_lock);
+	return ret;
+}
+
+static struct ip_conntrack_helper mms[MAX_PORTS];
+static char mms_names[MAX_PORTS][10];
+
+/* Not __exit: called from init() */
+static void fini(void)
+{
+	int i;
+	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+		DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
+				ports[i]);
+		ip_conntrack_helper_unregister(&mms[i]);
+	}
+}
+
+static int __init init(void)
+{
+	int i, ret;
+	char *tmpname;
+
+	if (ports[0] == 0)
+		ports[0] = MMS_PORT;
+
+	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+		memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
+		mms[i].tuple.src.u.tcp.port = htons(ports[i]);
+		mms[i].tuple.dst.protonum = IPPROTO_TCP;
+		mms[i].mask.src.u.tcp.port = 0xFFFF;
+		mms[i].mask.dst.protonum = 0xFF;
+		mms[i].max_expected = 1;
+		mms[i].timeout = 120;
+		mms[i].me = THIS_MODULE;
+		mms[i].help = help;
+
+		tmpname = &mms_names[i][0];
+		if (ports[i] == MMS_PORT)
+			sprintf(tmpname, "mms");
+		else
+			sprintf(tmpname, "mms-%d", ports[i]);
+		mms[i].name = tmpname;
+
+		DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
+				ports[i]);
+		ret = ip_conntrack_helper_register(&mms[i]);
+
+		if (ret) {
+			fini();
+			return ret;
+		}
+		ports_c++;
+	}
+	return 0;
+}
+
+module_init(init);
+module_exit(fini);
diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_mms.c pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_mms.c
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_mms.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_mms.c	2005-07-22 10:33:48.000000000 +0200
@@ -0,0 +1,195 @@
+/* MMS extension for TCP NAT alteration.
+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
+ * based on ip_nat_ftp.c and ip_nat_irc.c
+ *
+ * ip_nat_mms.c v0.3 2002-09-22
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      Module load syntax:
+ *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
+ *
+ *      Please give the ports of all MMS servers You wish to connect to.
+ *      If you don't specify ports, the default will be TCP port 1755.
+ *
+ *      More info on MMS protocol, firewalls and NAT:
+ *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
+ *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
+ *
+ *      The SDP project people are reverse-engineering MMS:
+ *      http://get.to/sdp
+ *
+ *  2005-02-13: Harald Welte <laforge@netfilter.org>
+ *  	- port to 2.6.x
+ *  	- update to work with post 2.6.11 helper API changes
+
+ */
+
+/* FIXME: issue with UDP & fragmentation with this URL: 
+   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
+   may be related to out-of-order first packets:
+   basically the expectation is set up correctly, then the server sends
+   a first UDP packet which is fragmented plus arrives out-of-order.
+   the MASQUERADING firewall with ip_nat_mms loaded responds with
+   an ICMP unreachable back to the server */
+
+#include <linux/module.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+#if 0 
+#define DEBUGP printk
+#define DUMP_BYTES(address, counter)                                \
+({                                                                  \
+	int temp_counter;                                           \
+	for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
+		DEBUGP("%u ", (u8)*(address+temp_counter));         \
+	};                                                          \
+	DEBUGP("\n");                                               \
+})
+#else
+#define DEBUGP(format, args...)
+#define DUMP_BYTES(address, counter)
+#endif
+
+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
+MODULE_LICENSE("GPL");
+
+static unsigned int mms_data_fixup(struct sk_buff **pskb,
+                          enum ip_conntrack_info ctinfo,
+			  const struct ip_ct_mms_expect *ct_mms_info,
+                          struct ip_conntrack_expect *expect)
+{
+	u_int32_t newip;
+	struct ip_conntrack *ct = expect->master;
+	struct iphdr *iph = (*pskb)->nh.iph;
+	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
+	char *data = (char *)tcph + tcph->doff * 4;
+	int i, j, k, port;
+	u_int16_t mms_proto;
+
+	u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
+	u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
+	u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
+
+	int zero_padding;
+
+	char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 
+				    (for unicode) */
+	char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
+	char proto_string[6];
+
+	/* what was the protocol again ? */
+	mms_proto = expect->tuple.dst.protonum;
+	sprintf(proto_string, "%u", mms_proto);
+	
+	DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) "
+	       "in %u, proto %s\n",
+	       expect->seq, ct_mms_info->len, ntohl(tcph->seq),
+	       mms_proto == IPPROTO_UDP ? "UDP"
+	       : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
+	
+	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+	expect->saved_proto.tcp.port = expect->tuple.dst.u.tcp.port;
+	expect->expectfn = ip_nat_follow_master;
+
+	/* Alter conntrack's expectations. */
+	for (port = ct_mms_info->port; port != 0; port++) {
+		expect->tuple.dst.u.tcp.port = htons(port);
+		if (ip_conntrack_expect_related(expect) == 0) {
+			DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n",
+				port); 
+			break;
+		}
+	}
+	
+	if (port == 0) {
+		ip_conntrack_expect_free(expect);
+		return NF_DROP;
+	}
+
+	sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
+	        NIPQUAD(newip),
+		expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
+		: expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
+		port);
+	DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
+	
+	memset(unicode_buffer, 0, sizeof(char)*75);
+
+	for (i=0; i<strlen(buffer); ++i)
+		*(unicode_buffer+i*2)=*(buffer+i);
+	
+	DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", 
+		ct_mms_info->padding, ct_mms_info->len);
+	DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", 
+		MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
+	DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
+	
+	/* add end of packet to it */
+	for (j=0; j<ct_mms_info->padding; ++j) {
+		DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
+		       i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
+		*(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
+	}
+
+	/* pad with zeroes at the end ? see explanation of weird math below */
+	zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
+	for (k=0; k<zero_padding; ++k)
+		*(unicode_buffer+i*2+j+k)= (char)0;
+	
+	DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
+	DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u "
+	       "messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM,
+	       *mms_messageLength);
+	
+	/* explanation, before I forget what I did:
+	   strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
+	   divide by 8 and add 3 to compute the mms_chunkLenLM field,
+	   but note that things may have to be padded with zeroes to align by 8 
+	   bytes, hence we add 7 and divide by 8 to get the correct length */ 
+	*mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
+	*mms_chunkLenLV    = *mms_chunkLenLM+2;
+	*mms_messageLength = *mms_chunkLenLV*8;
+	
+	DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u"
+	       " messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM,
+	       *mms_messageLength);
+	
+	ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
+	                         ct_mms_info->offset,
+	                         ct_mms_info->len + ct_mms_info->padding,
+				 unicode_buffer, strlen(buffer)*2 +
+				 ct_mms_info->padding + zero_padding);
+	DUMP_BYTES(unicode_buffer, 60);
+	
+	return NF_ACCEPT;
+}
+
+static void __exit fini(void)
+{
+	ip_nat_mms_hook = NULL;
+	synchronize_net();
+}
+
+static int __init init(void)
+{
+	BUG_ON(ip_nat_mms_hook);
+	ip_nat_mms_hook = &mms_data_fixup;
+
+	return 0;
+}
+
+module_init(init);
+module_exit(fini);
diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd	2005-07-03 22:40:06.000000000 +0200
@@ -0,0 +1,17 @@
+config IP_NF_NAT_MMS
+	tristate
+	depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
+	default IP_NF_NAT if IP_NF_MMS=y
+	default m if IP_NF_MMS=m
+
+config IP_NF_MMS
+	tristate  'MMS protocol support'
+	depends on IP_NF_CONNTRACK
+	help
+	  Tracking MMS (Microsoft Windows Media Services) connections
+	  could be problematic if random ports are used to send the
+	  streaming content. This option allows users to track streaming
+	  connections over random UDP or TCP ports.
+	
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `Y'.
diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd	2005-07-03 22:40:06.000000000 +0200
@@ -0,0 +1,2 @@
+# NAT helpers 
+obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
diff -Nrup --exclude=.svn pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd_2 pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd_2
--- pom-ng-svn/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd_2	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-edit/patchlets/mms-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd_2	2005-07-03 22:40:06.000000000 +0200
@@ -0,0 +1,2 @@
+# connection tracking helpers
+obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: lockhelp.h missing
       [not found]     ` <debc30fc0507230238427b0290@mail.gmail.com>
@ 2005-07-23 20:25       ` Sven Schuster
  2005-07-23 20:52       ` Sven Schuster
  1 sibling, 0 replies; 7+ messages in thread
From: Sven Schuster @ 2005-07-23 20:25 UTC (permalink / raw)
  To: Jérôme Poulin; +Cc: netfilter-devel

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


Hi Jérôme,

On Sat, Jul 23, 2005 at 05:38:23AM -0400, Jérôme Poulin told us:
> Thanks, MMS compiled without any error or warning, h323 still misses
> the file on its side.

hmm...I can take a look at h323, I'll post a patch either later tonight
or somewhen tomorrow. Have you already been able to verify that at least
the updated mms-conntrack-nat works??


Kind regards,

Sven

-- 
Linux zion 2.6.13-rc3-mm1 #6 PREEMPT Mon Jul 18 19:42:52 CEST 2005 i686 athlon i386 GNU/Linux
 22:21:23 up 1 day,  5:31,  2 users,  load average: 0.02, 0.01, 0.00

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: lockhelp.h missing
       [not found]     ` <debc30fc0507230238427b0290@mail.gmail.com>
  2005-07-23 20:25       ` Sven Schuster
@ 2005-07-23 20:52       ` Sven Schuster
  2005-07-26 18:25         ` Jérôme Poulin
       [not found]         ` <debc30fc05072611231d179fae@mail.gmail.com>
  1 sibling, 2 replies; 7+ messages in thread
From: Sven Schuster @ 2005-07-23 20:52 UTC (permalink / raw)
  To: Jérôme Poulin; +Cc: netfilter-devel


[-- Attachment #1.1: Type: text/plain, Size: 554 bytes --]


Hi Jérôme,

On Sat, Jul 23, 2005 at 05:38:23AM -0400, Jérôme Poulin told us:
> Thanks, MMS compiled without any error or warning, h323 still misses
> the file on its side.

here is a patch against current pom-ng svn to update h323-conntrack-nat
for current kernels. Please apply to your pom-ng and test it. Compile-
tested with 2.6.13-rc3-mm1.


Kind regards,

Sven

-- 
Linux zion 2.6.13-rc3-mm1 #6 PREEMPT Mon Jul 18 19:42:52 CEST 2005 i686 athlon i386 GNU/Linux
 22:50:36 up 1 day,  6:00,  2 users,  load average: 0.36, 0.48, 0.27

[-- Attachment #1.2: h323-2.6.12.patch --]
[-- Type: text/plain, Size: 71691 bytes --]

diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_h323.h pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_h323.h
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_h323.h	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/include/linux/netfilter_ipv4/ip_conntrack_h323.h	2005-07-03 22:40:12.000000000 +0200
@@ -0,0 +1,38 @@
+#ifndef _IP_CONNTRACK_H323_H
+#define _IP_CONNTRACK_H323_H
+/* H.323 connection tracking. */
+
+#ifdef __KERNEL__
+
+/* Default H.225 port */
+#define H225_PORT	1720
+
+struct ip_conntrack_expect;
+struct ip_conntrack;
+struct ip_conntrack_helper;
+
+extern int (*ip_nat_h245_hook)(struct sk_buff **pskb,
+			       enum ip_conntrack_info ctinfo,
+			       unsigned int offset,
+			       struct ip_conntrack_expect *exp);
+
+extern int (*ip_nat_h225_hook)(struct sk_buff **pskb,
+			       enum ip_conntrack_info ctinfo,
+			       unsigned int offset,
+			       struct ip_conntrack_expect *exp);
+
+extern void (*ip_nat_h225_signal_hook)(struct sk_buff **pskb,
+				       struct ip_conntrack *ct,
+				       enum ip_conntrack_info ctinfo,
+				       unsigned int offset,
+				       int dir,
+				       int orig_dir);
+
+extern struct ip_conntrack_helper ip_conntrack_helper_h225;
+
+void ip_conntrack_h245_expect(struct ip_conntrack *new,
+			      struct ip_conntrack_expect *this);
+
+#endif /* __KERNEL__ */
+
+#endif /* _IP_CONNTRACK_H323_H */
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.c pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.c
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.c	2005-07-03 22:40:12.000000000 +0200
@@ -0,0 +1,353 @@
+/*
+ * Tiny ASN.1 packet encoding rules (PER) library.
+ *
+ * This is a tiny library which helps parsing ASN.1/PER packets
+ * (i.e. read only). It is meant to be secure and small.
+ *
+ * Warning, this library may still be incomplete and buggy.
+ *
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include "asn1_per.h"
+
+void asn1_per_initialize(struct asn1_per_buffer *bb,
+			 const unsigned char *data,
+			 unsigned length, unsigned position) {
+	*bb = (struct asn1_per_buffer){
+		.data = data,
+		.length = length,
+		.i = position,
+		.bit = 8,
+		.error = 0,
+	};
+}
+
+int asn1_per_read_bit(struct asn1_per_buffer *bb) {
+	int value;
+
+	if (bb->error)
+		return 0;
+
+	if (bb->i >= bb->length) {
+		bb->error = 1;
+		return 0;
+	}
+
+	bb->bit--;
+
+	value = (bb->data[bb->i] & (1 << bb->bit)) != 0;
+
+	if (bb->bit == 0) {
+		bb->bit = 8;
+		bb->i++;
+	}
+
+	return value;
+}
+
+unsigned asn1_per_read_bits(struct asn1_per_buffer *bb, unsigned count) {
+	unsigned value;
+
+	if (bb->error)
+		return 0;
+	if (bb->i >= bb->length) {
+		bb->error = 1;
+		return 0;
+	}
+
+	if (count > 32) {
+		/* XXX support more than 32 bits in the future here? */
+		bb->error = 1;
+		return 0;
+	}
+
+	if (count <= bb->bit) {
+		value = (bb->data[bb->i] >> (bb->bit - count)) & (0xff >> (8 - count));
+
+		bb->bit -= count;
+		if (bb->bit == 0) {
+			bb->bit = 8;
+			bb->i++;
+		}
+
+		return value;
+	}
+
+	count -= bb->bit;
+
+	value = bb->data[bb->i] & (0xff >> (8 - bb->bit));
+	bb->i++;
+
+	while (count >= 8) {
+		if (bb->i >= bb->length) {
+			bb->error = 1;
+			return 0;
+		}
+
+		value = (value << 8) | bb->data[bb->i];
+
+		bb->i++;
+		count -= 8;
+	}
+
+	if (count > 0) {
+		if (bb->i >= bb->length) {
+			bb->error = 1;
+			return 0;
+		}
+
+		value = (value << count) | (bb->data[bb->i] >> (8 - count));
+	}
+
+	bb->bit = 8 - count;
+
+	return value;
+}
+
+void asn1_per_read_bitmap(struct asn1_per_buffer *bb, unsigned count,
+			  struct asn1_per_bitmap *bitmap) {
+	unsigned char *p;
+
+	memset(bitmap, 0, sizeof(*bitmap));
+
+	if (bb->error)
+		return;
+
+	if (count > sizeof(bitmap->data) * 8) {
+		/* XXX limited bit map support */
+		bb->error = 1;
+		return;
+	}
+
+	for (p = bitmap->data; count > 8; count -= 8)
+		*p++ = (unsigned char)asn1_per_read_bits(bb, 8);
+
+	if (count > 0)
+		*p = asn1_per_read_bits(bb, count) << (8 - count);
+
+	return;
+}
+
+void asn1_per_read_bytes(struct asn1_per_buffer *bb,
+			 void *buffer, unsigned count) {
+	if (bb->error)
+		return;
+
+	if (bb->bit != 8) {
+		bb->error = 1;
+		return;
+	}
+
+	if (bb->i + count > bb->length) {
+		bb->error = 1;
+		return;
+	}
+
+	memcpy(buffer, bb->data + bb->i, count);
+
+	bb->i += count;
+}
+
+void asn1_per_byte_align(struct asn1_per_buffer *bb) {
+	if (bb->bit < 8) {
+		bb->bit = 8;
+		bb->i++;
+	}
+}
+
+static unsigned count_bits(unsigned range) {
+	unsigned bits = 0;
+
+	if (range == 0)
+		return 32;
+
+	if (range == 1)
+		return 1;
+
+	while (bits < 32 && range > (unsigned)(1 << bits))
+		bits++;
+
+	return bits;
+}
+
+unsigned asn1_per_read_unsigned(struct asn1_per_buffer *bb,
+				unsigned lower, unsigned upper) {
+	unsigned range = (upper - lower) + 1;
+	unsigned bits = count_bits(range);
+
+	if (lower == upper)
+		return lower;
+
+	if (range == 0 || range > 255) {
+		if (bits > 16)
+			bits = asn1_per_read_length(bb, 1, (bits+7)/8) * 8;
+		else if (bits > 8)
+			bits = 16;
+		asn1_per_byte_align(bb);
+	}
+
+	return lower + asn1_per_read_bits(bb, bits);
+}
+
+unsigned asn1_per_read_length(struct asn1_per_buffer *bb,
+			      unsigned lower, unsigned upper) {
+	if (upper < 65536)
+		return asn1_per_read_unsigned(bb, lower, upper);
+
+	asn1_per_byte_align(bb);
+
+	if (!asn1_per_read_bit(bb))
+		return asn1_per_read_bits(bb, 7);
+
+	if (!asn1_per_read_bit(bb))
+		return asn1_per_read_bits(bb, 14);
+
+	bb->error = 1;
+	return 0;
+}
+
+unsigned asn1_per_read_small(struct asn1_per_buffer *bb) {
+	unsigned length;
+
+	if (!asn1_per_read_bit(bb))
+		return asn1_per_read_bits(bb, 6);
+
+	length = asn1_per_read_length(bb, 0, INT_MAX);
+
+	asn1_per_byte_align(bb);
+
+	return asn1_per_read_bits(bb, length * 8);
+}
+
+unsigned asn1_per_read_choice_header(struct asn1_per_buffer *bb,
+				     int extendable,
+				     unsigned options, unsigned *after) {
+	int extended;
+	unsigned choice;
+
+	extended = extendable && asn1_per_read_bit(bb);
+	if (extended) {
+		unsigned length;
+
+		choice = asn1_per_read_small(bb) + options;
+		length = asn1_per_read_length(bb, 0, INT_MAX);
+		*after = bb->i + length;
+	} else if (options < 2) {
+		choice = 0;
+		*after = 0;
+	} else {
+		choice = asn1_per_read_bits(bb, count_bits(options));
+		*after = 0;
+	}
+
+	return choice;
+}
+
+void asn1_per_read_sequence_header(struct asn1_per_buffer *bb, int extendable,
+				   unsigned optional_count,
+				   struct asn1_per_sequence_header *hdr) {
+	hdr->extended = extendable && asn1_per_read_bit(bb);
+	asn1_per_read_bitmap(bb, optional_count, &hdr->present);
+}
+
+void asn1_per_read_sequence_extension_header(struct asn1_per_buffer *bb,
+					     const struct asn1_per_sequence_header *hdr,
+					     struct asn1_per_sequence_extension_header *ext) {
+	if (!hdr->extended) {
+		memset(ext, 0, sizeof(*ext));
+		return;
+	}
+
+	ext->count = asn1_per_read_small(bb) + 1;
+	if (bb->error)
+		return;
+
+	asn1_per_read_bitmap(bb, ext->count, &ext->present);
+}
+
+void asn1_per_skip_sequence_extension(struct asn1_per_buffer *bb,
+				      const struct asn1_per_sequence_header *hdr) {
+	struct asn1_per_sequence_extension_header ext;
+	unsigned i;
+
+	asn1_per_read_sequence_extension_header(bb, hdr, &ext);
+	if (bb->error)
+		return;
+
+	for (i = 0; i < ext.count && !bb->error; i++) {
+		if (asn1_per_bitmap_get(&ext.present, i))
+			asn1_per_skip_octet_string(bb);
+	}
+}
+
+void asn1_per_skip_object_id(struct asn1_per_buffer *bb) {
+	unsigned length;
+
+	length = asn1_per_read_length(bb, 0, 255);
+	switch (length) {
+	case 0:
+		break;
+
+	case 1:
+		asn1_per_read_bits(bb, 8);
+		break;
+
+	case 2:
+		asn1_per_read_bits(bb, 16);
+		break;
+
+	default:
+		asn1_per_byte_align(bb);
+
+		bb->i += length;
+		if (bb->i > bb->length)
+			bb->error = 1;
+	}
+}
+
+unsigned asn1_per_read_octet_string_header(struct asn1_per_buffer *bb) {
+	unsigned length;
+
+	length = asn1_per_read_length(bb, 0, INT_MAX);
+	if (length > 2)
+		asn1_per_byte_align(bb);
+
+	return length;
+}
+
+void asn1_per_skip_octet_string(struct asn1_per_buffer *bb) {
+	unsigned length;
+
+	length = asn1_per_read_length(bb, 0, INT_MAX);
+	switch (length) {
+	case 0:
+		break;
+
+	case 1:
+		asn1_per_read_bits(bb, 8);
+		break;
+
+	case 2:
+		asn1_per_read_bits(bb, 16);
+		break;
+
+	default:
+		asn1_per_byte_align(bb);
+
+		bb->i += length;
+		if (bb->i > bb->length)
+			bb->error = 1;
+	}
+}
+
+
+int asn1_per_bitmap_get(const struct asn1_per_bitmap *bitmap, unsigned i) {
+	if (i >= sizeof(bitmap->data) * 8)
+		return 0;
+
+	return (bitmap->data[i / 8] & (1 << (7 - (i % 8)))) != 0;
+}
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.h pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.h
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.h	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/asn1_per.h	2005-07-03 22:40:12.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ * Tiny ASN.1 packet encoding rules (PER) library.
+ *
+ * This is a tiny library which helps parsing ASN.1/PER packets
+ * (i.e. read only). It is meant to be secure and small.
+ *
+ * Warning, this library may still be incomplete and buggy.
+ *
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ */
+
+#ifndef __ASN1_PER_H
+#define __ASN1_PER_H
+
+struct asn1_per_buffer {
+	const unsigned char *data;
+	unsigned length, i, bit;
+	int error;
+};
+
+struct asn1_per_bitmap {
+	unsigned char data[16];
+};
+
+struct asn1_per_sequence_header {
+	int extended;
+	struct asn1_per_bitmap present;
+};
+
+struct asn1_per_sequence_extension_header {
+	unsigned count;
+	struct asn1_per_bitmap present;
+};
+
+void asn1_per_initialize(struct asn1_per_buffer *bb,
+			 const unsigned char *data,
+			 unsigned length, unsigned position);
+
+int asn1_per_read_bit(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_bits(struct asn1_per_buffer *bb, unsigned count);
+
+void asn1_per_read_bitmap(struct asn1_per_buffer *bb, unsigned count,
+			  struct asn1_per_bitmap *bitmap);
+
+void asn1_per_read_bytes(struct asn1_per_buffer *bb,
+			 void *buffer, unsigned count);
+
+void asn1_per_byte_align(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_unsigned(struct asn1_per_buffer *bb,
+				unsigned lower, unsigned upper);
+
+unsigned asn1_per_read_length(struct asn1_per_buffer *bb,
+			      unsigned lower, unsigned upper);
+
+unsigned asn1_per_read_small(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_choice_header(struct asn1_per_buffer *bb,
+				     int extendable,
+				     unsigned options, unsigned *after);
+
+void asn1_per_read_sequence_header(struct asn1_per_buffer *bb, int extendable,
+				   unsigned optional_count,
+				   struct asn1_per_sequence_header *hdr);
+
+void asn1_per_read_sequence_extension_header(struct asn1_per_buffer *bb,
+					     const struct asn1_per_sequence_header *hdr,
+					     struct asn1_per_sequence_extension_header *ext);
+
+void asn1_per_skip_sequence_extension(struct asn1_per_buffer *bb,
+				      const struct asn1_per_sequence_header *hdr);
+
+void asn1_per_skip_object_id(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_octet_string_header(struct asn1_per_buffer *bb);
+
+void asn1_per_skip_octet_string(struct asn1_per_buffer *bb);
+
+
+int asn1_per_bitmap_get(const struct asn1_per_bitmap *bitmap, unsigned i);
+
+#endif
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323.c pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323.c
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323.c	2005-07-23 22:43:12.000000000 +0200
@@ -0,0 +1,447 @@
+/*
+ * H.323 'brute force' extension for H.323 connection tracking.
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ *
+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
+ * (http://www.coritel.it/projects/sofia/nat/)
+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
+ * the unregistered helpers to the conntrack entries.
+ */
+
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
+MODULE_LICENSE("GPL");
+
+/* This is slow, but it's simple. --RR */
+static char h323_buffer[65536];
+
+static DEFINE_SPINLOCK(ip_h323_lock);
+
+struct module *ip_conntrack_h323 = THIS_MODULE;
+
+int (*ip_nat_h245_hook)(struct sk_buff **pskb,
+			enum ip_conntrack_info ctinfo,
+			unsigned int offset,
+			struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_h245_hook);
+
+int (*ip_nat_h225_hook)(struct sk_buff **pskb,
+			enum ip_conntrack_info ctinfo,
+			unsigned int offset,
+			struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_h225_hook);
+
+void (*ip_nat_h225_signal_hook)(struct sk_buff **pskb,
+				struct ip_conntrack *ct,
+				enum ip_conntrack_info ctinfo,
+				unsigned int offset,
+				int dir,
+				int orig_dir);
+EXPORT_SYMBOL_GPL(ip_nat_h225_signal_hook);
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* FIXME: This should be in userspace.  Later. */
+static int h245_help(struct sk_buff **pskb,
+		     struct ip_conntrack *ct,
+		     enum ip_conntrack_info ctinfo)
+{
+	struct tcphdr _tcph, *tcph;
+	unsigned char *data;
+	unsigned char *data_limit;
+	unsigned dataoff, datalen;
+	int dir = CTINFO2DIR(ctinfo);
+	struct ip_conntrack_expect *exp;
+	u_int16_t data_port;
+	u_int32_t data_ip;
+	unsigned int i;
+	int ret;
+
+	/* Until there's been traffic both ways, don't look in packets. */
+	if (ctinfo != IP_CT_ESTABLISHED
+	    && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+		DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
+		return NF_ACCEPT;
+	}
+
+	tcph = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+				  sizeof(_tcph), &_tcph);
+	if (tcph == NULL)
+		return NF_ACCEPT;
+
+	DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+		NIPQUAD((*pskb)->nh.iph->saddr), ntohs(tcph->source),
+		NIPQUAD((*pskb)->nh.iph->daddr), ntohs(tcph->dest));
+
+	dataoff = (*pskb)->nh.iph->ihl*4 + tcph->doff*4;
+	/* No data? */
+	if (dataoff >= (*pskb)->len) {
+		DEBUGP("ct_h245_help: skblen = %u\n", (*pskb)->len);
+		return NF_ACCEPT;
+	}
+	datalen = (*pskb)->len - dataoff;
+
+	spin_lock_bh(&ip_h323_lock);
+	data = skb_header_pointer((*pskb), dataoff,
+				  datalen, h323_buffer);
+	BUG_ON(data == NULL);
+
+	data_limit = data + datalen - 6;
+	/* bytes: 0123   45
+	          ipadrr port */
+	for (i = 0; data <= data_limit; data++, i++) {
+		data_ip = *((u_int32_t *)data);
+		if (data_ip == ct->tuplehash[dir].tuple.src.ip) {
+			data_port = *((u_int16_t *)(data + 4));
+
+			/* update the H.225 info */
+			DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
+				NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
+				NIPQUAD((*pskb)->nh.iph->saddr), ntohs(data_port));
+
+			exp = ip_conntrack_expect_alloc();
+			if (exp == NULL) {
+				ret = NF_ACCEPT;
+				goto out;
+			}
+
+			exp->tuple = ((struct ip_conntrack_tuple)
+				{ { ct->tuplehash[!dir].tuple.src.ip,
+				    { 0 } },
+				  { data_ip,
+				    { .tcp = { data_port } },
+				    IPPROTO_UDP }});
+			exp->mask = ((struct ip_conntrack_tuple)
+				{ { 0xFFFFFFFF, { 0 } },
+				  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+
+			exp->expectfn = NULL;
+			exp->master = ct;
+
+			if (ip_nat_h245_hook != NULL) {
+				ret = ip_nat_h245_hook(pskb, ctinfo, i,
+						       exp);
+			} else {
+				/* Can't expect this?  Best to drop packet now. */
+				if (ip_conntrack_expect_related(exp) != 0) {
+					ip_conntrack_expect_free(exp);
+					ret = NF_DROP;
+				} else
+					ret = NF_ACCEPT;
+			}
+
+			break;
+		}
+	}
+
+	ret = NF_ACCEPT;
+ out:
+	spin_unlock_bh(&ip_h323_lock);
+	return ret;
+}
+
+/* H.245 helper is not registered! */
+static struct ip_conntrack_helper h245 =
+{
+	.name = "H.245",
+	.max_expected = 8,
+	.timeout = 240,
+	.tuple = { .dst = { .protonum = IPPROTO_TCP } },
+	.mask = { .src = { .u = { 0xFFFF } },
+		  .dst = { .protonum = 0xFF } },
+	.help = h245_help
+};
+
+void ip_conntrack_h245_expect(struct ip_conntrack *new,
+			      struct ip_conntrack_expect *this)
+{
+	write_lock_bh(&ip_conntrack_lock);
+	new->helper = &h245;
+	DEBUGP("h225_expect: helper for %p added\n", new);
+	write_unlock_bh(&ip_conntrack_lock);
+}
+EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
+
+/**
+ * Parse a Q.931 CONNECT packet and handle NAT/expectations for the
+ * H.245 transport address.
+ */
+static int h225_parse_q931_connect(struct sk_buff **pskb,
+				   struct ip_conntrack *ct,
+				   enum ip_conntrack_info ctinfo,
+				   const unsigned char *data,
+				   unsigned i, unsigned length)
+{
+	int dir = CTINFO2DIR(ctinfo);
+	u_int32_t data_ip;
+	u_int16_t data_port;
+	struct ip_conntrack_expect *exp;
+
+	/* protocol(1) + header(3) + protocolIdentifier(6) +
+	   h245ipAddress(1) + h245ipv4(4) + h245ipv4port(2) */
+	if (length < 17)
+		return NF_ACCEPT;
+
+	if (data[i++] != 0x05) /* X.208 / X.209 */
+		return NF_ACCEPT;
+
+	/* XXX: h225 header connect? */
+	if (data[i++] != 0x22 || data[i++] != 0xc0 || data[i++] != 0x06)
+		return NF_ACCEPT;
+
+	/* protocolIdentifier, ignore the last 2 bytes (minor
+	   version) */
+	if (memcmp(data + i, "\x00\x08\x91\x4a", 4) != 0)
+		return NF_ACCEPT;
+
+	i += 6;
+
+	if (data[i++] != 0x00) /* h245ipAddress? */
+		return NF_ACCEPT;
+
+	/* compare the IP address - this is only a valid H.245
+	   transport address, if it equals the source address of the
+	   packet */
+	data_ip = *(u_int32_t *)(data + i);
+	if (data_ip != ct->tuplehash[dir].tuple.src.ip)
+		return NF_ACCEPT;
+
+
+	data_port = *((u_int16_t *)(data + i + 4));
+
+	/* match found: create an expectation */
+	exp = ip_conntrack_expect_alloc();
+	if (exp == NULL)
+		return NF_ACCEPT;
+
+	exp->tuple = ((struct ip_conntrack_tuple)
+			{ { ct->tuplehash[!dir].tuple.src.ip,
+			    { 0 } },
+			  { ct->tuplehash[!dir].tuple.dst.ip,
+			    { .tcp = { data_port } },
+			    IPPROTO_TCP }});
+	exp->mask = ((struct ip_conntrack_tuple)
+			{ { 0xFFFFFFFF, { 0 } },
+			  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+
+	exp->expectfn = ip_conntrack_h245_expect;
+	exp->master = ct;
+
+	/* call NAT hook and register expectation */
+	if (ip_nat_h225_hook != NULL) {
+		return ip_nat_h225_hook(pskb, ctinfo, i,
+					exp);
+	} else {
+		/* Can't expect this?  Best to drop packet now. */
+		if (ip_conntrack_expect_related(exp) != 0) {
+			ip_conntrack_expect_free(exp);
+			return NF_DROP;
+		} else {
+			return NF_ACCEPT;
+		}
+	}
+}
+
+/**
+ * Scan a Q.931 packet for a user-to-user information element
+ * (IE). Return the index, or 0 if none found.
+ */
+static unsigned q931_find_u2u(const unsigned char *data,
+			      unsigned datalen,
+			      unsigned int i,
+			      unsigned *lengthp) {
+	unsigned char type;
+	unsigned length;
+
+	/* traverse all Q.931 information elements (IE) */
+	while (i + 2 <= datalen) {
+		type = data[i++];
+
+		/* highest bit set means one-byte IE */
+		if (type & 0x80)
+			continue;
+
+		length = data[i++];
+
+		if (type == 0x7e) { /* user-to-user */
+			/* user-to-user IEs have a 16 bit length
+			   field */
+			length = (length << 8) | data[i++];
+			if (i + length > datalen)
+				return 0;
+
+			*lengthp = length;
+			return i;
+		}
+
+		i += length;
+	}
+
+	return 0;
+}
+
+/**
+ * Parse a Q.931/H.225 packet and handle NAT/expectations for the
+ * H.245 transport address (if applicable).
+ */
+static int h225_parse_q931(struct sk_buff **pskb,
+			   struct ip_conntrack *ct,
+			   enum ip_conntrack_info ctinfo,
+			   const unsigned char *data,
+			   unsigned datalen, unsigned i) {
+	u_int8_t q931_message_type;
+	unsigned length;
+
+	/* parse Q.931 packet */
+	if (data[i++] != 0x08) /* protocol discriminator */
+		return NF_ACCEPT;
+
+	/* call reference */
+	i += 1 + data[i];
+	if (i >= datalen)
+		return NF_ACCEPT;
+
+	/* only some Q.931 message types can contain a H.245 transport
+	   address - we can ignore the rest in this module */
+	q931_message_type = data[i++];
+	if (q931_message_type == 0x07) {
+		/* CONNECT */
+
+		/* find a user-to-user information element (IE) */
+		i = q931_find_u2u(data, datalen, i, &length);
+		if (i == 0)
+			return NF_ACCEPT;
+
+		return h225_parse_q931_connect(pskb, ct, ctinfo,
+					       data, i, length);
+	} else {
+		/* XXX handle q931_message_type 0x01, 0x02, 0x03 */
+		return NF_ACCEPT;
+	}
+}
+
+/**
+ * Parse a TPKT/Q.931/H.225 packet and handle NAT/expectations for the
+ * H.245 transport address (if applicable).
+ */
+static int h225_parse_tpkt(struct sk_buff **pskb,
+			   struct ip_conntrack *ct,
+			   enum ip_conntrack_info ctinfo,
+			   const unsigned char *data,
+			   unsigned datalen) {
+	unsigned int i = 0;
+	u_int16_t tpkt_len;
+
+	/* expect TPKT header, see RFC 1006 */
+	if (data[0] != 0x03 || data[1] != 0x00)
+		return NF_ACCEPT;
+
+	i += 2;
+
+	tpkt_len = ntohs(*(u_int16_t*)(data + i));
+	if (tpkt_len < 16)
+		return NF_ACCEPT;
+
+	if (tpkt_len < datalen)
+		datalen = tpkt_len;
+
+	i += 2;
+
+	/* parse Q.931 packet */
+	return h225_parse_q931(pskb, ct, ctinfo,
+			       data, datalen, i);
+}
+
+static int h225_help(struct sk_buff **pskb,
+		     struct ip_conntrack *ct,
+		     enum ip_conntrack_info ctinfo)
+{
+	struct tcphdr _tcph, *tcph;
+	unsigned char *data;
+	unsigned dataoff, datalen;
+	int ret = NF_ACCEPT;
+
+	/* Until there's been traffic both ways, don't look in packets. */
+	if (ctinfo != IP_CT_ESTABLISHED
+	    && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+		DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
+		return NF_ACCEPT;
+	}
+
+	tcph = skb_header_pointer((*pskb), (*pskb)->nh.iph->ihl*4,
+				  sizeof(_tcph), &_tcph);
+	if (tcph == NULL)
+		return NF_ACCEPT;
+
+	DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+		NIPQUAD((*pskb)->nh.iph->saddr), ntohs(tcph->source),
+		NIPQUAD((*pskb)->nh.iph->daddr), ntohs(tcph->dest));
+
+	dataoff = (*pskb)->nh.iph->ihl*4 + tcph->doff*4;
+	/* No data? */
+	if (dataoff >= (*pskb)->len) {
+		DEBUGP("ct_h225_help: skblen = %u\n", (*pskb)->len);
+		return NF_ACCEPT;
+	}
+	datalen = (*pskb)->len - dataoff;
+
+	if (datalen < 32)
+		return NF_ACCEPT;
+
+	/* get data portion, and evaluate it */
+	spin_lock_bh(&ip_h323_lock);
+	data = skb_header_pointer((*pskb), dataoff,
+				  datalen, h323_buffer);
+	BUG_ON(data == NULL);
+
+	ret = h225_parse_tpkt(pskb, ct, ctinfo,
+			      data, datalen);
+
+	spin_unlock_bh(&ip_h323_lock);
+	return ret;
+}
+
+static struct ip_conntrack_helper h225 =
+{
+	.name = "H.225",
+	.me = THIS_MODULE,
+	.max_expected = 2,
+	.timeout = 240,
+	.tuple = { .src = { .u = { __constant_htons(H225_PORT) } },
+		   .dst = { .protonum = IPPROTO_TCP } },
+	.mask = { .src = { .u = { 0xFFFF } },
+		  .dst = { .protonum = 0xFF } },
+	.help = h225_help
+};
+
+static int __init init(void)
+{
+	return ip_conntrack_helper_register(&h225);
+}
+
+static void __exit fini(void)
+{
+	/* Unregister H.225 helper */
+	ip_conntrack_helper_unregister(&h225);
+}
+
+module_init(init);
+module_exit(fini);
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_core.c pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_core.c
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_core.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_core.c	2005-07-23 22:44:53.000000000 +0200
@@ -0,0 +1,37 @@
+/*
+ * H.323 connection tracking helper
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ *
+ * Based on the 'brute force' H.323 connection tracking module by
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ */
+
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+
+MODULE_AUTHOR("Max Kellermann <max@duempel.org>");
+MODULE_DESCRIPTION("H.323 connection tracking helper");
+MODULE_LICENSE("GPL");
+
+static int __init init(void)
+{
+	return ip_conntrack_helper_register(&ip_conntrack_helper_h225);
+}
+
+static void __exit fini(void)
+{
+	ip_conntrack_helper_unregister(&ip_conntrack_helper_h225);
+}
+
+module_init(init);
+module_exit(fini);
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h225.c pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h225.c
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h225.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h225.c	2005-07-23 22:43:39.000000000 +0200
@@ -0,0 +1,405 @@
+/*
+ * H.323/H.225 connection tracking helper
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ *
+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
+ * the unregistered helpers to the conntrack entries.
+ */
+
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+
+#include "asn1_per.h"
+
+/* This is slow, but it's simple. --RR */
+static char h225_buffer[65536];
+
+static DEFINE_SPINLOCK(ip_h225_lock);
+
+int (*ip_nat_h225_hook)(struct sk_buff **pskb,
+			enum ip_conntrack_info ctinfo,
+			unsigned int offset,
+			struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_h225_hook);
+
+void (*ip_nat_h225_signal_hook)(struct sk_buff **pskb,
+				struct ip_conntrack *ct,
+				enum ip_conntrack_info ctinfo,
+				unsigned int offset,
+				int dir,
+				int orig_dir);
+EXPORT_SYMBOL_GPL(ip_nat_h225_signal_hook);
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/**
+ * Parse an H.225 TransportAddress and return the position of the IP
+ * address (if present). Returns 1 on success.
+ */
+static int h225_parse_transport_address(struct asn1_per_buffer *bb, unsigned *i,
+					u_int32_t *ip, u_int16_t *port) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 7, &after);
+	if (bb->error)
+		return 0;
+
+	switch (choice) {
+	case 0: /* ipAddress */
+		asn1_per_byte_align(bb);
+		*i = bb->i;
+		asn1_per_read_bytes(bb, ip, sizeof(*ip));
+		asn1_per_read_bytes(bb, port, sizeof(*port));
+		return !bb->error;
+
+	default:
+		if (after == 0) {
+			DEBUGP("TransportAddress %u not yet supported\n", choice);
+			bb->error = 1;
+		} else {
+			bb->i = after;
+		}
+		return 0;
+	}
+}
+
+/**
+ * Parse a H.225 Connect-UUIE packet and handle NAT/expectations for
+ * the H.245 transport address.
+ */
+static int h225_parse_connect_uuie(struct sk_buff **pskb,
+				   struct ip_conntrack *ct,
+				   enum ip_conntrack_info ctinfo,
+				   struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr;
+
+	asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+	/* protocolIdentifier */
+	asn1_per_skip_object_id(bb);
+
+	/* h245Address */
+	if (asn1_per_bitmap_get(&hdr.present, 0)) {
+		int dir = CTINFO2DIR(ctinfo);
+		struct ip_conntrack_expect *exp;
+		int ret;
+		unsigned i;
+		u_int32_t ip;
+		u_int16_t port;
+
+		ret = h225_parse_transport_address(bb, &i, &ip, &port);
+		if (ret) {
+			DEBUGP("H.245 transportAddress: %u.%u.%u.%u:%u\n",
+			       NIPQUAD(ip), ntohs(port));
+		}
+		if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+			/* match found: create an expectation */
+			exp = ip_conntrack_expect_alloc();
+			if (exp == NULL)
+				return NF_ACCEPT;
+
+			exp->tuple = ((struct ip_conntrack_tuple)
+					{ { ct->tuplehash[!dir].tuple.src.ip,
+					    { 0 } },
+					  { ct->tuplehash[!dir].tuple.dst.ip,
+					    { .tcp = { port } },
+					    IPPROTO_TCP }});
+			exp->mask = ((struct ip_conntrack_tuple)
+					{ { 0xFFFFFFFF, { 0 } },
+					  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+
+			exp->expectfn = ip_conntrack_h245_expect;
+			exp->master = ct;
+
+			/* call NAT hook and register expectation */
+			if (ip_nat_h225_hook != NULL) {
+				return ip_nat_h225_hook(pskb, ctinfo, i,
+							exp);
+			} else {
+				/* Can't expect this?  Best to drop packet now. */
+				if (ip_conntrack_expect_related(exp) != 0) {
+					ip_conntrack_expect_free(exp);
+					return NF_DROP;
+				} else {
+					return NF_ACCEPT;
+				}
+			}
+		}
+	}
+
+	/* XXX */
+	bb->error = 1;
+
+	asn1_per_skip_sequence_extension(bb, &hdr);
+
+	return NF_ACCEPT;
+}
+
+/**
+ * Parse a H.225 H323-UU-PDU packet and handle NAT/expectations for
+ * the H.245 transport address.
+ */
+static int h225_parse_uu_pdu(struct sk_buff **pskb,
+			     struct ip_conntrack *ct,
+			     enum ip_conntrack_info ctinfo,
+			     struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr;
+	unsigned choice, after;
+	int ret;
+
+	asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+	/* h323-message-body */
+	choice = asn1_per_read_choice_header(bb, 1, 7, &after);
+	switch (choice) {
+	case 2: /* connect */
+		ret = h225_parse_connect_uuie(pskb, ct, ctinfo, bb);
+		if (ret != NF_ACCEPT)
+			return ret;
+		break;
+
+	default:
+		if (after == 0) {
+			bb->error = 1;
+			return NF_ACCEPT;
+		}
+
+		bb->i = after;
+	}
+
+	asn1_per_skip_sequence_extension(bb, &hdr);
+
+	return NF_ACCEPT;
+}
+
+/**
+ * Parse a H.225 packet and handle NAT/expectations for the H.245
+ * transport address.
+ */
+static int h225_parse(struct sk_buff **pskb,
+		      struct ip_conntrack *ct,
+		      enum ip_conntrack_info ctinfo,
+		      struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr;
+
+	asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+	return h225_parse_uu_pdu(pskb, ct, ctinfo, bb);
+}
+
+/**
+ * Parse a Q.931 CONNECT packet and handle NAT/expectations for the
+ * H.245 transport address.
+ */
+static int h225_parse_q931_connect(struct sk_buff **pskb,
+				   struct ip_conntrack *ct,
+				   enum ip_conntrack_info ctinfo,
+				   const unsigned char *data,
+				   unsigned i, unsigned length)
+{
+	struct asn1_per_buffer bb;
+
+	if (i + 2 > length)
+		return NF_ACCEPT;
+
+	if (data[i++] != 0x05) /* X.208 / X.209 */
+		return NF_ACCEPT;
+
+	asn1_per_initialize(&bb, data, length, i);
+
+	return h225_parse(pskb, ct, ctinfo, &bb);
+}
+
+/**
+ * Scan a Q.931 packet for a user-to-user information element
+ * (IE). Return the index, or 0 if none found.
+ */
+static unsigned q931_find_u2u(const unsigned char *data,
+			      unsigned datalen,
+			      unsigned int i,
+			      unsigned *lengthp) {
+	unsigned char type;
+	unsigned length;
+
+	/* traverse all Q.931 information elements (IE) */
+	while (i + 2 <= datalen) {
+		type = data[i++];
+
+		/* highest bit set means one-byte IE */
+		if (type & 0x80)
+			continue;
+
+		length = data[i++];
+
+		if (type == 0x7e) { /* user-to-user */
+			/* user-to-user IEs have a 16 bit length
+			   field */
+			length = (length << 8) | data[i++];
+			if (i + length > datalen)
+				return 0;
+
+			*lengthp = length;
+			return i;
+		}
+
+		i += length;
+	}
+
+	return 0;
+}
+
+/**
+ * Parse a Q.931/H.225 packet and handle NAT/expectations for the
+ * H.245 transport address (if applicable).
+ */
+static int h225_parse_q931(struct sk_buff **pskb,
+			   struct ip_conntrack *ct,
+			   enum ip_conntrack_info ctinfo,
+			   const unsigned char *data,
+			   unsigned datalen, unsigned i) {
+	u_int8_t q931_message_type;
+	unsigned length;
+
+	if (i + 3 > datalen)
+		return NF_ACCEPT;
+
+	/* parse Q.931 packet */
+	if (data[i++] != 0x08) /* protocol discriminator */
+		return NF_ACCEPT;
+
+	/* call reference */
+	i += 1 + data[i];
+	if (i >= datalen)
+		return NF_ACCEPT;
+
+	/* only some Q.931 message types can contain a H.245 transport
+	   address - we can ignore the rest in this module */
+	q931_message_type = data[i++];
+	if (q931_message_type == 0x07) {
+		/* CONNECT */
+
+		/* find a user-to-user information element (IE) */
+		i = q931_find_u2u(data, datalen, i, &length);
+		if (i == 0)
+			return NF_ACCEPT;
+
+		/* the length returned by q931_find_u2u() is relative
+		   to i */
+		length += i;
+
+		return h225_parse_q931_connect(pskb, ct, ctinfo,
+					       data, i, length);
+	} else {
+		/* XXX handle q931_message_type 0x01, 0x02, 0x03 */
+		return NF_ACCEPT;
+	}
+}
+
+/**
+ * Parse a TPKT/Q.931/H.225 packet and handle NAT/expectations for the
+ * H.245 transport address (if applicable).
+ */
+static int h225_parse_tpkt(struct sk_buff **pskb,
+			   struct ip_conntrack *ct,
+			   enum ip_conntrack_info ctinfo,
+			   const unsigned char *data,
+			   unsigned datalen) {
+	unsigned int i = 0;
+	u_int16_t tpkt_len;
+
+	if (i + 4 > datalen)
+		return NF_ACCEPT;
+
+	/* expect TPKT header, see RFC 1006 */
+	if (data[0] != 0x03 || data[1] != 0x00)
+		return NF_ACCEPT;
+
+	i += 2;
+
+	tpkt_len = ntohs(*(u_int16_t*)(data + i));
+	if (tpkt_len < datalen)
+		datalen = tpkt_len;
+
+	i += 2;
+
+	/* parse Q.931 packet */
+	return h225_parse_q931(pskb, ct, ctinfo,
+			       data, datalen, i);
+}
+
+static int h225_help(struct sk_buff **pskb,
+		     struct ip_conntrack *ct,
+		     enum ip_conntrack_info ctinfo)
+{
+	struct tcphdr _tcph, *tcph;
+	unsigned char *data;
+	unsigned dataoff, datalen;
+	int ret = NF_ACCEPT;
+
+	/* Until there's been traffic both ways, don't look in packets. */
+	if (ctinfo != IP_CT_ESTABLISHED
+	    && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+		DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
+		return NF_ACCEPT;
+	}
+
+	tcph = skb_header_pointer((*pskb), (*pskb)->nh.iph->ihl*4,
+				  sizeof(_tcph), &_tcph);
+	if (tcph == NULL)
+		return NF_ACCEPT;
+
+	DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+		NIPQUAD((*pskb)->nh.iph->saddr), ntohs(tcph->source),
+		NIPQUAD((*pskb)->nh.iph->daddr), ntohs(tcph->dest));
+
+	dataoff = (*pskb)->nh.iph->ihl*4 + tcph->doff*4;
+	/* No data? */
+	if (dataoff >= (*pskb)->len) {
+		DEBUGP("ct_h225_help: skblen = %u\n", (*pskb)->len);
+		return NF_ACCEPT;
+	}
+	datalen = (*pskb)->len - dataoff;
+
+	if (datalen < 16)
+		return NF_ACCEPT;
+
+	/* get data portion, and evaluate it */
+	spin_lock_bh(&ip_h225_lock);
+	data = skb_header_pointer((*pskb), dataoff,
+				  datalen, h225_buffer);
+	BUG_ON(data == NULL);
+
+	ret = h225_parse_tpkt(pskb, ct, ctinfo,
+			      data, datalen);
+
+	spin_unlock_bh(&ip_h225_lock);
+	return ret;
+}
+
+struct ip_conntrack_helper ip_conntrack_helper_h225 =
+{
+	.name = "H.225",
+	.me = THIS_MODULE,
+	.max_expected = 2,
+	.timeout = 240,
+	.tuple = { .src = { .u = { __constant_htons(H225_PORT) } },
+		   .dst = { .protonum = IPPROTO_TCP } },
+	.mask = { .src = { .u = { 0xFFFF } },
+		  .dst = { .protonum = 0xFF } },
+	.help = h225_help
+};
+EXPORT_SYMBOL_GPL(ip_conntrack_helper_h225);
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h245.c pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h245.c
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h245.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_conntrack_h323_h245.c	2005-07-23 22:44:22.000000000 +0200
@@ -0,0 +1,959 @@
+/*
+ * H.323/H.245 connection tracking helper
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ *
+ * Based on the 'brute force' H.323 connection tracking module by
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ */
+
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+
+#include "asn1_per.h"
+
+/* This is slow, but it's simple. --RR */
+static char h245_buffer[65536];
+
+static DEFINE_SPINLOCK(ip_h245_lock);
+
+struct module *ip_conntrack_h245 = THIS_MODULE;
+
+int (*ip_nat_h245_hook)(struct sk_buff **pskb,
+			enum ip_conntrack_info ctinfo,
+			unsigned int offset,
+			struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_h245_hook);
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/**
+ * Skip an H.245 NonStandardIdentifier, discarding its value.
+ */
+static void h245_skip_nonstandard_id(struct asn1_per_buffer *bb) {
+	unsigned choice;
+
+	choice = asn1_per_read_bits(bb, 1);
+	switch (choice) {
+	case 0:
+		asn1_per_skip_object_id(bb);
+		break;
+
+	case 1:
+		asn1_per_read_unsigned(bb, 0, 255);
+		asn1_per_read_unsigned(bb, 0, 255);
+		asn1_per_read_unsigned(bb, 0, 65535);
+		break;
+	}
+}
+
+/**
+ * Skip an H.245 NonStandardParameter, discarding its value.
+ */
+static void h245_skip_nonstandard_param(struct asn1_per_buffer *bb) {
+	h245_skip_nonstandard_id(bb);
+	asn1_per_skip_octet_string(bb);
+}
+
+/**
+ * Skip an H.245 VideoCapability, discarding its value.
+ */
+static void h245_skip_video_capability(struct asn1_per_buffer *bb) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 5, &after);
+	DEBUGP("video_capability: choice=%u after=%u error=%d\n",
+	       choice, after, bb->error);
+
+	if (bb->error)
+		return;
+
+	/* XXX support the rest */
+	switch (choice) {
+	case 0: /* nonStandard */
+		h245_skip_nonstandard_param(bb);
+		break;
+
+	default:
+		if (after == 0) {
+			DEBUGP("unsupported audio_capability %u\n", choice);
+			bb->error = 1;
+		}
+	}
+
+	if (after > 0)
+		bb->i = after;
+}
+
+/**
+ * Skip an H.245 AudioCapability, discarding its value.
+ */
+static void h245_skip_audio_capability(struct asn1_per_buffer *bb) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 14, &after);
+	DEBUGP("audio_capability: audio_capability=%u after=%u error=%d\n", choice, after, bb->error);
+
+	if (bb->error)
+		return;
+
+	/* XXX support the rest */
+	switch (choice) {
+		unsigned value;
+
+	case 0: /* nonStandard */
+		h245_skip_nonstandard_param(bb);
+		break;
+
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 9:
+	case 10:
+	case 11:
+	case 14:
+	case 17:
+		value = asn1_per_read_unsigned(bb, 1, 256);
+		DEBUGP("value %u = %u\n", choice, value);
+		break;
+	default:
+		if (after == 0) {
+			DEBUGP("unsupported audio_capability %u\n", choice);
+			bb->error = 1;
+		}
+	}
+
+	if (after > 0)
+		bb->i = after;
+}
+
+/**
+ * Skip an H.245 DataType, discarding its value.
+ */
+static void h245_skip_data_type(struct asn1_per_buffer *bb) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 6, &after);
+
+	if (bb->error)
+		return;
+
+	/* XXX support the rest */
+	switch (choice) {
+	case 0: /* nonStandard */
+		h245_skip_nonstandard_param(bb);
+		break;
+
+	case 1: /* nullData */
+		break;
+
+	case 2: /* videoData */
+		h245_skip_video_capability(bb);
+		break;
+
+	case 3: /* audioData */
+		h245_skip_audio_capability(bb);
+		break;
+
+	default:
+		if (after == 0) {
+			DEBUGP("unsupported data_type %u\n", choice);
+			bb->error = 1;
+		}
+	}
+
+	if (after > 0)
+		bb->i = after;
+}
+
+/**
+ * Parse an H.245 UnicastAddress and return the position of the IP
+ * address (if present). Returns 1 on success.
+ */
+static int h245_parse_unicast_address(struct asn1_per_buffer *bb, unsigned *i,
+				      u_int32_t *ip, u_int16_t *port) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 5, &after);
+	DEBUGP("Parsing UnicastAddress choice=%u after=%u\n", choice, after);
+	switch (choice) {
+	case 0: /* iPAddress */
+		asn1_per_read_bit(bb); /* XXX use this bit */
+		asn1_per_byte_align(bb);
+		*i = bb->i;
+		asn1_per_read_bytes(bb, ip, sizeof(*ip));
+		asn1_per_read_bytes(bb, port, sizeof(*port));
+		return !bb->error;
+	default:
+		if (after == 0) {
+			DEBUGP("UnicastAddress %u not yet supported\n", choice);
+			bb->error = 1;
+		} else {
+			bb->i = after;
+		}
+		return 0;
+	}
+}
+
+/**
+ * Parse an H.245 TransportAddress and return the position of the
+ * Unicast IP address (if present). Returns 1 on success.
+ */
+static int h245_parse_transport_address(struct asn1_per_buffer *bb, unsigned *i,
+					u_int32_t *ip, u_int16_t *port) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 2, &after);
+	switch (choice) {
+	case 0: /* UnicastAddress */
+		return h245_parse_unicast_address(bb, i, ip, port);
+	case 1: /* MulticastAddress */
+		/* XXX */
+		DEBUGP("MulticastAddress not yet supported\n");
+		bb->error = 1;
+		return 0;
+	default:
+		if (after == 0) {
+			DEBUGP("ERROR7\n");
+			bb->error = 1;
+		} else {
+			bb->i = after;
+		}
+		return 0;
+	}
+}
+
+/**
+ * Skip an H.245 TerminalLabel, discarding its value.
+ */
+static void h245_skip_terminal_label(struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr;
+
+	asn1_per_read_sequence_header(bb, 1, 0, &hdr);
+
+	/* mcuNumber */
+	asn1_per_read_unsigned(bb, 0, 192);
+	/* terminalNumber */
+	asn1_per_read_unsigned(bb, 0, 192);
+
+	asn1_per_skip_sequence_extension(bb, &hdr);
+}
+
+/**
+ * Parse an H.245 H2250LogicalChannelParameters request packet and
+ * handle NAT/expectations for the logical channel address.
+ */
+static int h245_parse_h2250_lchannel_params(struct sk_buff **pskb,
+					    struct ip_conntrack *ct,
+					    enum ip_conntrack_info ctinfo,
+					    struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr;
+	unsigned session_id;
+
+	asn1_per_read_sequence_header(bb, 1, 10, &hdr);
+
+	/* nonStandard */
+	if (asn1_per_bitmap_get(&hdr.present, 0))
+		h245_skip_nonstandard_param(bb);
+
+	/* sessionID */
+	session_id = asn1_per_read_unsigned(bb, 0, 255);
+
+	/* associatedSessionID */
+	if (asn1_per_bitmap_get(&hdr.present, 1))
+		asn1_per_read_unsigned(bb, 1, 255);
+
+	/* mediaChannel */
+	DEBUGP("lchannel_params mediaChannel: i=%u bit=%u\n", bb->i, bb->bit);
+	if (asn1_per_bitmap_get(&hdr.present, 2)) {
+		int dir = CTINFO2DIR(ctinfo);
+		struct ip_conntrack_expect *exp;
+		int ret;
+		unsigned i;
+		u_int32_t ip;
+		u_int16_t port;
+
+		ret = h245_parse_transport_address(bb, &i, &ip, &port);
+		if (ret)
+			DEBUGP("mediaChannel IPv4 address: %u.%u.%u.%u:%u\n",
+			       NIPQUAD(ip), ntohs(port));
+		if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+			/* match found: create an expectation */
+			exp = ip_conntrack_expect_alloc();
+			if (exp == NULL)
+				return NF_ACCEPT;
+
+			exp->tuple = ((struct ip_conntrack_tuple)
+					{ { ct->tuplehash[!dir].tuple.src.ip,
+					    { 0 } },
+					  { ct->tuplehash[!dir].tuple.dst.ip,
+					    { .udp = { port } },
+					    IPPROTO_UDP }});
+			exp->mask = ((struct ip_conntrack_tuple)
+					{ { 0xFFFFFFFF, { 0 } },
+					  { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+			exp->master = ct;
+
+			/* call NAT hook and register expectation */
+			if (ip_nat_h245_hook != NULL) {
+				return ip_nat_h245_hook(pskb, ctinfo, i,
+							exp);
+			} else {
+				/* Can't expect this?  Best to drop packet now. */
+				if (ip_conntrack_expect_related(exp) != 0) {
+					ip_conntrack_expect_free(exp);
+					return NF_DROP;
+				} else {
+					return NF_ACCEPT;
+				}
+			}
+		}
+	}
+
+	/* mediaGuaranteedDelivery */
+	if (asn1_per_bitmap_get(&hdr.present, 3))
+		asn1_per_read_bit(bb);
+
+	/* mediaControlChannel */
+	DEBUGP("lchannel_params controlChannel: i=%u bit=%u\n", bb->i, bb->bit);
+	if (asn1_per_bitmap_get(&hdr.present, 4)) {
+		int dir = CTINFO2DIR(ctinfo);
+		struct ip_conntrack_expect *exp;
+		int ret;
+		unsigned i;
+		u_int32_t ip;
+		u_int16_t port;
+
+		ret = h245_parse_transport_address(bb, &i, &ip, &port);
+		if (ret)
+			DEBUGP("mediaControlChannel IPv4 address: %u.%u.%u.%u:%u\n",
+			       NIPQUAD(ip), ntohs(port));
+		if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+			/* match found: create an expectation */
+			exp = ip_conntrack_expect_alloc();
+			if (exp == NULL)
+				return NF_ACCEPT;
+
+			exp->tuple = ((struct ip_conntrack_tuple)
+					{ { ct->tuplehash[!dir].tuple.src.ip,
+					    { 0 } },
+					  { ct->tuplehash[!dir].tuple.dst.ip,
+					    { .udp = { port } },
+					    IPPROTO_UDP }});
+			exp->mask = ((struct ip_conntrack_tuple)
+					{ { 0xFFFFFFFF, { 0 } },
+					  { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+			exp->master = ct;
+
+			/* call NAT hook and register expectation */
+			if (ip_nat_h245_hook != NULL) {
+				return ip_nat_h245_hook(pskb, ctinfo, i,
+							exp);
+			} else {
+				/* Can't expect this?  Best to drop packet now. */
+				if (ip_conntrack_expect_related(exp) != 0) {
+					ip_conntrack_expect_free(exp);
+					return NF_DROP;
+				} else {
+					return NF_ACCEPT;
+				}
+			}
+		}
+	}
+
+	/* mediaControlGuaranteedDelivery */
+	if (asn1_per_bitmap_get(&hdr.present, 5))
+		asn1_per_read_bit(bb);
+
+	/* silenceSuppression */
+	if (asn1_per_bitmap_get(&hdr.present, 6))
+		asn1_per_read_bit(bb);
+
+	/* destination */
+	if (asn1_per_bitmap_get(&hdr.present, 7))
+		h245_skip_terminal_label(bb);
+
+	/* dynamicRTPPayloadType */
+	if (asn1_per_bitmap_get(&hdr.present, 8))
+		asn1_per_read_unsigned(bb, 96, 127);
+
+	/* mediaPacketization */
+	if (asn1_per_bitmap_get(&hdr.present, 9)) {
+		unsigned choice, after;
+
+		choice = asn1_per_read_choice_header(bb, 1, 1, &after);
+		switch (choice) {
+		case 0: /* h261aVideoPacketization */
+			break;
+
+		default:
+			if (after == 0) {
+				DEBUGP("ERROR7\n");
+				bb->error = 1;
+				return NF_ACCEPT;
+			}
+
+			bb->i = after;
+		}
+	}
+
+	/* XXX */
+
+	asn1_per_skip_sequence_extension(bb, &hdr);
+
+	return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 OpenLogicalChannel request packet and handle
+ * NAT/expectations for the logical channel address.
+ */
+static int h245_parse_open_lchannel(struct sk_buff **pskb,
+				    struct ip_conntrack *ct,
+				    enum ip_conntrack_info ctinfo,
+				    struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr, hdr2;
+	unsigned forwardLogicalChannelNumber;
+	unsigned choice, after;
+
+	asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+	forwardLogicalChannelNumber = asn1_per_read_unsigned(bb, 1, 65535);
+
+	/* entering forwardLogicalChannelParameters */
+	asn1_per_read_sequence_header(bb, 1, 1, &hdr2);
+	if (asn1_per_bitmap_get(&hdr2.present, 0))
+		asn1_per_read_unsigned(bb, 0, 65535);
+
+	h245_skip_data_type(bb);
+
+	/* multiplexParameters */
+	choice = asn1_per_read_choice_header(bb, 1, 3, &after);
+	if (bb->error)
+		return NF_ACCEPT;
+
+	switch (choice) {
+	case 3: /* h2250LogicalChannelParameters */
+		h245_parse_h2250_lchannel_params(pskb, ct, ctinfo, bb);
+		break;
+	default:
+		if (after == 0) {
+			DEBUGP("unsupported multiplex_parameter %u\n", choice);
+			bb->error = 1;
+			return NF_ACCEPT;
+		}
+	}
+
+	if (bb->error)
+		return NF_ACCEPT;
+
+	if (after > 0)
+		bb->i = after;
+
+	asn1_per_skip_sequence_extension(bb, &hdr2);
+
+	/* leaving multiplexParameters, forwardLogicalChannelParameters */
+
+	/* reverseLogicalChannelParameters */
+	if (asn1_per_bitmap_get(&hdr.present, 0)) {
+		asn1_per_read_sequence_header(bb, 1, 1, &hdr2);
+
+		h245_skip_data_type(bb);
+
+		/* multiplexParameters */
+		if (asn1_per_bitmap_get(&hdr2.present, 0)) {
+			choice = asn1_per_read_choice_header(bb, 1, 2, &after);
+			if (bb->error)
+				return NF_ACCEPT;
+
+			DEBUGP("reverse_parameter multiplex=%u after=%u\n", choice, after);
+
+			switch (choice) {
+			case 2: /* h2250LogicalChannelParameters */
+				h245_parse_h2250_lchannel_params(pskb, ct, ctinfo, bb);
+				break;
+			default:
+				if (after == 0) {
+					DEBUGP("unsupported multiplex_parameter %u\n", choice);
+					bb->error = 1;
+					return NF_ACCEPT;
+				}
+			}
+
+			if (bb->error)
+				return NF_ACCEPT;
+
+			if (after > 0)
+				bb->i = after;
+		}
+
+		asn1_per_skip_sequence_extension(bb, &hdr2);
+	}
+
+	asn1_per_skip_sequence_extension(bb, &hdr);
+
+	/* XXX */
+	return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 request packet and handle NAT/expectations for the
+ * logical channel address.
+ */
+static int h245_parse_request(struct sk_buff **pskb,
+			      struct ip_conntrack *ct,
+			      enum ip_conntrack_info ctinfo,
+			      struct asn1_per_buffer *bb) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 11, &after);
+	DEBUGP("H.245: message_type=%u\n", choice);
+	switch (choice) {
+	case 3:
+		return h245_parse_open_lchannel(pskb, ct, ctinfo, bb);
+	default:
+		return NF_ACCEPT;
+	}
+}
+
+/**
+ * Parse an H.245 H222LogicalChannelParameters response packet and
+ * handle NAT/expectations for the logical channel address.
+ */
+static int h245_parse_h222_lchannel_params(struct sk_buff **pskb,
+					   struct ip_conntrack *ct,
+					   enum ip_conntrack_info ctinfo,
+					   struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr;
+
+	asn1_per_read_sequence_header(bb, 1, 3, &hdr);
+
+	if (bb->error)
+		return NF_ACCEPT;
+
+	/* resourceID */
+	asn1_per_read_unsigned(bb, 0, 65535);
+
+	/* subChannelID */
+	asn1_per_read_unsigned(bb, 0, 8191);
+
+	/* pcr-pid */
+	if (asn1_per_bitmap_get(&hdr.present, 0))
+		asn1_per_read_unsigned(bb, 0, 8191);
+
+	/* programDescriptors */
+	if (asn1_per_bitmap_get(&hdr.present, 1))
+		asn1_per_skip_octet_string(bb);
+
+	/* streamDescriptors */
+	if (asn1_per_bitmap_get(&hdr.present, 2))
+		asn1_per_skip_octet_string(bb);
+
+	asn1_per_skip_sequence_extension(bb, &hdr);
+
+	return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 H2250LogicalChannelAckParameters response packet and
+ * handle NAT/expectations for the logical channel address.
+ */
+static int h245_parse_h2250_lchannel_ack_params(struct sk_buff **pskb,
+						struct ip_conntrack *ct,
+						enum ip_conntrack_info ctinfo,
+						struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr;
+	unsigned count;
+
+	DEBUGP("entering h245_parse_h2250_lchannel_ack_params\n");
+
+	asn1_per_read_sequence_header(bb, 1, 5, &hdr);
+
+	/* nonStandard */
+	if (asn1_per_bitmap_get(&hdr.present, 0)) {
+		count = asn1_per_read_length(bb, 0, UINT_MAX);
+		while (count > 0) {
+			h245_skip_nonstandard_param(bb);
+			if (bb->error)
+				return NF_ACCEPT;
+		}
+	}
+
+	/* sessionID */
+	if (asn1_per_bitmap_get(&hdr.present, 1))
+		asn1_per_read_unsigned(bb, 1, 255);
+
+	/* mediaChannel */
+	if (asn1_per_bitmap_get(&hdr.present, 2)) {
+		int ret;
+		unsigned i;
+		u_int32_t ip;
+		u_int16_t port;
+		int dir = CTINFO2DIR(ctinfo);
+		struct ip_conntrack_expect *exp;
+
+		ret = h245_parse_transport_address(bb, &i, &ip, &port);
+		DEBUGP("entering mediaChannel ret=%d i=%u ip=%x port=%u\n",
+		       ret, i, ip, port);
+		if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+			/* match found: create an expectation */
+			exp = ip_conntrack_expect_alloc();
+			if (exp == NULL)
+				return NF_ACCEPT;
+
+			exp->tuple = ((struct ip_conntrack_tuple)
+					{ { ct->tuplehash[!dir].tuple.src.ip,
+					    { 0 } },
+					  { ct->tuplehash[!dir].tuple.dst.ip,
+					    { .udp = { port } },
+					    IPPROTO_UDP }});
+			exp->mask = ((struct ip_conntrack_tuple)
+					{ { 0xFFFFFFFF, { 0 } },
+					  { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+			exp->master = ct;
+
+			/* call NAT hook and register expectation */
+			if (ip_nat_h245_hook != NULL) {
+				ret = ip_nat_h245_hook(pskb, ctinfo, i, exp);
+				if (ret != NF_ACCEPT)
+					return ret;
+			} else {
+				/* Can't expect this?  Best to drop packet now. */
+				if (ip_conntrack_expect_related(exp) != 0) {
+					ip_conntrack_expect_free(exp);
+					return NF_DROP;
+				} else {
+					return NF_ACCEPT;
+				}
+			}
+		}
+	}
+
+	/* mediaControlChannel */
+	if (asn1_per_bitmap_get(&hdr.present, 3)) {
+		int ret;
+		unsigned i;
+		u_int32_t ip;
+		u_int16_t port;
+		int dir = CTINFO2DIR(ctinfo);
+		struct ip_conntrack_expect *exp;
+
+		ret = h245_parse_transport_address(bb, &i, &ip, &port);
+		DEBUGP("entering mediaControlChannel ret=%d i=%u ip=%x port=%u\n",
+		       ret, i, ip, port);
+		if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+			/* match found: create an expectation */
+			exp = ip_conntrack_expect_alloc();
+			if (exp == NULL)
+				return NF_ACCEPT;
+
+			exp->tuple = ((struct ip_conntrack_tuple)
+					{ { ct->tuplehash[!dir].tuple.src.ip,
+					    { 0 } },
+					  { ct->tuplehash[!dir].tuple.dst.ip,
+					    { .udp = { port } },
+					    IPPROTO_UDP }});
+			exp->mask = ((struct ip_conntrack_tuple)
+					{ { 0xFFFFFFFF, { 0 } },
+					  { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+			exp->master = ct;
+
+			/* call NAT hook and register expectation */
+			if (ip_nat_h245_hook != NULL) {
+				ret = ip_nat_h245_hook(pskb, ctinfo, i, exp);
+				if (ret != NF_ACCEPT)
+					return ret;
+			} else {
+				/* Can't expect this?  Best to drop packet now. */
+				if (ip_conntrack_expect_related(exp) != 0) {
+					ip_conntrack_expect_free(exp);
+					return NF_DROP;
+				} else {
+					return NF_ACCEPT;
+				}
+			}
+		}
+	}
+
+	/* dynamicRTPPayloadType */
+	if (asn1_per_bitmap_get(&hdr.present, 1))
+		asn1_per_read_unsigned(bb, 96, 127);
+
+	asn1_per_skip_sequence_extension(bb, &hdr);
+
+	return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 OpenLogicalChannelAck response packet and handle
+ * NAT/expectations for the logical channel address.
+ */
+static int h245_parse_open_lchannel_ack(struct sk_buff **pskb,
+					struct ip_conntrack *ct,
+					enum ip_conntrack_info ctinfo,
+					struct asn1_per_buffer *bb) {
+	struct asn1_per_sequence_header hdr, hdr2;
+	struct asn1_per_sequence_extension_header ext;
+	unsigned forwardLogicalChannelNumber;
+	unsigned choice, after, after2, i;
+
+	asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+	forwardLogicalChannelNumber = asn1_per_read_unsigned(bb, 1, 65535);
+	DEBUGP("forwardLogicalChannelNumber=%u\n", forwardLogicalChannelNumber);
+
+	/* reverseLogicalChannelParameters */
+	if (asn1_per_bitmap_get(&hdr.present, 0)) {
+		DEBUGP("reverseLogicalChannelParameters present\n");
+		asn1_per_read_sequence_header(bb, 1, 2, &hdr2);
+
+		/* reverseLogicalChannelNumber */
+		asn1_per_read_unsigned(bb, 1, 65535);
+
+		/* portNumber */
+		if (asn1_per_bitmap_get(&hdr.present, 0))
+			asn1_per_read_unsigned(bb, 0, 65535);
+
+		/* multiplexParameters */
+		if (asn1_per_bitmap_get(&hdr2.present, 1)) {
+			choice = asn1_per_read_choice_header(bb, 1, 1, &after);
+			if (bb->error)
+				return NF_ACCEPT;
+
+			switch (choice) {
+			case 0: /* h222LogicalChannelParameters */
+				h245_parse_h222_lchannel_params(pskb, ct,
+								ctinfo, bb);
+				break;
+			case 1: /* h2250LogicalChannelParameters */
+				h245_parse_h2250_lchannel_params(pskb, ct,
+								 ctinfo, bb);
+				break;
+			default:
+				if (after == 0) {
+					DEBUGP("unsupported multiplex_parameter %u\n", choice);
+					bb->error = 1;
+					return NF_ACCEPT;
+				}
+			}
+
+			if (bb->error)
+				return NF_ACCEPT;
+
+			if (after > 0)
+				bb->i = after;
+		}
+
+		asn1_per_skip_sequence_extension(bb, &hdr2);
+	}
+
+	asn1_per_read_sequence_extension_header(bb, &hdr, &ext);
+	if (bb->error)
+		return NF_ACCEPT;
+
+	/* separateStack */
+	if (asn1_per_bitmap_get(&ext.present, 0))
+		asn1_per_skip_octet_string(bb);
+
+	/* forwardMultiplexAckParameters */
+	if (asn1_per_bitmap_get(&ext.present, 1)) {
+		DEBUGP("forwardMultiplexAckParameters present\n");
+
+		after = asn1_per_read_octet_string_header(bb);
+		DEBUGP("forwardMultiplexAckParameters present length=%u i=%u after=%u end=%u\n",
+		       after, bb->i, bb->i + after, bb->length);
+		after += bb->i;
+
+		choice = asn1_per_read_choice_header(bb, 1, 1, &after2);
+		if (bb->error)
+			return NF_ACCEPT;
+
+		DEBUGP("entering forwardMultiplexAckParameters choice=%u after=%u\n", choice, after2);
+
+		switch (choice) {
+		case 0: /* h2250LogicalChannelAckParameters */
+			h245_parse_h2250_lchannel_ack_params(pskb, ct,
+							     ctinfo, bb);
+			break;
+		}
+
+		if (bb->error)
+			return NF_ACCEPT;
+
+		bb->i = after;
+	}
+
+	for (i = 2; i < ext.count; i++)
+		if (asn1_per_bitmap_get(&ext.present, i))
+			asn1_per_skip_octet_string(bb);
+
+	return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 response packet and handle NAT/expectations for the
+ * logical channel address.
+ */
+static int h245_parse_response(struct sk_buff **pskb,
+			       struct ip_conntrack *ct,
+			       enum ip_conntrack_info ctinfo,
+			       struct asn1_per_buffer *bb) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 19, &after);
+	DEBUGP("H.245: response type=%u\n", choice);
+	switch (choice) {
+	case 5: /* openLogicalChannelAck */
+		return h245_parse_open_lchannel_ack(pskb, ct, ctinfo, bb);
+
+	default:
+		return NF_ACCEPT;
+	}
+}
+
+/**
+ * Parse an H.245 packet and handle NAT/expectations for the logical
+ * channel address.
+ */
+static int h245_parse(struct sk_buff **pskb,
+		      struct ip_conntrack *ct,
+		      enum ip_conntrack_info ctinfo,
+		      struct asn1_per_buffer *bb) {
+	unsigned choice, after;
+
+	choice = asn1_per_read_choice_header(bb, 1, 4, &after);
+	DEBUGP("H.245: message_class=%u\n", choice);
+	switch (choice) {
+	case 0:
+		return h245_parse_request(pskb, ct, ctinfo, bb);
+	case 1:
+		return h245_parse_response(pskb, ct, ctinfo, bb);
+	default:
+		return NF_ACCEPT;
+	}
+}
+
+/**
+ * Parse a TPKT/H.245 packet and handle NAT/expectations for the
+ * logical channel transport address (if applicable).
+ */
+static int h245_parse_tpkt(struct sk_buff **pskb,
+			   struct ip_conntrack *ct,
+			   enum ip_conntrack_info ctinfo,
+			   const unsigned char *data,
+			   unsigned datalen) {
+	unsigned int i = 0;
+	u_int16_t tpkt_len;
+	struct asn1_per_buffer bb;
+
+	if (i + 4 > datalen)
+		return NF_ACCEPT;
+
+	/* expect TPKT header, see RFC 1006 */
+	if (data[0] != 0x03 || data[1] != 0x00)
+		return NF_ACCEPT;
+
+	i += 2;
+
+	tpkt_len = ntohs(*(u_int16_t*)(data + i));
+	if (tpkt_len < datalen)
+		datalen = tpkt_len;
+
+	i += 2;
+
+	/* parse H.245 packet (ASN.1 PER) */
+	asn1_per_initialize(&bb, data, datalen, i);
+
+	return h245_parse(pskb, ct, ctinfo, &bb);
+}
+
+static int h245_help(struct sk_buff **pskb,
+		     struct ip_conntrack *ct,
+		     enum ip_conntrack_info ctinfo)
+{
+	struct tcphdr _tcph, *tcph;
+	unsigned char *data;
+	unsigned dataoff, datalen;
+	int ret;
+
+	/* Until there's been traffic both ways, don't look in packets. */
+	if (ctinfo != IP_CT_ESTABLISHED
+	    && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+		DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
+		return NF_ACCEPT;
+	}
+
+	tcph = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+				  sizeof(_tcph), &_tcph);
+	if (tcph == NULL)
+		return NF_ACCEPT;
+
+	DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+		NIPQUAD((*pskb)->nh.iph->saddr), ntohs(tcph->source),
+		NIPQUAD((*pskb)->nh.iph->daddr), ntohs(tcph->dest));
+
+	dataoff = (*pskb)->nh.iph->ihl*4 + tcph->doff*4;
+	/* No data? */
+	if (dataoff >= (*pskb)->len) {
+		DEBUGP("ct_h245_help: skblen = %u\n", (*pskb)->len);
+		return NF_ACCEPT;
+	}
+	datalen = (*pskb)->len - dataoff;
+
+	if (datalen < 16)
+		return NF_ACCEPT;
+
+	spin_lock_bh(&ip_h245_lock);
+	data = skb_header_pointer((*pskb), dataoff,
+				  datalen, h245_buffer);
+	BUG_ON(data == NULL);
+
+	ret = h245_parse_tpkt(pskb, ct, ctinfo,
+			      data, datalen);
+
+	spin_unlock_bh(&ip_h245_lock);
+	return ret;
+}
+
+/* H.245 helper is not registered! */
+static struct ip_conntrack_helper h245 =
+{
+	.name = "H.245",
+	.max_expected = 8,
+	.timeout = 240,
+	.tuple = { .dst = { .protonum = IPPROTO_TCP } },
+	.mask = { .src = { .u = { 0xFFFF } },
+		  .dst = { .protonum = 0xFF } },
+	.help = h245_help
+};
+
+void ip_conntrack_h245_expect(struct ip_conntrack *new,
+			      struct ip_conntrack_expect *this)
+{
+	write_lock_bh(&ip_conntrack_lock);
+	new->helper = &h245;
+	DEBUGP("h225_expect: helper for %p added\n", new);
+	write_unlock_bh(&ip_conntrack_lock);
+}
+EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_h323.c pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_h323.c
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_h323.c	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/ip_nat_h323.c	2005-07-23 22:44:56.000000000 +0200
@@ -0,0 +1,196 @@
+/*
+ * H.323 'brute force' extension for NAT alteration.
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ *
+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
+ * (http://www.coritel.it/projects/sofia/nat.html)
+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
+ * the unregistered helpers to the conntrack entries.
+ */
+
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
+MODULE_LICENSE("GPL");
+
+struct module *ip_nat_h323 = THIS_MODULE;
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static void ip_nat_h225_signal(struct sk_buff **pskb,
+			       struct ip_conntrack *ct,
+			       enum ip_conntrack_info ctinfo,
+			       unsigned int offset,
+			       int dir,
+			       int orig_dir)
+{
+	struct {
+		u_int32_t ip;
+		u_int16_t port;
+	} __attribute__ ((__packed__)) newdata;
+
+	/* Change address inside packet to match way we're mapping
+	   this connection. */
+	if (dir == IP_CT_DIR_ORIGINAL) {
+		newdata.ip = ct->tuplehash[!orig_dir].tuple.dst.ip;
+		newdata.port = ct->tuplehash[!orig_dir].tuple.dst.u.tcp.port;
+	} else {
+		newdata.ip = ct->tuplehash[!orig_dir].tuple.src.ip;
+		newdata.port = ct->tuplehash[!orig_dir].tuple.src.u.tcp.port;
+	}
+
+	/* Modify the packet */
+	ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+				 offset,
+				 sizeof(newdata),
+				 (const char*)&newdata, sizeof(newdata));
+}
+
+/**
+ * This conntrack expect function replaces ip_conntrack_h245_expect()
+ * which was set by ip_conntrack_h323.c. It calls both
+ * ip_nat_follow_master() and ip_conntrack_h245_expect().
+ */
+static void ip_nat_h245_expect(struct ip_conntrack *new,
+			       struct ip_conntrack_expect *this)
+{
+	ip_nat_follow_master(new, this);
+	ip_conntrack_h245_expect(new, this);
+}
+
+static int ip_nat_h225(struct sk_buff **pskb,
+		       enum ip_conntrack_info ctinfo,
+		       unsigned int offset,
+		       struct ip_conntrack_expect *exp)
+{
+	u_int16_t port;
+	struct {
+		u_int32_t ip;
+		u_int16_t port;
+	} __attribute__ ((__packed__)) newdata;
+	int dir = CTINFO2DIR(ctinfo);
+	struct ip_conntrack *ct = exp->master;
+	int ret;
+
+	/* Connection will come from wherever this packet goes, hence !dir */
+	newdata.ip = ct->tuplehash[!dir].tuple.dst.ip;
+	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+	exp->dir = !dir;
+
+	/* When you see the packet, we need to NAT it the same as the
+	 * this one. */
+	BUG_ON(exp->expectfn != ip_conntrack_h245_expect);
+	exp->expectfn = ip_nat_h245_expect;
+
+	/* Try to get same port: if not, try to change it. */
+	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+		exp->tuple.dst.u.tcp.port = htons(port);
+		if (ip_conntrack_expect_related(exp) == 0)
+			break;
+	}
+
+	if (port == 0) {
+		ip_conntrack_expect_free(exp);
+		return NF_DROP;
+	}
+
+	newdata.port = htons(port);
+
+	/* now mangle packet */
+	ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+				       offset,
+				       sizeof(newdata),
+				       (const char*)&newdata, sizeof(newdata));
+	if (!ret)
+		return NF_DROP;
+
+	return NF_ACCEPT;
+}
+
+static int ip_nat_h245(struct sk_buff **pskb,
+		       enum ip_conntrack_info ctinfo,
+		       unsigned int offset,
+		       struct ip_conntrack_expect *exp)
+{
+	u_int16_t port;
+	struct {
+		u_int32_t ip;
+		u_int16_t port;
+	} __attribute__ ((__packed__)) newdata;
+	int dir = CTINFO2DIR(ctinfo);
+	struct ip_conntrack *ct = exp->master;
+	int ret;
+
+	/* Connection will come from wherever this packet goes, hence !dir */
+	newdata.ip = ct->tuplehash[!dir].tuple.dst.ip;
+	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+	exp->dir = !dir;
+
+	/* When you see the packet, we need to NAT it the same as the
+	 * this one. */
+	exp->expectfn = ip_nat_follow_master;
+
+	/* Try to get same port: if not, try to change it. */
+	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+		exp->tuple.dst.u.tcp.port = htons(port);
+		if (ip_conntrack_expect_related(exp) == 0)
+			break;
+	}
+
+	if (port == 0) {
+		ip_conntrack_expect_free(exp);
+		return NF_DROP;
+	}
+
+	newdata.port = htons(port);
+
+	/* now mangle packet */
+	ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+				       offset,
+				       sizeof(newdata),
+				       (const char*)&newdata, sizeof(newdata));
+	if (!ret)
+		return NF_DROP;
+
+	return NF_ACCEPT;
+}
+
+static int __init init(void)
+{
+	BUG_ON(ip_nat_h225_hook != NULL);
+	BUG_ON(ip_nat_h245_hook != NULL);
+
+	ip_nat_h225_hook = ip_nat_h225;
+	ip_nat_h225_signal_hook = ip_nat_h225_signal;
+	ip_nat_h245_hook = ip_nat_h245;
+
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	ip_nat_h225_hook = NULL;
+	ip_nat_h225_signal_hook = NULL;
+	ip_nat_h245_hook = NULL;
+}
+
+module_init(init);
+module_exit(fini);
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Kconfig.ladd	2005-07-03 22:40:12.000000000 +0200
@@ -0,0 +1,17 @@
+config IP_NF_NAT_H323
+	tristate
+	depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
+	default IP_NF_NAT if IP_NF_H323=y
+	default m if IP_NF_H323=m
+
+config IP_NF_H323
+	tristate  'H.323 (netmeeting) support'
+	depends on IP_NF_CONNTRACK
+	help
+	  H.323 is a standard signalling protocol used by teleconferencing
+	  softwares like netmeeting. With the ip_conntrack_h323 and
+	  the ip_nat_h323 modules you can support the protocol on a connection
+	  tracking/NATing firewall.
+	
+	  If you want to compile it as a module, say 'M' here and read
+	  Documentation/modules.txt.  If unsure, say 'N'.
diff -Nrup pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd
--- pom-ng-svn/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ pom-ng-h323/patchlets/h323-conntrack-nat/linux-2.6.12/net/ipv4/netfilter/Makefile.ladd	2005-07-03 22:40:12.000000000 +0200
@@ -0,0 +1,7 @@
+obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
+ 
+# H.323 support
+obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
+ip_conntrack_h323-objs := ip_conntrack_h323_core.o ip_conntrack_h323_h225.o ip_conntrack_h323_h245.o asn1_per.o
+obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
+

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: lockhelp.h missing
  2005-07-23 20:52       ` Sven Schuster
@ 2005-07-26 18:25         ` Jérôme Poulin
       [not found]         ` <debc30fc05072611231d179fae@mail.gmail.com>
  1 sibling, 0 replies; 7+ messages in thread
From: Jérôme Poulin @ 2005-07-26 18:25 UTC (permalink / raw)
  To: netfilter-devel

Just finished testing and the 2 patches works perfectly on
2.6.13-rc3-mm1 ! Apply with no warning and works, thanks :)

On 7/23/05, Sven Schuster <schuster.sven@gmx.de> wrote:
> 
> Hi Jérôme,
> 
> On Sat, Jul 23, 2005 at 05:38:23AM -0400, Jérôme Poulin told us:
> > Thanks, MMS compiled without any error or warning, h323 still misses
> > the file on its side.
> 
> here is a patch against current pom-ng svn to update h323-conntrack-nat
> for current kernels. Please apply to your pom-ng and test it. Compile-
> tested with 2.6.13-rc3-mm1.
> 
> 
> Kind regards,
> 
> Sven
> 
> --
> Linux zion 2.6.13-rc3-mm1 #6 PREEMPT Mon Jul 18 19:42:52 CEST 2005 i686 athlon i386 GNU/Linux
>  22:50:36 up 1 day,  6:00,  2 users,  load average: 0.36, 0.48, 0.27
> 
> 
>

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

* Re: lockhelp.h missing
       [not found]         ` <debc30fc05072611231d179fae@mail.gmail.com>
@ 2005-07-26 18:47           ` Sven Schuster
  0 siblings, 0 replies; 7+ messages in thread
From: Sven Schuster @ 2005-07-26 18:47 UTC (permalink / raw)
  To: Jérôme Poulin; +Cc: netfilter-devel

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


Hi Jérôme,

On Tue, Jul 26, 2005 at 02:23:57PM -0400, Jérôme Poulin told us:
> Just finished testing and the 2 patches works perfectly on
> 2.6.13-rc3-mm1 ! Apply with no warning and works, thanks :)

nice to hear that it works. So I can now send the patches for
applying to svn :-)


Sven

-- 
Linux zion 2.6.13-rc3-mm1 #12 PREEMPT Sun Jul 24 02:04:45 CEST 2005 i686 athlon i386 GNU/Linux
 20:45:43 up 1 day, 20:55,  1 user,  load average: 0.00, 0.00, 0.00

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

end of thread, other threads:[~2005-07-26 18:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-22  5:34 lockhelp.h missing Jérôme Poulin
2005-07-22  5:56 ` Patrick McHardy
2005-07-22 12:52   ` Sven Schuster
     [not found]     ` <debc30fc0507230238427b0290@mail.gmail.com>
2005-07-23 20:25       ` Sven Schuster
2005-07-23 20:52       ` Sven Schuster
2005-07-26 18:25         ` Jérôme Poulin
     [not found]         ` <debc30fc05072611231d179fae@mail.gmail.com>
2005-07-26 18:47           ` Sven Schuster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.