diff options
Diffstat (limited to 'target')
| -rw-r--r-- | target/linux/linux-2.4/config/brcm | 2 | ||||
| -rw-r--r-- | target/linux/linux-2.4/config/x86 | 2 | ||||
| -rw-r--r-- | target/linux/linux-2.4/patches/generic/614-netfilter_nat_h323.patch | 821 | 
3 files changed, 825 insertions, 0 deletions
| diff --git a/target/linux/linux-2.4/config/brcm b/target/linux/linux-2.4/config/brcm index 94a9018ec..8bd18cf14 100644 --- a/target/linux/linux-2.4/config/brcm +++ b/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/target/linux/linux-2.4/config/x86 b/target/linux/linux-2.4/config/x86 index bc139cc3a..335823199 100644 --- a/target/linux/linux-2.4/config/x86 +++ b/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/target/linux/linux-2.4/patches/generic/614-netfilter_nat_h323.patch b/target/linux/linux-2.4/patches/generic/614-netfilter_nat_h323.patch new file mode 100644 index 000000000..e5f0dfb34 --- /dev/null +++ b/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 */ | 
