diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-06-26 20:42:18 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2010-06-26 20:42:18 +0000 |
commit | 95c5443b843c7875794c17aeba33213b71ba4dbb (patch) | |
tree | 0c25039640bb2607a15f2792558ea5b2b4c1a48d /target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch | |
parent | c4f3caef75c247bcce4502391c072e10f741430a (diff) | |
download | upstream-95c5443b843c7875794c17aeba33213b71ba4dbb.tar.gz upstream-95c5443b843c7875794c17aeba33213b71ba4dbb.tar.bz2 upstream-95c5443b843c7875794c17aeba33213b71ba4dbb.zip |
remove generic linux 2.4 support
SVN-Revision: 21948
Diffstat (limited to 'target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch')
-rw-r--r-- | target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch | 814 |
1 files changed, 0 insertions, 814 deletions
diff --git a/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch b/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch deleted file mode 100644 index 950516005f..0000000000 --- a/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch +++ /dev/null @@ -1,814 +0,0 @@ ---- a/net/ipv4/netfilter/Config.in -+++ b/net/ipv4/netfilter/Config.in -@@ -13,6 +13,7 @@ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; - dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK - dep_tristate ' Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK - dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES -+ dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK - fi - - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -@@ -80,6 +81,13 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; - define_tristate CONFIG_IP_NF_NAT_AMANDA $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_EXPERIMENTAL" = "y" ]; then - dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT - fi ---- a/net/ipv4/netfilter/Makefile -+++ b/net/ipv4/netfilter/Makefile -@@ -47,12 +47,17 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_ - ifdef CONFIG_IP_NF_IRC - export-objs += ip_conntrack_irc.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 - obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o - obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o - obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o - obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o -+obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o - - # generic IP tables - obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o ---- /dev/null -+++ b/net/ipv4/netfilter/ip_conntrack_h323.c -@@ -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); ---- /dev/null -+++ b/net/ipv4/netfilter/ip_nat_h323.c -@@ -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); ---- a/include/linux/netfilter_ipv4/ip_conntrack.h -+++ b/include/linux/netfilter_ipv4/ip_conntrack.h -@@ -67,6 +67,7 @@ union ip_conntrack_expect_proto { - - #include <linux/netfilter_ipv4/ip_conntrack_ftp.h> - #include <linux/netfilter_ipv4/ip_conntrack_irc.h> -+#include <linux/netfilter_ipv4/ip_conntrack_h323.h> - - /* per expectation: application helper private data */ - union ip_conntrack_expect_help { -@@ -74,6 +75,7 @@ union ip_conntrack_expect_help { - struct ip_ct_amanda_expect exp_amanda_info; - struct ip_ct_ftp_expect exp_ftp_info; - struct ip_ct_irc_expect exp_irc_info; -+ struct ip_ct_h225_expect exp_h225_info; - - #ifdef CONFIG_IP_NF_NAT_NEEDED - union { -@@ -87,6 +89,7 @@ union ip_conntrack_help { - /* insert conntrack helper private data (master) here */ - struct ip_ct_ftp_master ct_ftp_info; - struct ip_ct_irc_master ct_irc_info; -+ struct ip_ct_h225_master ct_h225_info; - }; - - #ifdef CONFIG_IP_NF_NAT_NEEDED ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h -@@ -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 */ |