| From: |
| Max Kellermann <max@duempel.org> |
| To: |
| netfilter-devel@lists.netfilter.org |
| Subject: |
| [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3
sources |
| Date: |
| Wed, 11 May 2005 00:52:55 +0200 |
| Cc: |
| laforge@gnumonks.org |
| Archive-link: |
| Article,
Thread
|
h323-04-split_conntrack_into_3.patch
- splitted ip_conntrack_h323.c into 3 sources
Tue May 10 23:26:46 CEST 2005 max@duempel.org
* splitted ip_conntrack_h323.c into 3 sources IV
diff -rN -u
old-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_h323.h
new-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_h323.h
---
old-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2005-05-10 23:48:49.000000000 +0200
+++
new-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2005-05-10 23:33:19.000000000 +0200
@@ -9,6 +9,7 @@
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,
@@ -27,6 +28,8 @@
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);
diff -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/Makefile.ladd
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/Makefile.ladd
--- old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/Makefile.ladd 2005-05-10
23:48:49.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/Makefile.ladd 2005-05-10
23:48:49.000000000 +0200
@@ -2,5 +2,6 @@
# 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
obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
diff -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323.c
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323.c
--- old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323.c 2005-05-10
23:48:49.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01
01:00:00.000000000 +0100
@@ -1,448 +0,0 @@
-/*
- * 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/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");
-
-/* This is slow, but it's simple. --RR */
-static char h323_buffer[65536];
-
-static DECLARE_LOCK(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;
-
- 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:
- 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(&ip_conntrack_lock);
- new->helper = &h245;
- DEBUGP("h225_expect: helper for %p added\n", new);
- WRITE_UNLOCK(&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 */
- 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);
-
- 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 -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_core.c
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_core.c
---
old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_core.c 1970-01-01
01:00:00.000000000 +0100
+++
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_core.c 2005-05-10
23:33:19.000000000 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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/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("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 -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c
---
old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c 1970-01-01
01:00:00.000000000 +0100
+++
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c 2005-05-10
23:33:19.000000000 +0200
@@ -0,0 +1,299 @@
+/*
+ * 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/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>
+
+/* This is slow, but it's simple. --RR */
+static char h225_buffer[65536];
+
+static DECLARE_LOCK(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 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 */
+ 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);
+
+ 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 -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h245.c
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h245.c
---
old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h245.c 1970-01-01
01:00:00.000000000 +0100
+++
new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h245.c 2005-05-10
23:48:49.000000000 +0200
@@ -0,0 +1,161 @@
+/*
+ * 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/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>
+
+/* This is slow, but it's simple. --RR */
+static char h245_buffer[65536];
+
+static DECLARE_LOCK(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
+
+/* 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;
+
+ LOCK_BH(&ip_h245_lock);
+ data = skb_header_pointer((*pskb), dataoff,
+ datalen, h245_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:
+ 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(&ip_conntrack_lock);
+ new->helper = &h245;
+ DEBUGP("h225_expect: helper for %p added\n", new);
+ WRITE_UNLOCK(&ip_conntrack_lock);
+}
+EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);