diff --git a/openwrt/target/linux/linux-2.4/config/brcm b/openwrt/target/linux/linux-2.4/config/brcm
index 94a9018ec865588db9ca95b982690fd65df1cd68..8bd18cf14d58ce2ded05579d3bbfd33d7c11bb05 100644
--- a/openwrt/target/linux/linux-2.4/config/brcm
+++ b/openwrt/target/linux/linux-2.4/config/brcm
@@ -363,6 +363,7 @@ CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_CT_PROTO_GRE=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_H323=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_MATCH_LIMIT=m
@@ -412,6 +413,7 @@ CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_NAT_PPTP=m
 CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_NAT_PROTO_GRE=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_SNMP_BASIC=m
diff --git a/openwrt/target/linux/linux-2.4/config/x86 b/openwrt/target/linux/linux-2.4/config/x86
index bc139cc3a8c2f8f34887ba6d24f19db2d0ef1df2..335823199b842d1d0009ca99be0f2bdaf9073c7c 100644
--- a/openwrt/target/linux/linux-2.4/config/x86
+++ b/openwrt/target/linux/linux-2.4/config/x86
@@ -287,6 +287,7 @@ CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_CT_PROTO_GRE=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_H323=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_MATCH_LIMIT=m
@@ -336,6 +337,7 @@ CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_NAT_PPTP=m
 CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_NAT_PROTO_GRE=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_SNMP_BASIC=m
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/614-netfilter_nat_h323.patch b/openwrt/target/linux/linux-2.4/patches/generic/614-netfilter_nat_h323.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e5f0dfb342b45fad7e9c3cb73993a58bec08910c
--- /dev/null
+++ b/openwrt/target/linux/linux-2.4/patches/generic/614-netfilter_nat_h323.patch
@@ -0,0 +1,821 @@
+diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32/net/ipv4/netfilter/Config.in
+--- linux-2.4.32/net/ipv4/netfilter/Config.in	2005-12-12 11:13:17.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/Config.in	2005-12-12 11:18:47.000000000 +0100
+@@ -16,6 +16,7 @@
+   dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
+   dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+   dep_tristate '  SIP protocol support' CONFIG_IP_NF_SIP $CONFIG_IP_NF_CONNTRACK
++  dep_tristate '  H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
+ fi
+ 
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+@@ -112,6 +113,13 @@
+ 	  define_tristate CONFIG_IP_NF_NAT_SIP $CONFIG_IP_NF_NAT
+ 	fi
+       fi
++      if [ "$CONFIG_IP_NF_H323" = "m" ]; then
++	define_tristate CONFIG_IP_NF_NAT_H323 m
++      else
++	if [ "$CONFIG_IP_NF_H323" = "y" ]; then
++	  define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
++	fi
++      fi
+       if [ "$CONFIG_IP_NF_AMANDA" = "m" ]; then
+         define_tristate CONFIG_IP_NF_NAT_AMANDA m
+       else
+diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32/net/ipv4/netfilter/Makefile
+--- linux-2.4.32/net/ipv4/netfilter/Makefile	2005-12-12 11:13:17.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/Makefile	2005-12-12 11:17:37.000000000 +0100
+@@ -57,6 +57,10 @@
+ ifdef CONFIG_IP_NF_NAT_SIP
+         export-objs += ip_conntrack_sip.o
+ endif
++obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
++ifdef CONFIG_IP_NF_NAT_H323
++	export-objs += ip_conntrack_h323.o
++endif
+ 
+ 
+ # NAT helpers 
+@@ -67,6 +71,7 @@
+ obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
+ obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
+ obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
++obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
+ 
+ # generic IP tables 
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c	2005-12-12 11:14:54.000000000 +0100
+@@ -0,0 +1,302 @@
++/* 
++ * H.323 'brute force' extension for H.323 connection tracking. 
++ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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/lockhelp.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");
++
++DECLARE_LOCK(ip_h323_lock);
++struct module *ip_conntrack_h323 = THIS_MODULE;
++
++#define DEBUGP(format, args...)
++
++static int h245_help(const struct iphdr *iph, size_t len,
++		     struct ip_conntrack *ct,
++		     enum ip_conntrack_info ctinfo)
++{
++	struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
++	unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
++	unsigned char *data_limit;
++	u_int32_t tcplen = len - iph->ihl * 4;
++	u_int32_t datalen = tcplen - tcph->doff * 4;
++	int dir = CTINFO2DIR(ctinfo);
++	struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
++	struct ip_conntrack_expect expect, *exp = &expect;
++	struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
++	u_int16_t data_port;
++	u_int32_t data_ip;
++	unsigned int i;
++
++	DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
++		NIPQUAD(iph->saddr), ntohs(tcph->source),
++		NIPQUAD(iph->daddr), ntohs(tcph->dest));
++
++	/* Can't track connections formed before we registered */
++	if (!info)
++		return 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_h245_help: Conntrackinfo = %u\n", ctinfo);
++		return NF_ACCEPT;
++	}
++
++	/* Not whole TCP header or too short packet? */
++	if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
++		DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
++		return NF_ACCEPT;
++	}
++
++	/* Checksum invalid?  Ignore. */
++	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++			      csum_partial((char *)tcph, tcplen, 0))) {
++		DEBUGP("ct_h245_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;
++	}
++
++	data_limit = (unsigned char *) data + datalen;
++	/* bytes: 0123   45
++	          ipadrr port */
++	for (i = 0; data < (data_limit - 5); data++, i++) {
++		memcpy(&data_ip, data, sizeof(u_int32_t));
++		if (data_ip == iph->saddr) {
++			memcpy(&data_port, data + 4, sizeof(u_int16_t));
++			memset(&expect, 0, sizeof(expect));
++			/* 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(iph->saddr), ntohs(data_port));
++			LOCK_BH(&ip_h323_lock);
++			info->is_h225 = H225_PORT + 1;
++			exp_info->port = data_port;
++			exp_info->dir = dir;
++			exp_info->offset = i;
++
++			exp->seq = ntohl(tcph->seq) + i;
++		    
++			exp->tuple = ((struct ip_conntrack_tuple)
++				{ { ct->tuplehash[!dir].tuple.src.ip,
++				    { 0 } },
++				  { data_ip,
++				    { data_port },
++				    IPPROTO_UDP }});
++			exp->mask = ((struct ip_conntrack_tuple)
++				{ { 0xFFFFFFFF, { 0 } },
++				  { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
++	
++			exp->expectfn = NULL;
++			
++			/* Ignore failure; should only happen with NAT */
++			ip_conntrack_expect_related(ct, exp);
++
++			UNLOCK_BH(&ip_h323_lock);
++		}
++	}
++
++	return NF_ACCEPT;
++
++}
++
++/* H.245 helper is not registered! */
++static struct ip_conntrack_helper h245 = 
++	{ { NULL, NULL },
++          "H.245",				/* name */
++          IP_CT_HELPER_F_REUSE_EXPECT,		/* flags */
++          NULL,					/* module */
++          8,					/* max_ expected */
++          240,					/* timeout */
++          { { 0, { 0 } },			/* tuple */
++            { 0, { 0 }, IPPROTO_TCP } },
++          { { 0, { 0xFFFF } },			/* mask */
++            { 0, { 0 }, 0xFFFF } },
++          h245_help				/* helper */
++	};
++
++static int h225_expect(struct ip_conntrack *ct)
++{
++	WRITE_LOCK(&ip_conntrack_lock);
++	ct->helper = &h245;
++	DEBUGP("h225_expect: helper for %p added\n", ct);
++	WRITE_UNLOCK(&ip_conntrack_lock);
++	
++	return NF_ACCEPT;	/* unused */
++}
++
++static int h225_help(const struct iphdr *iph, size_t len,
++		     struct ip_conntrack *ct,
++		     enum ip_conntrack_info ctinfo)
++{
++	struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
++	unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
++	unsigned char *data_limit;
++	u_int32_t tcplen = len - iph->ihl * 4;
++	u_int32_t datalen = tcplen - tcph->doff * 4;
++	int dir = CTINFO2DIR(ctinfo);
++	struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
++	struct ip_conntrack_expect expect, *exp = &expect;
++	struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
++	u_int16_t data_port;
++	u_int32_t data_ip;
++	unsigned int i;
++	
++	DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
++		NIPQUAD(iph->saddr), ntohs(tcph->source),
++		NIPQUAD(iph->daddr), ntohs(tcph->dest));
++
++	/* Can't track connections formed before we registered */
++	if (!info)
++		return 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;
++	}
++
++	/* Not whole TCP header or too short packet? */
++	if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
++		DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
++		return NF_ACCEPT;
++	}
++
++	/* Checksum invalid?  Ignore. */
++	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++			      csum_partial((char *)tcph, tcplen, 0))) {
++		DEBUGP("ct_h225_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;
++	}
++	
++	data_limit = (unsigned char *) data + datalen;
++	/* bytes: 0123   45
++	          ipadrr port */
++	for (i = 0; data < (data_limit - 5); data++, i++) {
++		memcpy(&data_ip, data, sizeof(u_int32_t));
++		if (data_ip == iph->saddr) {
++			memcpy(&data_port, data + 4, sizeof(u_int16_t));
++			if (data_port == tcph->source) {
++				/* Signal address */
++				DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
++					NIPQUAD(iph->saddr));
++				/* Update the H.225 info so that NAT can mangle the address/port
++				   even when we have no expected connection! */
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++				LOCK_BH(&ip_h323_lock);
++				info->dir = dir;
++				info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
++				info->offset[IP_CT_DIR_ORIGINAL] = i;
++				UNLOCK_BH(&ip_h323_lock);
++#endif
++			} else {
++				memset(&expect, 0, sizeof(expect));
++
++				/* update the H.225 info */
++				LOCK_BH(&ip_h323_lock);
++				info->is_h225 = H225_PORT;
++				exp_info->port = data_port;
++				exp_info->dir = dir;
++				exp_info->offset = i;
++
++				exp->seq = ntohl(tcph->seq) + i;
++
++				exp->tuple = ((struct ip_conntrack_tuple)
++					{ { ct->tuplehash[!dir].tuple.src.ip,
++					    { 0 } },
++					  { data_ip,
++					    { data_port },
++					    IPPROTO_TCP }});
++				exp->mask = ((struct ip_conntrack_tuple)
++					{ { 0xFFFFFFFF, { 0 } },
++					  { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
++	
++				exp->expectfn = h225_expect;
++				
++				/* Ignore failure */
++				ip_conntrack_expect_related(ct, exp);
++
++				DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
++					NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
++					NIPQUAD(iph->saddr), ntohs(data_port));
++
++				UNLOCK_BH(&ip_h323_lock);
++                	}  
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++		} else if (data_ip == iph->daddr) {
++			memcpy(&data_port, data + 4, sizeof(u_int16_t));
++			if (data_port == tcph->dest) {
++				/* Signal address */
++				DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
++					NIPQUAD(iph->daddr));
++				/* Update the H.225 info so that NAT can mangle the address/port
++				   even when we have no expected connection! */
++				LOCK_BH(&ip_h323_lock);
++				info->dir = dir;
++				info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
++				info->offset[IP_CT_DIR_REPLY] = i;
++				UNLOCK_BH(&ip_h323_lock);
++			}
++#endif
++		}
++	}
++
++	return NF_ACCEPT;
++
++}
++
++static struct ip_conntrack_helper h225 = 
++	{ { NULL, NULL },
++	  "H.225",					/* name */
++	  IP_CT_HELPER_F_REUSE_EXPECT,			/* flags */
++	  THIS_MODULE,					/* module */
++	  2,						/* max_expected */
++	  240,						/* timeout */
++	  { { 0, { __constant_htons(H225_PORT) } },	/* tuple */
++	    { 0, { 0 }, IPPROTO_TCP } },
++	  { { 0, { 0xFFFF } },				/* mask */
++	    { 0, { 0 }, 0xFFFF } },
++	  h225_help					/* helper */
++	};
++
++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);
++}
++
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++EXPORT_SYMBOL(ip_h323_lock);
++#endif
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c /linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c
+--- linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c	2005-12-12 11:14:54.000000000 +0100
+@@ -0,0 +1,403 @@
++/* 
++ * H.323 'brute force' extension for NAT alteration. 
++ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ *
++ * 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/lockhelp.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");
++
++DECLARE_LOCK_EXTERN(ip_h323_lock);
++struct module *ip_nat_h323 = THIS_MODULE;
++
++#define DEBUGP(format, args...)
++
++
++static unsigned int 
++h225_nat_expected(struct sk_buff **pskb,
++		  unsigned int hooknum,
++		  struct ip_conntrack *ct,
++		  struct ip_nat_info *info);
++
++static unsigned int h225_nat_help(struct ip_conntrack *ct,
++				  struct ip_conntrack_expect *exp,
++			 	  struct ip_nat_info *info,
++			 	  enum ip_conntrack_info ctinfo,
++			 	  unsigned int hooknum,
++			 	  struct sk_buff **pskb);
++		  
++static struct ip_nat_helper h245 = 
++	{ { NULL, NULL },
++          "H.245",				/* name */
++	  0,					/* flags */
++	  NULL,					/* module */
++	  { { 0, { 0 } },			/* tuple */
++	    { 0, { 0 }, IPPROTO_TCP } },
++	  { { 0, { 0xFFFF } },			/* mask */
++	    { 0, { 0 }, 0xFFFF } },
++	  h225_nat_help,			/* helper */
++	  h225_nat_expected			/* expectfn */
++	};
++
++static unsigned int
++h225_nat_expected(struct sk_buff **pskb,
++		  unsigned int hooknum,
++		  struct ip_conntrack *ct,
++		  struct ip_nat_info *info)
++{
++	struct ip_nat_multi_range mr;
++	u_int32_t newdstip, newsrcip, newip;
++	u_int16_t port;
++	struct ip_ct_h225_expect *exp_info;
++	struct ip_ct_h225_master *master_info;
++	struct ip_conntrack *master = master_ct(ct);
++	unsigned int is_h225, ret;
++	
++	IP_NF_ASSERT(info);
++	IP_NF_ASSERT(master);
++
++	IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
++
++	DEBUGP("h225_nat_expected: We have a connection!\n");
++	master_info = &ct->master->expectant->help.ct_h225_info;
++	exp_info = &ct->master->help.exp_h225_info;
++
++	LOCK_BH(&ip_h323_lock);
++
++	DEBUGP("master: ");
++	DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++	DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
++	DEBUGP("conntrack: ");
++	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++	if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
++		/* Make connection go to the client. */
++		newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++		newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++		DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
++		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
++	} else {
++		/* Make the connection go to the server */
++		newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
++		newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++		DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
++		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
++	}
++	port = exp_info->port;
++	is_h225 = master_info->is_h225 == H225_PORT;
++	UNLOCK_BH(&ip_h323_lock);
++	
++	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
++		newip = newsrcip;
++	else
++		newip = newdstip;
++
++	DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
++
++	mr.rangesize = 1;
++	/* We don't want to manip the per-protocol, just the IPs... */
++	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
++	mr.range[0].min_ip = mr.range[0].max_ip = newip;
++
++	/* ... unless we're doing a MANIP_DST, in which case, make
++	   sure we map to the correct port */
++	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
++		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++		mr.range[0].min = mr.range[0].max
++			= ((union ip_conntrack_manip_proto)
++				{ port });
++	}
++
++	ret = ip_nat_setup_info(ct, &mr, hooknum);
++	
++	if (is_h225) {
++		DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
++		/* NAT expectfn called with ip_nat_lock write-locked */
++		info->helper = &h245;
++	}
++	return ret;
++}
++
++static int h323_signal_address_fixup(struct ip_conntrack *ct,
++			      	     struct sk_buff **pskb,
++			      	     enum ip_conntrack_info ctinfo)
++{
++	struct iphdr *iph = (*pskb)->nh.iph;
++	struct tcphdr *tcph = (void *)iph + iph->ihl*4;
++	unsigned char *data;
++	u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
++	u_int32_t datalen = tcplen - tcph->doff*4;
++	struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
++	u_int32_t newip;
++	u_int16_t port;
++	u_int8_t buffer[6];
++	int i;
++
++	MUST_BE_LOCKED(&ip_h323_lock);
++
++	DEBUGP("h323_signal_address_fixup: %s %s\n",
++		between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
++			? "yes" : "no",
++		between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
++			? "yes" : "no");
++	if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
++	      || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
++		return 1;
++
++	DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
++		info->offset[IP_CT_DIR_ORIGINAL], 
++		info->offset[IP_CT_DIR_REPLY],
++		tcplen);
++	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++
++	for (i = 0; i < IP_CT_DIR_MAX; i++) {
++		DEBUGP("h323_signal_address_fixup: %s %s\n",
++			info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
++			i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
++		if (!between(info->seq[i], ntohl(tcph->seq), 
++			     ntohl(tcph->seq) + datalen))
++			continue;
++		if (!between(info->seq[i] + 6, ntohl(tcph->seq),
++			     ntohl(tcph->seq) + datalen)) {
++			/* Partial retransmisison. It's a cracker being funky. */
++			if (net_ratelimit()) {
++				printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
++				     info->seq[i],
++				     ntohl(tcph->seq),
++				     ntohl(tcph->seq) + datalen);
++			}
++			return 0;
++		}
++
++		/* Change address inside packet to match way we're mapping
++		   this connection. */
++		if (i == IP_CT_DIR_ORIGINAL) {
++			newip = ct->tuplehash[!info->dir].tuple.dst.ip;
++			port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
++		} else {
++			newip = ct->tuplehash[!info->dir].tuple.src.ip;
++			port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
++		}
++
++		data = (char *) tcph + tcph->doff * 4 + info->offset[i];
++
++		DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
++			i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
++		        data[0], data[1], data[2], data[3],
++		        (data[4] << 8 | data[5]));
++
++		/* Modify the packet */
++		memcpy(buffer, &newip, 4);
++		memcpy(buffer + 4, &port, 2);
++		if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset[i],
++					      6, buffer, 6))
++			return 0;
++
++		DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
++			i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
++		        data[0], data[1], data[2], data[3],
++		        (data[4] << 8 | data[5]));
++	}
++
++	return 1;
++}
++
++static int h323_data_fixup(struct ip_ct_h225_expect *info,
++			   struct ip_conntrack *ct,
++			   struct sk_buff **pskb,
++			   enum ip_conntrack_info ctinfo,
++			   struct ip_conntrack_expect *expect)
++{
++	u_int32_t newip;
++	u_int16_t port;
++	u_int8_t buffer[6];
++	struct ip_conntrack_tuple newtuple;
++	struct iphdr *iph = (*pskb)->nh.iph;
++	struct tcphdr *tcph = (void *)iph + iph->ihl*4;
++	unsigned char *data;
++	u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
++	struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
++	int is_h225;
++
++	MUST_BE_LOCKED(&ip_h323_lock);
++	DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
++	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++
++	if (!between(expect->seq + 6, ntohl(tcph->seq),
++		    ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
++		/* Partial retransmisison. It's a cracker being funky. */
++		if (net_ratelimit()) {
++			printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
++			     expect->seq,
++			     ntohl(tcph->seq),
++			     ntohl(tcph->seq) + tcplen - tcph->doff * 4);
++		}
++		return 0;
++	}
++
++	/* Change address inside packet to match way we're mapping
++	   this connection. */
++	if (info->dir == IP_CT_DIR_REPLY) {
++		/* Must be where client thinks server is */
++		newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++		/* Expect something from client->server */
++		newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++		newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++	} else {
++		/* Must be where server thinks client is */
++		newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++		/* Expect something from server->client */
++		newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
++		newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++	}
++
++	is_h225 = (master_info->is_h225 == H225_PORT);
++
++	if (is_h225) {
++		newtuple.dst.protonum = IPPROTO_TCP;
++		newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
++	} else {
++		newtuple.dst.protonum = IPPROTO_UDP;
++		newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
++	}
++	
++	/* Try to get same port: if not, try to change it. */
++	for (port = ntohs(info->port); port != 0; port++) {
++		if (is_h225)
++			newtuple.dst.u.tcp.port = htons(port);
++		else
++			newtuple.dst.u.udp.port = htons(port);
++
++		if (ip_conntrack_change_expect(expect, &newtuple) == 0)
++			break;
++	}
++	if (port == 0) {
++		DEBUGP("h323_data_fixup: no free port found!\n");
++		return 0;
++	}
++
++	port = htons(port);
++
++	data = (char *) tcph + tcph->doff * 4 + info->offset;
++
++	DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
++	        data[0], data[1], data[2], data[3],
++	        (data[4] << 8 | data[5]));
++
++	/* Modify the packet */
++	memcpy(buffer, &newip, 4);
++	memcpy(buffer + 4, &port, 2);
++	if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset,
++				      6, buffer, 6))
++		return 0;
++	
++	DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
++	        data[0], data[1], data[2], data[3],
++	        (data[4] << 8 | data[5]));
++
++	return 1;
++}
++
++static unsigned int h225_nat_help(struct ip_conntrack *ct,
++				  struct ip_conntrack_expect *exp,
++			 	  struct ip_nat_info *info,
++			 	  enum ip_conntrack_info ctinfo,
++			 	  unsigned int hooknum,
++			 	  struct sk_buff **pskb)
++{
++	int dir;
++	struct ip_ct_h225_expect *exp_info;
++	
++	/* Only mangle things once: original direction in POST_ROUTING
++	   and reply direction on PRE_ROUTING. */
++	dir = CTINFO2DIR(ctinfo);
++	DEBUGP("nat_h323: dir %s at hook %s\n",
++	       dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++	       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++	       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++	       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
++	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
++	      || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
++		DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
++		       dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
++		       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
++		       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
++		       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
++		return NF_ACCEPT;
++	}
++
++	if (!exp) {
++		LOCK_BH(&ip_h323_lock);
++		if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
++			UNLOCK_BH(&ip_h323_lock);
++			return NF_DROP;
++		}
++		UNLOCK_BH(&ip_h323_lock);
++		return NF_ACCEPT;
++	}
++		
++	exp_info = &exp->help.exp_h225_info;
++
++	LOCK_BH(&ip_h323_lock);
++	if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
++		UNLOCK_BH(&ip_h323_lock);
++		return NF_DROP;
++	}
++	UNLOCK_BH(&ip_h323_lock);
++
++	return NF_ACCEPT;
++}
++
++static struct ip_nat_helper h225 = 
++	{ { NULL, NULL },
++	  "H.225",					/* name */
++	  IP_NAT_HELPER_F_ALWAYS, 			/* flags */
++	  THIS_MODULE,					/* module */
++	  { { 0, { __constant_htons(H225_PORT) } },	/* tuple */
++	    { 0, { 0 }, IPPROTO_TCP } },
++	  { { 0, { 0xFFFF } },				/* mask */
++	    { 0, { 0 }, 0xFFFF } },
++	  h225_nat_help,				/* helper */
++	  h225_nat_expected				/* expectfn */
++	};
++
++static int __init init(void)
++{
++	int ret;
++	
++	ret = ip_nat_helper_register(&h225);
++
++	if (ret != 0)
++		printk("ip_nat_h323: cannot initialize the module!\n");
++
++	return ret;
++}
++
++static void __exit fini(void)
++{
++	ip_nat_helper_unregister(&h225);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h	2005-12-12 11:13:17.000000000 +0100
++++ linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h	2005-12-12 11:16:13.000000000 +0100
+@@ -72,6 +72,7 @@
+ #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_sip.h>
++#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+ 
+ /* per expectation: application helper private data */
+ union ip_conntrack_expect_help {
+@@ -81,6 +82,7 @@
+ 	struct ip_ct_irc_expect exp_irc_info;
+ 	struct ip_ct_pptp_expect exp_pptp_info;
+ 	struct ip_ct_sip_expect exp_sip_info;
++	struct ip_ct_h225_expect exp_h225_info;
+ 
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+ 	union {
+@@ -96,6 +98,7 @@
+ 	struct ip_ct_irc_master ct_irc_info;
+ 	struct ip_ct_pptp_master ct_pptp_info;
+ 	struct ip_ct_sip_master ct_sip_info;
++	struct ip_ct_h225_master ct_h225_info;
+ };
+ 
+ #ifdef CONFIG_IP_NF_NAT_NEEDED
+diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h	2005-12-12 11:14:54.000000000 +0100
+@@ -0,0 +1,30 @@
++#ifndef _IP_CONNTRACK_H323_H
++#define _IP_CONNTRACK_H323_H
++/* H.323 connection tracking. */
++
++#ifdef __KERNEL__
++/* Protects H.323 related data */
++DECLARE_LOCK_EXTERN(ip_h323_lock);
++#endif
++
++/* Default H.225 port */
++#define H225_PORT	1720
++
++/* This structure is per expected connection */
++struct ip_ct_h225_expect {
++	u_int16_t port;			/* Port of the H.225 helper/RTCP/RTP channel */
++	enum ip_conntrack_dir dir;	/* Direction of the original connection */
++	unsigned int offset;		/* offset of the address in the payload */
++};
++
++/* This structure exists only once per master */
++struct ip_ct_h225_master {
++	int is_h225;				/* H.225 or H.245 connection */
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++	enum ip_conntrack_dir dir;		/* Direction of the original connection */
++	u_int32_t seq[IP_CT_DIR_MAX];		/* Exceptional packet mangling for signal addressess... */
++	unsigned int offset[IP_CT_DIR_MAX];	/* ...and the offset of the addresses in the payload */
++#endif
++};
++
++#endif /* _IP_CONNTRACK_H323_H */