* [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser
@ 2005-05-10 22:50 Max Kellermann
2005-05-10 22:51 ` [PATCH pom-ng 1/6] H.323: remove struct ip_ct_h225_master Max Kellermann
` (7 more replies)
0 siblings, 8 replies; 13+ messages in thread
From: Max Kellermann @ 2005-05-10 22:50 UTC (permalink / raw)
To: netfilter-devel; +Cc: laforge
Hi,
the following patchset replaces Jozsef's "brute force" parser with a
real H.245 parser. It adds a very simple ASN.1/PER parsing library,
and parses very few H.245 structures (enough for all H.323 software I
tested).
My next task will be the rewrite of the H.225 parser using my
ASN.1/PER library.
Max
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH pom-ng 1/6] H.323: remove struct ip_ct_h225_master
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
@ 2005-05-10 22:51 ` Max Kellermann
2005-05-10 22:51 ` [PATCH pom-ng 2/6] add ip_nat_h245() Max Kellermann
` (6 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2005-05-10 22:51 UTC (permalink / raw)
To: netfilter-devel; +Cc: laforge
[-- Attachment #1: Type: text/plain, Size: 73 bytes --]
h323-01-remove_ip_ct_h225_master.patch
- remove struct ip_ct_h225_master
[-- Attachment #2: h323-01-remove_ip_ct_h225_master.patch --]
[-- Type: text/plain, Size: 1928 bytes --]
Tue Apr 19 21:28:07 CEST 2005 max@duempel.org
* removed dummy struct ip_ct_h225_master
diff -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd new-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd
--- old-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd 2005-05-10 23:48:01.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
- /* insert conntrack helper private data (master) here */
- struct ip_ct_h225_master ct_h225_info;
diff -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2 new-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2
--- old-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2 2005-05-10 23:48:01.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack.h.ladd_2 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-/* Add protocol helper include file here */
-#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
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:01.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2005-05-10 23:48:01.000000000 +0200
@@ -7,11 +7,6 @@
/* Default H.225 port */
#define H225_PORT 1720
-/* This structure exists only once per master */
-struct ip_ct_h225_master {
- int dummy;
-};
-
struct ip_conntrack_expect;
struct ip_conntrack;
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH pom-ng 2/6] add ip_nat_h245()
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
2005-05-10 22:51 ` [PATCH pom-ng 1/6] H.323: remove struct ip_ct_h225_master Max Kellermann
@ 2005-05-10 22:51 ` Max Kellermann
2005-05-10 22:52 ` [PATCH pom-ng 3/6] H.323: minor code style fixes Max Kellermann
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2005-05-10 22:51 UTC (permalink / raw)
To: netfilter-devel; +Cc: laforge
[-- Attachment #1: Type: text/plain, Size: 79 bytes --]
h323-02-add_ip_nat_h245.patch
- add ip_nat_h245(), separate fro ip_nat_h225()
[-- Attachment #2: h323-02-add_ip_nat_h245.patch --]
[-- Type: text/plain, Size: 2071 bytes --]
Tue Apr 19 22:45:33 CEST 2005 max@duempel.org
* ip_nat_h245_hook has its own implementation, ip_nat_h245()
diff -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_h323.c new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_h323.c
--- old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_h323.c 2005-05-10 23:48:25.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_h323.c 2005-05-10 23:48:26.000000000 +0200
@@ -126,6 +126,54 @@
return NF_ACCEPT;
}
+static int ip_nat_h245(struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo,
+ unsigned int offset,
+ struct ip_conntrack_expect *exp)
+{
+ u_int16_t port;
+ struct {
+ u_int32_t ip;
+ u_int16_t port;
+ } __attribute__ ((__packed__)) newdata;
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack *ct = exp->master;
+ int ret;
+
+ /* Connection will come from wherever this packet goes, hence !dir */
+ newdata.ip = ct->tuplehash[!dir].tuple.dst.ip;
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->dir = !dir;
+
+ /* When you see the packet, we need to NAT it the same as the
+ * this one. */
+ exp->expectfn = ip_nat_follow_master;
+
+ /* Try to get same port: if not, try to change it. */
+ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+ exp->tuple.dst.u.tcp.port = htons(port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (port == 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ }
+
+ newdata.port = htons(port);
+
+ /* now mangle packet */
+ ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ offset,
+ sizeof(newdata),
+ (const char*)&newdata, sizeof(newdata));
+ if (!ret)
+ return NF_DROP;
+
+ return NF_ACCEPT;
+}
+
static int __init init(void)
{
BUG_ON(ip_nat_h225_hook != NULL);
@@ -133,7 +181,7 @@
ip_nat_h225_hook = ip_nat_h225;
ip_nat_h225_signal_hook = ip_nat_h225_signal;
- ip_nat_h245_hook = ip_nat_h225;
+ ip_nat_h245_hook = ip_nat_h245;
return 0;
}
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH pom-ng 3/6] H.323: minor code style fixes
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
2005-05-10 22:51 ` [PATCH pom-ng 1/6] H.323: remove struct ip_ct_h225_master Max Kellermann
2005-05-10 22:51 ` [PATCH pom-ng 2/6] add ip_nat_h245() Max Kellermann
@ 2005-05-10 22:52 ` Max Kellermann
2005-05-10 22:52 ` [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources Max Kellermann
` (4 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2005-05-10 22:52 UTC (permalink / raw)
To: netfilter-devel; +Cc: laforge
[-- Attachment #1: Type: text/plain, Size: 51 bytes --]
h323-03-code_style.patch
- minor code style fixes
[-- Attachment #2: h323-03-code_style.patch --]
[-- Type: text/plain, Size: 895 bytes --]
Tue Apr 19 22:46:24 CEST 2005 max@duempel.org
* minor code style fixes
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:35.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323.c 2005-05-10 23:48:35.000000000 +0200
@@ -160,7 +160,8 @@
}
/* H.245 helper is not registered! */
-static struct ip_conntrack_helper h245 = {
+static struct ip_conntrack_helper h245 =
+{
.name = "H.245",
.max_expected = 8,
.timeout = 240,
@@ -419,7 +420,8 @@
return ret;
}
-static struct ip_conntrack_helper h225 = {
+static struct ip_conntrack_helper h225 =
+{
.name = "H.225",
.me = THIS_MODULE,
.max_expected = 2,
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
` (2 preceding siblings ...)
2005-05-10 22:52 ` [PATCH pom-ng 3/6] H.323: minor code style fixes Max Kellermann
@ 2005-05-10 22:52 ` Max Kellermann
2005-05-11 23:40 ` Patrick McHardy
2005-05-10 22:53 ` [PATCH pom-ng 5/6] H.323: ASN.1/PER parser Max Kellermann
` (3 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Max Kellermann @ 2005-05-10 22:52 UTC (permalink / raw)
To: netfilter-devel; +Cc: laforge
[-- Attachment #1: Type: text/plain, Size: 83 bytes --]
h323-04-split_conntrack_into_3.patch
- splitted ip_conntrack_h323.c into 3 sources
[-- Attachment #2: h323-04-split_conntrack_into_3.patch --]
[-- Type: text/plain, Size: 28519 bytes --]
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);
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH pom-ng 5/6] H.323: ASN.1/PER parser
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
` (3 preceding siblings ...)
2005-05-10 22:52 ` [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources Max Kellermann
@ 2005-05-10 22:53 ` Max Kellermann
2005-05-10 22:54 ` [PATCH pom-ng 6/6] H.323: H.245/ASN.1 parser Max Kellermann
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2005-05-10 22:53 UTC (permalink / raw)
To: netfilter-devel; +Cc: laforge
[-- Attachment #1: Type: text/plain, Size: 65 bytes --]
h323-05-simple_asn1_per_parser.patch
- added an ASN.1/PER parser
[-- Attachment #2: h323-05-simple_asn1_per_parser.patch --]
[-- Type: text/plain, Size: 11064 bytes --]
Tue May 10 23:28:17 CEST 2005 max@duempel.org
* added an ASN.1/PER parser IV
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:49:02.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/Makefile.ladd 2005-05-10 23:33:19.000000000 +0200
@@ -2,6 +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
+ip_conntrack_h323-objs := ip_conntrack_h323_core.o ip_conntrack_h323_h225.o ip_conntrack_h323_h245.o asn1_per.o
obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
diff -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.c new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.c
--- old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.c 1970-01-01 01:00:00.000000000 +0100
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.c 2005-05-10 23:33:19.000000000 +0200
@@ -0,0 +1,353 @@
+/*
+ * Tiny ASN.1 packet encoding rules (PER) library.
+ *
+ * This is a tiny library which helps parsing ASN.1/PER packets
+ * (i.e. read only). It is meant to be secure and small.
+ *
+ * Warning, this library may still be incomplete and buggy.
+ *
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include "asn1_per.h"
+
+void asn1_per_initialize(struct asn1_per_buffer *bb,
+ const unsigned char *data,
+ unsigned length, unsigned position) {
+ *bb = (struct asn1_per_buffer){
+ .data = data,
+ .length = length,
+ .i = position,
+ .bit = 8,
+ .error = 0,
+ };
+}
+
+int asn1_per_read_bit(struct asn1_per_buffer *bb) {
+ int value;
+
+ if (bb->error)
+ return 0;
+
+ if (bb->i >= bb->length) {
+ bb->error = 1;
+ return 0;
+ }
+
+ bb->bit--;
+
+ value = (bb->data[bb->i] & (1 << bb->bit)) != 0;
+
+ if (bb->bit == 0) {
+ bb->bit = 8;
+ bb->i++;
+ }
+
+ return value;
+}
+
+unsigned asn1_per_read_bits(struct asn1_per_buffer *bb, unsigned count) {
+ unsigned value;
+
+ if (bb->error)
+ return 0;
+ if (bb->i >= bb->length) {
+ bb->error = 1;
+ return 0;
+ }
+
+ if (count > 32) {
+ /* XXX support more than 32 bits in the future here? */
+ bb->error = 1;
+ return 0;
+ }
+
+ if (count <= bb->bit) {
+ value = (bb->data[bb->i] >> (bb->bit - count)) & (0xff >> (8 - count));
+
+ bb->bit -= count;
+ if (bb->bit == 0) {
+ bb->bit = 8;
+ bb->i++;
+ }
+
+ return value;
+ }
+
+ count -= bb->bit;
+
+ value = bb->data[bb->i] & (0xff >> (8 - bb->bit));
+ bb->i++;
+
+ while (count >= 8) {
+ if (bb->i >= bb->length) {
+ bb->error = 1;
+ return 0;
+ }
+
+ value = (value << 8) | bb->data[bb->i];
+
+ bb->i++;
+ count -= 8;
+ }
+
+ if (count > 0) {
+ if (bb->i >= bb->length) {
+ bb->error = 1;
+ return 0;
+ }
+
+ value = (value << count) | (bb->data[bb->i] >> (8 - count));
+ }
+
+ bb->bit = 8 - count;
+
+ return value;
+}
+
+void asn1_per_read_bitmap(struct asn1_per_buffer *bb, unsigned count,
+ struct asn1_per_bitmap *bitmap) {
+ unsigned char *p;
+
+ memset(bitmap, 0, sizeof(*bitmap));
+
+ if (bb->error)
+ return;
+
+ if (count > sizeof(bitmap->data) * 8) {
+ /* XXX limited bit map support */
+ bb->error = 1;
+ return;
+ }
+
+ for (p = bitmap->data; count > 8; count -= 8)
+ *p++ = (unsigned char)asn1_per_read_bits(bb, 8);
+
+ if (count > 0)
+ *p = asn1_per_read_bits(bb, count) << (8 - count);
+
+ return;
+}
+
+void asn1_per_read_bytes(struct asn1_per_buffer *bb,
+ void *buffer, unsigned count) {
+ if (bb->error)
+ return;
+
+ if (bb->bit != 8) {
+ bb->error = 1;
+ return;
+ }
+
+ if (bb->i + count > bb->length) {
+ bb->error = 1;
+ return;
+ }
+
+ memcpy(buffer, bb->data + bb->i, count);
+
+ bb->i += count;
+}
+
+void asn1_per_byte_align(struct asn1_per_buffer *bb) {
+ if (bb->bit < 8) {
+ bb->bit = 8;
+ bb->i++;
+ }
+}
+
+static unsigned count_bits(unsigned range) {
+ unsigned bits = 0;
+
+ if (range == 0)
+ return 32;
+
+ if (range == 1)
+ return 1;
+
+ while (bits < 32 && range > (unsigned)(1 << bits))
+ bits++;
+
+ return bits;
+}
+
+unsigned asn1_per_read_unsigned(struct asn1_per_buffer *bb,
+ unsigned lower, unsigned upper) {
+ unsigned range = (upper - lower) + 1;
+ unsigned bits = count_bits(range);
+
+ if (lower == upper)
+ return lower;
+
+ if (range == 0 || range > 255) {
+ if (bits > 16)
+ bits = asn1_per_read_length(bb, 1, (bits+7)/8) * 8;
+ else if (bits > 8)
+ bits = 16;
+ asn1_per_byte_align(bb);
+ }
+
+ return lower + asn1_per_read_bits(bb, bits);
+}
+
+unsigned asn1_per_read_length(struct asn1_per_buffer *bb,
+ unsigned lower, unsigned upper) {
+ if (upper < 65536)
+ return asn1_per_read_unsigned(bb, lower, upper);
+
+ asn1_per_byte_align(bb);
+
+ if (!asn1_per_read_bit(bb))
+ return asn1_per_read_bits(bb, 7);
+
+ if (!asn1_per_read_bit(bb))
+ return asn1_per_read_bits(bb, 14);
+
+ bb->error = 1;
+ return 0;
+}
+
+unsigned asn1_per_read_small(struct asn1_per_buffer *bb) {
+ unsigned length;
+
+ if (!asn1_per_read_bit(bb))
+ return asn1_per_read_bits(bb, 6);
+
+ length = asn1_per_read_length(bb, 0, INT_MAX);
+
+ asn1_per_byte_align(bb);
+
+ return asn1_per_read_bits(bb, length * 8);
+}
+
+unsigned asn1_per_read_choice_header(struct asn1_per_buffer *bb,
+ int extendable,
+ unsigned options, unsigned *after) {
+ int extended;
+ unsigned choice;
+
+ extended = extendable && asn1_per_read_bit(bb);
+ if (extended) {
+ unsigned length;
+
+ choice = asn1_per_read_small(bb) + options;
+ length = asn1_per_read_length(bb, 0, INT_MAX);
+ *after = bb->i + length;
+ } else if (options < 2) {
+ choice = 0;
+ *after = 0;
+ } else {
+ choice = asn1_per_read_bits(bb, count_bits(options));
+ *after = 0;
+ }
+
+ return choice;
+}
+
+void asn1_per_read_sequence_header(struct asn1_per_buffer *bb, int extendable,
+ unsigned optional_count,
+ struct asn1_per_sequence_header *hdr) {
+ hdr->extended = extendable && asn1_per_read_bit(bb);
+ asn1_per_read_bitmap(bb, optional_count, &hdr->present);
+}
+
+void asn1_per_read_sequence_extension_header(struct asn1_per_buffer *bb,
+ const struct asn1_per_sequence_header *hdr,
+ struct asn1_per_sequence_extension_header *ext) {
+ if (!hdr->extended) {
+ memset(ext, 0, sizeof(*ext));
+ return;
+ }
+
+ ext->count = asn1_per_read_small(bb) + 1;
+ if (bb->error)
+ return;
+
+ asn1_per_read_bitmap(bb, ext->count, &ext->present);
+}
+
+void asn1_per_skip_sequence_extension(struct asn1_per_buffer *bb,
+ const struct asn1_per_sequence_header *hdr) {
+ struct asn1_per_sequence_extension_header ext;
+ unsigned i;
+
+ asn1_per_read_sequence_extension_header(bb, hdr, &ext);
+ if (bb->error)
+ return;
+
+ for (i = 0; i < ext.count; i++) {
+ if (asn1_per_bitmap_get(&ext.present, i))
+ asn1_per_skip_octet_string(bb);
+ }
+}
+
+void asn1_per_skip_object_id(struct asn1_per_buffer *bb) {
+ unsigned length;
+
+ length = asn1_per_read_length(bb, 0, 255);
+ switch (length) {
+ case 0:
+ break;
+
+ case 1:
+ asn1_per_read_bits(bb, 8);
+ break;
+
+ case 2:
+ asn1_per_read_bits(bb, 16);
+ break;
+
+ default:
+ asn1_per_byte_align(bb);
+
+ bb->i += length;
+ if (bb->i > bb->length)
+ bb->error = 1;
+ }
+}
+
+unsigned asn1_per_read_octet_string_header(struct asn1_per_buffer *bb) {
+ unsigned length;
+
+ length = asn1_per_read_length(bb, 0, INT_MAX);
+ if (length > 2)
+ asn1_per_byte_align(bb);
+
+ return length;
+}
+
+void asn1_per_skip_octet_string(struct asn1_per_buffer *bb) {
+ unsigned length;
+
+ length = asn1_per_read_length(bb, 0, INT_MAX);
+ switch (length) {
+ case 0:
+ break;
+
+ case 1:
+ asn1_per_read_bits(bb, 8);
+ break;
+
+ case 2:
+ asn1_per_read_bits(bb, 16);
+ break;
+
+ default:
+ asn1_per_byte_align(bb);
+
+ bb->i += length;
+ if (bb->i > bb->length)
+ bb->error = 1;
+ }
+}
+
+
+int asn1_per_bitmap_get(const struct asn1_per_bitmap *bitmap, unsigned i) {
+ if (i >= sizeof(bitmap->data) * 8)
+ return 0;
+
+ return (bitmap->data[i / 8] & (1 << (7 - (i % 8)))) != 0;
+}
diff -rN -u old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.h new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.h
--- old-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.h 1970-01-01 01:00:00.000000000 +0100
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/asn1_per.h 2005-05-10 23:33:19.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ * Tiny ASN.1 packet encoding rules (PER) library.
+ *
+ * This is a tiny library which helps parsing ASN.1/PER packets
+ * (i.e. read only). It is meant to be secure and small.
+ *
+ * Warning, this library may still be incomplete and buggy.
+ *
+ * (c) 2005 Max Kellermann <max@duempel.org>
+ */
+
+#ifndef __ASN1_PER_H
+#define __ASN1_PER_H
+
+struct asn1_per_buffer {
+ const unsigned char *data;
+ unsigned length, i, bit;
+ int error;
+};
+
+struct asn1_per_bitmap {
+ unsigned char data[16];
+};
+
+struct asn1_per_sequence_header {
+ int extended;
+ struct asn1_per_bitmap present;
+};
+
+struct asn1_per_sequence_extension_header {
+ unsigned count;
+ struct asn1_per_bitmap present;
+};
+
+void asn1_per_initialize(struct asn1_per_buffer *bb,
+ const unsigned char *data,
+ unsigned length, unsigned position);
+
+int asn1_per_read_bit(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_bits(struct asn1_per_buffer *bb, unsigned count);
+
+void asn1_per_read_bitmap(struct asn1_per_buffer *bb, unsigned count,
+ struct asn1_per_bitmap *bitmap);
+
+void asn1_per_read_bytes(struct asn1_per_buffer *bb,
+ void *buffer, unsigned count);
+
+void asn1_per_byte_align(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_unsigned(struct asn1_per_buffer *bb,
+ unsigned lower, unsigned upper);
+
+unsigned asn1_per_read_length(struct asn1_per_buffer *bb,
+ unsigned lower, unsigned upper);
+
+unsigned asn1_per_read_small(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_choice_header(struct asn1_per_buffer *bb,
+ int extendable,
+ unsigned options, unsigned *after);
+
+void asn1_per_read_sequence_header(struct asn1_per_buffer *bb, int extendable,
+ unsigned optional_count,
+ struct asn1_per_sequence_header *hdr);
+
+void asn1_per_read_sequence_extension_header(struct asn1_per_buffer *bb,
+ const struct asn1_per_sequence_header *hdr,
+ struct asn1_per_sequence_extension_header *ext);
+
+void asn1_per_skip_sequence_extension(struct asn1_per_buffer *bb,
+ const struct asn1_per_sequence_header *hdr);
+
+void asn1_per_skip_object_id(struct asn1_per_buffer *bb);
+
+unsigned asn1_per_read_octet_string_header(struct asn1_per_buffer *bb);
+
+void asn1_per_skip_octet_string(struct asn1_per_buffer *bb);
+
+
+int asn1_per_bitmap_get(const struct asn1_per_bitmap *bitmap, unsigned i);
+
+#endif
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH pom-ng 6/6] H.323: H.245/ASN.1 parser
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
` (4 preceding siblings ...)
2005-05-10 22:53 ` [PATCH pom-ng 5/6] H.323: ASN.1/PER parser Max Kellermann
@ 2005-05-10 22:54 ` Max Kellermann
2005-05-11 8:01 ` [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Harald Welte
2005-05-11 18:16 ` [PATCH pom-ng 7/6] H.323: reimplement the H.225 parser using the ASN.1/PER library Max Kellermann
7 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2005-05-10 22:54 UTC (permalink / raw)
To: netfilter-devel; +Cc: laforge
[-- Attachment #1: Type: text/plain, Size: 82 bytes --]
h323-06-replace_bruteforce_with_h245_parser.patch
- implement a real H.245 parser
[-- Attachment #2: h323-06-replace_bruteforce_with_h245_parser.patch --]
[-- Type: text/plain, Size: 24494 bytes --]
Tue May 10 23:35:13 CEST 2005 max@duempel.org
* H.245/ASN.1 parser VII
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 2005-05-10 23:49:18.000000000 +0200
+++ new-h323-4/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h245.c 2005-05-10 23:34:17.000000000 +0200
@@ -20,6 +20,8 @@
#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+#include "asn1_per.h"
+
/* This is slow, but it's simple. --RR */
static char h245_buffer[65536];
@@ -39,20 +41,861 @@
#define DEBUGP(format, args...)
#endif
-/* FIXME: This should be in userspace. Later. */
+/**
+ * Skip an H.245 NonStandardIdentifier, discarding its value.
+ */
+static void h245_skip_nonstandard_id(struct asn1_per_buffer *bb) {
+ unsigned choice;
+
+ choice = asn1_per_read_bits(bb, 1);
+ switch (choice) {
+ case 0:
+ asn1_per_skip_object_id(bb);
+ break;
+
+ case 1:
+ asn1_per_read_unsigned(bb, 0, 255);
+ asn1_per_read_unsigned(bb, 0, 255);
+ asn1_per_read_unsigned(bb, 0, 65535);
+ break;
+ }
+}
+
+/**
+ * Skip an H.245 NonStandardParameter, discarding its value.
+ */
+static void h245_skip_nonstandard_param(struct asn1_per_buffer *bb) {
+ h245_skip_nonstandard_id(bb);
+ asn1_per_skip_octet_string(bb);
+}
+
+/**
+ * Skip an H.245 VideoCapability, discarding its value.
+ */
+static void h245_skip_video_capability(struct asn1_per_buffer *bb) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 5, &after);
+ DEBUGP("video_capability: choice=%u after=%u error=%d\n",
+ choice, after, bb->error);
+
+ if (bb->error)
+ return;
+
+ /* XXX support the rest */
+ switch (choice) {
+ case 0: /* nonStandard */
+ h245_skip_nonstandard_param(bb);
+ break;
+
+ default:
+ if (after == 0) {
+ DEBUGP("unsupported audio_capability %u\n", choice);
+ bb->error = 1;
+ }
+ }
+
+ if (after > 0)
+ bb->i = after;
+}
+
+/**
+ * Skip an H.245 AudioCapability, discarding its value.
+ */
+static void h245_skip_audio_capability(struct asn1_per_buffer *bb) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 14, &after);
+ DEBUGP("audio_capability: audio_capability=%u after=%u error=%d\n", choice, after, bb->error);
+
+ if (bb->error)
+ return;
+
+ /* XXX support the rest */
+ switch (choice) {
+ unsigned value;
+
+ case 0: /* nonStandard */
+ h245_skip_nonstandard_param(bb);
+ break;
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 9:
+ case 10:
+ case 11:
+ case 14:
+ case 17:
+ value = asn1_per_read_unsigned(bb, 1, 256);
+ DEBUGP("value %u = %u\n", choice, value);
+ break;
+ default:
+ if (after == 0) {
+ DEBUGP("unsupported audio_capability %u\n", choice);
+ bb->error = 1;
+ }
+ }
+
+ if (after > 0)
+ bb->i = after;
+}
+
+/**
+ * Skip an H.245 DataType, discarding its value.
+ */
+static void h245_skip_data_type(struct asn1_per_buffer *bb) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 6, &after);
+
+ if (bb->error)
+ return;
+
+ /* XXX support the rest */
+ switch (choice) {
+ case 0: /* nonStandard */
+ h245_skip_nonstandard_param(bb);
+ break;
+
+ case 1: /* nullData */
+ break;
+
+ case 2: /* videoData */
+ h245_skip_video_capability(bb);
+ break;
+
+ case 3: /* audioData */
+ h245_skip_audio_capability(bb);
+ break;
+
+ default:
+ if (after == 0) {
+ DEBUGP("unsupported data_type %u\n", choice);
+ bb->error = 1;
+ }
+ }
+
+ if (after > 0)
+ bb->i = after;
+}
+
+/**
+ * Parse an H.245 UnicastAddress and return the position of the IP
+ * address (if present). Returns 1 on success.
+ */
+static int h245_parse_unicast_address(struct asn1_per_buffer *bb, unsigned *i,
+ u_int32_t *ip, u_int16_t *port) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 5, &after);
+ DEBUGP("Parsing UnicastAddress choice=%u after=%u\n", choice, after);
+ switch (choice) {
+ case 0: /* iPAddress */
+ asn1_per_read_bit(bb); /* XXX use this bit */
+ asn1_per_byte_align(bb);
+ *i = bb->i;
+ asn1_per_read_bytes(bb, ip, sizeof(*ip));
+ asn1_per_read_bytes(bb, port, sizeof(*port));
+ return !bb->error;
+ default:
+ if (after == 0) {
+ DEBUGP("UnicastAddress %u not yet supported\n", choice);
+ bb->error = 1;
+ } else {
+ bb->i = after;
+ }
+ return 0;
+ }
+}
+
+/**
+ * Parse an H.245 TransportAddress and return the position of the
+ * Unicast IP address (if present). Returns 1 on success.
+ */
+static int h245_parse_transport_address(struct asn1_per_buffer *bb, unsigned *i,
+ u_int32_t *ip, u_int16_t *port) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 2, &after);
+ switch (choice) {
+ case 0: /* UnicastAddress */
+ return h245_parse_unicast_address(bb, i, ip, port);
+ case 1: /* MulticastAddress */
+ /* XXX */
+ DEBUGP("MulticastAddress not yet supported\n");
+ bb->error = 1;
+ return 0;
+ default:
+ if (after == 0) {
+ DEBUGP("ERROR7\n");
+ bb->error = 1;
+ } else {
+ bb->i = after;
+ }
+ return 0;
+ }
+}
+
+/**
+ * Skip an H.245 TerminalLabel, discarding its value.
+ */
+static void h245_skip_terminal_label(struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr;
+
+ asn1_per_read_sequence_header(bb, 1, 0, &hdr);
+
+ /* mcuNumber */
+ asn1_per_read_unsigned(bb, 0, 192);
+ /* terminalNumber */
+ asn1_per_read_unsigned(bb, 0, 192);
+
+ asn1_per_skip_sequence_extension(bb, &hdr);
+}
+
+/**
+ * Parse an H.245 H2250LogicalChannelParameters request packet and
+ * handle NAT/expectations for the logical channel address.
+ */
+static int h245_parse_h2250_lchannel_params(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr;
+ unsigned session_id;
+
+ asn1_per_read_sequence_header(bb, 1, 10, &hdr);
+
+ /* nonStandard */
+ if (asn1_per_bitmap_get(&hdr.present, 0))
+ h245_skip_nonstandard_param(bb);
+
+ /* sessionID */
+ session_id = asn1_per_read_unsigned(bb, 0, 255);
+
+ /* associatedSessionID */
+ if (asn1_per_bitmap_get(&hdr.present, 1))
+ asn1_per_read_unsigned(bb, 1, 255);
+
+ /* mediaChannel */
+ DEBUGP("lchannel_params mediaChannel: i=%u bit=%u\n", bb->i, bb->bit);
+ if (asn1_per_bitmap_get(&hdr.present, 2)) {
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack_expect *exp;
+ int ret;
+ unsigned i;
+ u_int32_t ip;
+ u_int16_t port;
+
+ ret = h245_parse_transport_address(bb, &i, &ip, &port);
+ if (ret)
+ DEBUGP("mediaChannel IPv4 address: %u.%u.%u.%u:%u\n",
+ NIPQUAD(ip), ntohs(port));
+ if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+ /* match found: create an expectation */
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL)
+ return NF_ACCEPT;
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { ct->tuplehash[!dir].tuple.src.ip,
+ { 0 } },
+ { ct->tuplehash[!dir].tuple.dst.ip,
+ { .udp = { port } },
+ IPPROTO_UDP }});
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0xFFFFFFFF, { 0 } },
+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+ exp->master = ct;
+
+ /* call NAT hook and register expectation */
+ if (ip_nat_h245_hook != NULL) {
+ return ip_nat_h245_hook(pskb, ctinfo, i,
+ exp);
+ } else {
+ /* Can't expect this? Best to drop packet now. */
+ if (ip_conntrack_expect_related(exp) != 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ } else {
+ return NF_ACCEPT;
+ }
+ }
+ }
+ }
+
+ /* mediaGuaranteedDelivery */
+ if (asn1_per_bitmap_get(&hdr.present, 3))
+ asn1_per_read_bit(bb);
+
+ /* mediaControlChannel */
+ DEBUGP("lchannel_params controlChannel: i=%u bit=%u\n", bb->i, bb->bit);
+ if (asn1_per_bitmap_get(&hdr.present, 4)) {
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack_expect *exp;
+ int ret;
+ unsigned i;
+ u_int32_t ip;
+ u_int16_t port;
+
+ ret = h245_parse_transport_address(bb, &i, &ip, &port);
+ if (ret)
+ DEBUGP("mediaControlChannel IPv4 address: %u.%u.%u.%u:%u\n",
+ NIPQUAD(ip), ntohs(port));
+ if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+ /* match found: create an expectation */
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL)
+ return NF_ACCEPT;
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { ct->tuplehash[!dir].tuple.src.ip,
+ { 0 } },
+ { ct->tuplehash[!dir].tuple.dst.ip,
+ { .udp = { port } },
+ IPPROTO_UDP }});
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0xFFFFFFFF, { 0 } },
+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+ exp->master = ct;
+
+ /* call NAT hook and register expectation */
+ if (ip_nat_h245_hook != NULL) {
+ return ip_nat_h245_hook(pskb, ctinfo, i,
+ exp);
+ } else {
+ /* Can't expect this? Best to drop packet now. */
+ if (ip_conntrack_expect_related(exp) != 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ } else {
+ return NF_ACCEPT;
+ }
+ }
+ }
+ }
+
+ /* mediaControlGuaranteedDelivery */
+ if (asn1_per_bitmap_get(&hdr.present, 5))
+ asn1_per_read_bit(bb);
+
+ /* silenceSuppression */
+ if (asn1_per_bitmap_get(&hdr.present, 6))
+ asn1_per_read_bit(bb);
+
+ /* destination */
+ if (asn1_per_bitmap_get(&hdr.present, 7))
+ h245_skip_terminal_label(bb);
+
+ /* dynamicRTPPayloadType */
+ if (asn1_per_bitmap_get(&hdr.present, 8))
+ asn1_per_read_unsigned(bb, 96, 127);
+
+ /* mediaPacketization */
+ if (asn1_per_bitmap_get(&hdr.present, 9)) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 1, &after);
+ switch (choice) {
+ case 0: /* h261aVideoPacketization */
+ break;
+
+ default:
+ if (after == 0) {
+ DEBUGP("ERROR7\n");
+ bb->error = 1;
+ return NF_ACCEPT;
+ }
+
+ bb->i = after;
+ }
+ }
+
+ /* XXX */
+
+ asn1_per_skip_sequence_extension(bb, &hdr);
+
+ return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 OpenLogicalChannel request packet and handle
+ * NAT/expectations for the logical channel address.
+ */
+static int h245_parse_open_lchannel(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr, hdr2;
+ unsigned forwardLogicalChannelNumber;
+ unsigned choice, after;
+
+ asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+ forwardLogicalChannelNumber = asn1_per_read_unsigned(bb, 1, 65535);
+
+ /* entering forwardLogicalChannelParameters */
+ asn1_per_read_sequence_header(bb, 1, 1, &hdr2);
+ if (asn1_per_bitmap_get(&hdr2.present, 0))
+ asn1_per_read_unsigned(bb, 0, 65535);
+
+ h245_skip_data_type(bb);
+
+ /* multiplexParameters */
+ choice = asn1_per_read_choice_header(bb, 1, 3, &after);
+ if (bb->error)
+ return NF_ACCEPT;
+
+ switch (choice) {
+ case 3: /* h2250LogicalChannelParameters */
+ h245_parse_h2250_lchannel_params(pskb, ct, ctinfo, bb);
+ break;
+ default:
+ if (after == 0) {
+ DEBUGP("unsupported multiplex_parameter %u\n", choice);
+ bb->error = 1;
+ return NF_ACCEPT;
+ }
+ }
+
+ if (bb->error)
+ return NF_ACCEPT;
+
+ if (after > 0)
+ bb->i = after;
+
+ asn1_per_skip_sequence_extension(bb, &hdr2);
+
+ /* leaving multiplexParameters, forwardLogicalChannelParameters */
+
+ /* reverseLogicalChannelParameters */
+ if (asn1_per_bitmap_get(&hdr.present, 0)) {
+ asn1_per_read_sequence_header(bb, 1, 1, &hdr2);
+
+ h245_skip_data_type(bb);
+
+ /* multiplexParameters */
+ if (asn1_per_bitmap_get(&hdr2.present, 0)) {
+ choice = asn1_per_read_choice_header(bb, 1, 2, &after);
+ if (bb->error)
+ return NF_ACCEPT;
+
+ DEBUGP("reverse_parameter multiplex=%u after=%u\n", choice, after);
+
+ switch (choice) {
+ case 2: /* h2250LogicalChannelParameters */
+ h245_parse_h2250_lchannel_params(pskb, ct, ctinfo, bb);
+ break;
+ default:
+ if (after == 0) {
+ DEBUGP("unsupported multiplex_parameter %u\n", choice);
+ bb->error = 1;
+ return NF_ACCEPT;
+ }
+ }
+
+ if (bb->error)
+ return NF_ACCEPT;
+
+ if (after > 0)
+ bb->i = after;
+ }
+
+ asn1_per_skip_sequence_extension(bb, &hdr2);
+ }
+
+ asn1_per_skip_sequence_extension(bb, &hdr);
+
+ /* XXX */
+ return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 request packet and handle NAT/expectations for the
+ * logical channel address.
+ */
+static int h245_parse_request(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 11, &after);
+ DEBUGP("H.245: message_type=%u\n", choice);
+ switch (choice) {
+ case 3:
+ return h245_parse_open_lchannel(pskb, ct, ctinfo, bb);
+ default:
+ return NF_ACCEPT;
+ }
+}
+
+/**
+ * Parse an H.245 H222LogicalChannelParameters response packet and
+ * handle NAT/expectations for the logical channel address.
+ */
+static int h245_parse_h222_lchannel_params(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr;
+
+ asn1_per_read_sequence_header(bb, 1, 3, &hdr);
+
+ if (bb->error)
+ return NF_ACCEPT;
+
+ /* resourceID */
+ asn1_per_read_unsigned(bb, 0, 65535);
+
+ /* subChannelID */
+ asn1_per_read_unsigned(bb, 0, 8191);
+
+ /* pcr-pid */
+ if (asn1_per_bitmap_get(&hdr.present, 0))
+ asn1_per_read_unsigned(bb, 0, 8191);
+
+ /* programDescriptors */
+ if (asn1_per_bitmap_get(&hdr.present, 1))
+ asn1_per_skip_octet_string(bb);
+
+ /* streamDescriptors */
+ if (asn1_per_bitmap_get(&hdr.present, 2))
+ asn1_per_skip_octet_string(bb);
+
+ asn1_per_skip_sequence_extension(bb, &hdr);
+
+ return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 H2250LogicalChannelAckParameters response packet and
+ * handle NAT/expectations for the logical channel address.
+ */
+static int h245_parse_h2250_lchannel_ack_params(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr;
+ unsigned count;
+
+ DEBUGP("entering h245_parse_h2250_lchannel_ack_params\n");
+
+ asn1_per_read_sequence_header(bb, 1, 5, &hdr);
+
+ /* nonStandard */
+ if (asn1_per_bitmap_get(&hdr.present, 0)) {
+ count = asn1_per_read_length(bb, 0, UINT_MAX);
+ while (count > 0) {
+ h245_skip_nonstandard_param(bb);
+ if (bb->error)
+ return NF_ACCEPT;
+ }
+ }
+
+ /* sessionID */
+ if (asn1_per_bitmap_get(&hdr.present, 1))
+ asn1_per_read_unsigned(bb, 1, 255);
+
+ /* mediaChannel */
+ if (asn1_per_bitmap_get(&hdr.present, 2)) {
+ int ret;
+ unsigned i;
+ u_int32_t ip;
+ u_int16_t port;
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack_expect *exp;
+
+ ret = h245_parse_transport_address(bb, &i, &ip, &port);
+ DEBUGP("entering mediaChannel ret=%d i=%u ip=%x port=%u\n",
+ ret, i, ip, port);
+ if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+ /* match found: create an expectation */
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL)
+ return NF_ACCEPT;
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { ct->tuplehash[!dir].tuple.src.ip,
+ { 0 } },
+ { ct->tuplehash[!dir].tuple.dst.ip,
+ { .udp = { port } },
+ IPPROTO_UDP }});
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0xFFFFFFFF, { 0 } },
+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+ exp->master = ct;
+
+ /* call NAT hook and register expectation */
+ if (ip_nat_h245_hook != NULL) {
+ ret = ip_nat_h245_hook(pskb, ctinfo, i, exp);
+ if (ret != NF_ACCEPT)
+ return ret;
+ } else {
+ /* Can't expect this? Best to drop packet now. */
+ if (ip_conntrack_expect_related(exp) != 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ } else {
+ return NF_ACCEPT;
+ }
+ }
+ }
+ }
+
+ /* mediaControlChannel */
+ if (asn1_per_bitmap_get(&hdr.present, 3)) {
+ int ret;
+ unsigned i;
+ u_int32_t ip;
+ u_int16_t port;
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack_expect *exp;
+
+ ret = h245_parse_transport_address(bb, &i, &ip, &port);
+ DEBUGP("entering mediaControlChannel ret=%d i=%u ip=%x port=%u\n",
+ ret, i, ip, port);
+ if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+ /* match found: create an expectation */
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL)
+ return NF_ACCEPT;
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { ct->tuplehash[!dir].tuple.src.ip,
+ { 0 } },
+ { ct->tuplehash[!dir].tuple.dst.ip,
+ { .udp = { port } },
+ IPPROTO_UDP }});
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0xFFFFFFFF, { 0 } },
+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
+
+ exp->master = ct;
+
+ /* call NAT hook and register expectation */
+ if (ip_nat_h245_hook != NULL) {
+ ret = ip_nat_h245_hook(pskb, ctinfo, i, exp);
+ if (ret != NF_ACCEPT)
+ return ret;
+ } else {
+ /* Can't expect this? Best to drop packet now. */
+ if (ip_conntrack_expect_related(exp) != 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ } else {
+ return NF_ACCEPT;
+ }
+ }
+ }
+ }
+
+ /* dynamicRTPPayloadType */
+ if (asn1_per_bitmap_get(&hdr.present, 1))
+ asn1_per_read_unsigned(bb, 96, 127);
+
+ asn1_per_skip_sequence_extension(bb, &hdr);
+
+ return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 OpenLogicalChannelAck response packet and handle
+ * NAT/expectations for the logical channel address.
+ */
+static int h245_parse_open_lchannel_ack(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr, hdr2;
+ struct asn1_per_sequence_extension_header ext;
+ unsigned forwardLogicalChannelNumber;
+ unsigned choice, after, after2, i;
+
+ asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+ forwardLogicalChannelNumber = asn1_per_read_unsigned(bb, 1, 65535);
+ DEBUGP("forwardLogicalChannelNumber=%u\n", forwardLogicalChannelNumber);
+
+ /* reverseLogicalChannelParameters */
+ if (asn1_per_bitmap_get(&hdr.present, 0)) {
+ DEBUGP("reverseLogicalChannelParameters present\n");
+ asn1_per_read_sequence_header(bb, 1, 2, &hdr2);
+
+ /* reverseLogicalChannelNumber */
+ asn1_per_read_unsigned(bb, 1, 65535);
+
+ /* portNumber */
+ if (asn1_per_bitmap_get(&hdr.present, 0))
+ asn1_per_read_unsigned(bb, 0, 65535);
+
+ /* multiplexParameters */
+ if (asn1_per_bitmap_get(&hdr2.present, 1)) {
+ choice = asn1_per_read_choice_header(bb, 1, 1, &after);
+ if (bb->error)
+ return NF_ACCEPT;
+
+ switch (choice) {
+ case 0: /* h222LogicalChannelParameters */
+ h245_parse_h222_lchannel_params(pskb, ct,
+ ctinfo, bb);
+ break;
+ case 1: /* h2250LogicalChannelParameters */
+ h245_parse_h2250_lchannel_params(pskb, ct,
+ ctinfo, bb);
+ break;
+ default:
+ if (after == 0) {
+ DEBUGP("unsupported multiplex_parameter %u\n", choice);
+ bb->error = 1;
+ return NF_ACCEPT;
+ }
+ }
+
+ if (bb->error)
+ return NF_ACCEPT;
+
+ if (after > 0)
+ bb->i = after;
+ }
+
+ asn1_per_skip_sequence_extension(bb, &hdr2);
+ }
+
+ asn1_per_read_sequence_extension_header(bb, &hdr, &ext);
+ if (bb->error)
+ return NF_ACCEPT;
+
+ /* separateStack */
+ if (asn1_per_bitmap_get(&ext.present, 0))
+ asn1_per_skip_octet_string(bb);
+
+ /* forwardMultiplexAckParameters */
+ if (asn1_per_bitmap_get(&ext.present, 1)) {
+ DEBUGP("forwardMultiplexAckParameters present\n");
+
+ after = asn1_per_read_octet_string_header(bb);
+ DEBUGP("forwardMultiplexAckParameters present length=%u i=%u after=%u end=%u\n",
+ after, bb->i, bb->i + after, bb->length);
+ after += bb->i;
+
+ choice = asn1_per_read_choice_header(bb, 1, 1, &after2);
+ if (bb->error)
+ return NF_ACCEPT;
+
+ DEBUGP("entering forwardMultiplexAckParameters choice=%u after=%u\n", choice, after2);
+
+ switch (choice) {
+ case 0: /* h2250LogicalChannelAckParameters */
+ h245_parse_h2250_lchannel_ack_params(pskb, ct,
+ ctinfo, bb);
+ break;
+ }
+
+ if (bb->error)
+ return NF_ACCEPT;
+
+ bb->i = after;
+ }
+
+ for (i = 2; i < ext.count; i++)
+ if (asn1_per_bitmap_get(&ext.present, i))
+ asn1_per_skip_octet_string(bb);
+
+ return NF_ACCEPT;
+}
+
+/**
+ * Parse an H.245 response packet and handle NAT/expectations for the
+ * logical channel address.
+ */
+static int h245_parse_response(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 19, &after);
+ DEBUGP("H.245: response type=%u\n", choice);
+ switch (choice) {
+ case 5: /* openLogicalChannelAck */
+ return h245_parse_open_lchannel_ack(pskb, ct, ctinfo, bb);
+
+ default:
+ return NF_ACCEPT;
+ }
+}
+
+/**
+ * Parse an H.245 packet and handle NAT/expectations for the logical
+ * channel address.
+ */
+static int h245_parse(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 4, &after);
+ DEBUGP("H.245: message_class=%u\n", choice);
+ switch (choice) {
+ case 0:
+ return h245_parse_request(pskb, ct, ctinfo, bb);
+ case 1:
+ return h245_parse_response(pskb, ct, ctinfo, bb);
+ default:
+ return NF_ACCEPT;
+ }
+}
+
+/**
+ * Parse a TPKT/H.245 packet and handle NAT/expectations for the
+ * logical channel transport address (if applicable).
+ */
+static int h245_parse_tpkt(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ const unsigned char *data,
+ unsigned datalen) {
+ unsigned int i = 0;
+ u_int16_t tpkt_len;
+ struct asn1_per_buffer bb;
+
+ /* 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 H.245 packet (ASN.1 PER) */
+ asn1_per_initialize(&bb, data, datalen, i);
+
+ return h245_parse(pskb, ct, ctinfo, &bb);
+}
+
static int h245_help(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo)
{
struct tcphdr _tcph, *tcph;
unsigned char *data;
- unsigned 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. */
@@ -84,56 +927,9 @@
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 = h245_parse_tpkt(pskb, ct, ctinfo,
+ data, datalen);
- ret = NF_ACCEPT;
- out:
UNLOCK_BH(&ip_h245_lock);
return ret;
}
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
` (5 preceding siblings ...)
2005-05-10 22:54 ` [PATCH pom-ng 6/6] H.323: H.245/ASN.1 parser Max Kellermann
@ 2005-05-11 8:01 ` Harald Welte
2005-05-11 18:16 ` [PATCH pom-ng 7/6] H.323: reimplement the H.225 parser using the ASN.1/PER library Max Kellermann
7 siblings, 0 replies; 13+ messages in thread
From: Harald Welte @ 2005-05-11 8:01 UTC (permalink / raw)
To: Max Kellermann; +Cc: netfilter-devel, Jozsef Kadlecsik
[-- Attachment #1: Type: text/plain, Size: 955 bytes --]
On Wed, May 11, 2005 at 12:50:19AM +0200, Max Kellermann wrote:
> Hi,
>
> the following patchset replaces Jozsef's "brute force" parser with a
> real H.245 parser. It adds a very simple ASN.1/PER parsing library,
> and parses very few H.245 structures (enough for all H.323 software I
> tested).
Thanks, this is great news. Including the list of tested h.323 software
somwhere in the 'info' or 'help' file would definitely be a good idea.
I'd happily apply your patches but leave it up to Jozsef, since he's
more familiar with the protocol and the helper he wrote.
--
- Harald Welte <laforge@netfilter.org> http://netfilter.org/
============================================================================
"Fragmentation is like classful addressing -- an interesting early
architectural error that shows how much experimentation was going
on while IP was being designed." -- Paul Vixie
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH pom-ng 7/6] H.323: reimplement the H.225 parser using the ASN.1/PER library
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
` (6 preceding siblings ...)
2005-05-11 8:01 ` [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Harald Welte
@ 2005-05-11 18:16 ` Max Kellermann
2005-05-17 15:18 ` Patrick McHardy
7 siblings, 1 reply; 13+ messages in thread
From: Max Kellermann @ 2005-05-11 18:16 UTC (permalink / raw)
To: netfilter-devel; +Cc: Jozsef Kadlecsik
[-- Attachment #1: Type: text/plain, Size: 180 bytes --]
An additional patch to this patch series, which I developed today:
h323-07-reimplement_h225_parser_with_asn1_per.patch
- reimplement the H.225 parser using the ASN.1/PER library
[-- Attachment #2: h323-07-reimplement_h225_parser_with_asn1_per.patch --]
[-- Type: text/plain, Size: 6836 bytes --]
Wed May 11 11:35:03 CEST 2005 max@duempel.org
* reimplement the H.225 parser using the ASN.1/PER library
diff -rN -u old-h323-0/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c new-h323-0/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c
--- old-h323-0/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c 2005-05-11 20:16:27.000000000 +0200
+++ new-h323-0/h323-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_h323_h225.c 2005-05-11 12:26:20.000000000 +0200
@@ -20,6 +20,8 @@
#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+#include "asn1_per.h"
+
/* This is slow, but it's simple. --RR */
static char h225_buffer[65536];
@@ -46,6 +48,161 @@
#endif
/**
+ * Parse an H.225 TransportAddress and return the position of the IP
+ * address (if present). Returns 1 on success.
+ */
+static int h225_parse_transport_address(struct asn1_per_buffer *bb, unsigned *i,
+ u_int32_t *ip, u_int16_t *port) {
+ unsigned choice, after;
+
+ choice = asn1_per_read_choice_header(bb, 1, 7, &after);
+ if (bb->error)
+ return 0;
+
+ switch (choice) {
+ case 0: /* ipAddress */
+ asn1_per_byte_align(bb);
+ *i = bb->i;
+ asn1_per_read_bytes(bb, ip, sizeof(*ip));
+ asn1_per_read_bytes(bb, port, sizeof(*port));
+ return !bb->error;
+
+ default:
+ if (after == 0) {
+ DEBUGP("TransportAddress %u not yet supported\n", choice);
+ bb->error = 1;
+ } else {
+ bb->i = after;
+ }
+ return 0;
+ }
+}
+
+/**
+ * Parse a H.225 Connect-UUIE packet and handle NAT/expectations for
+ * the H.245 transport address.
+ */
+static int h225_parse_connect_uuie(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr;
+
+ asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+ /* protocolIdentifier */
+ asn1_per_skip_object_id(bb);
+
+ /* h245Address */
+ if (asn1_per_bitmap_get(&hdr.present, 0)) {
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_conntrack_expect *exp;
+ int ret;
+ unsigned i;
+ u_int32_t ip;
+ u_int16_t port;
+
+ ret = h225_parse_transport_address(bb, &i, &ip, &port);
+ if (ret) {
+ DEBUGP("H.245 transportAddress: %u.%u.%u.%u:%u\n",
+ NIPQUAD(ip), ntohs(port));
+ }
+ if (ret && ip == ct->tuplehash[dir].tuple.src.ip) {
+ /* match found: create an expectation */
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL)
+ return NF_ACCEPT;
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { ct->tuplehash[!dir].tuple.src.ip,
+ { 0 } },
+ { ct->tuplehash[!dir].tuple.dst.ip,
+ { .tcp = { port } },
+ IPPROTO_TCP }});
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0xFFFFFFFF, { 0 } },
+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+
+ exp->expectfn = ip_conntrack_h245_expect;
+ exp->master = ct;
+
+ /* call NAT hook and register expectation */
+ if (ip_nat_h225_hook != NULL) {
+ return ip_nat_h225_hook(pskb, ctinfo, i,
+ exp);
+ } else {
+ /* Can't expect this? Best to drop packet now. */
+ if (ip_conntrack_expect_related(exp) != 0) {
+ ip_conntrack_expect_free(exp);
+ return NF_DROP;
+ } else {
+ return NF_ACCEPT;
+ }
+ }
+ }
+ }
+
+ /* XXX */
+ bb->error = 1;
+
+ asn1_per_skip_sequence_extension(bb, &hdr);
+
+ return NF_ACCEPT;
+}
+
+/**
+ * Parse a H.225 H323-UU-PDU packet and handle NAT/expectations for
+ * the H.245 transport address.
+ */
+static int h225_parse_uu_pdu(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr;
+ unsigned choice, after;
+ int ret;
+
+ asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+ /* h323-message-body */
+ choice = asn1_per_read_choice_header(bb, 1, 7, &after);
+ switch (choice) {
+ case 2: /* connect */
+ ret = h225_parse_connect_uuie(pskb, ct, ctinfo, bb);
+ if (ret != NF_ACCEPT)
+ return ret;
+ break;
+
+ default:
+ if (after == 0) {
+ bb->error = 1;
+ return NF_ACCEPT;
+ }
+
+ bb->i = after;
+ }
+
+ asn1_per_skip_sequence_extension(bb, &hdr);
+
+ return NF_ACCEPT;
+}
+
+/**
+ * Parse a H.225 packet and handle NAT/expectations for the H.245
+ * transport address.
+ */
+static int h225_parse(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct asn1_per_buffer *bb) {
+ struct asn1_per_sequence_header hdr;
+
+ asn1_per_read_sequence_header(bb, 1, 1, &hdr);
+
+ return h225_parse_uu_pdu(pskb, ct, ctinfo, bb);
+}
+
+/**
* Parse a Q.931 CONNECT packet and handle NAT/expectations for the
* H.245 transport address.
*/
@@ -55,10 +212,7 @@
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;
+ struct asn1_per_buffer bb;
/* protocol(1) + header(3) + protocolIdentifier(6) +
h245ipAddress(1) + h245ipv4(4) + h245ipv4port(2) */
@@ -68,61 +222,9 @@
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;
+ asn1_per_initialize(&bb, data, length, i);
- /* 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;
- }
- }
+ return h225_parse(pskb, ct, ctinfo, &bb);
}
/**
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources
2005-05-10 22:52 ` [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources Max Kellermann
@ 2005-05-11 23:40 ` Patrick McHardy
2005-05-12 5:26 ` Max Kellermann
0 siblings, 1 reply; 13+ messages in thread
From: Patrick McHardy @ 2005-05-11 23:40 UTC (permalink / raw)
To: Max Kellermann; +Cc: netfilter-devel, laforge
Max Kellermann wrote:
> h323-04-split_conntrack_into_3.patch
> - splitted ip_conntrack_h323.c into 3 sources
>
> 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
This file looks a bit unnecessary, I suggest to put register/unregister
in ip_conntrack_h323_h225.c.
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources
2005-05-11 23:40 ` Patrick McHardy
@ 2005-05-12 5:26 ` Max Kellermann
2005-05-17 15:39 ` Patrick McHardy
0 siblings, 1 reply; 13+ messages in thread
From: Max Kellermann @ 2005-05-12 5:26 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, laforge
On 2005/05/12 01:40, Patrick McHardy <kaber@trash.net> wrote:
> Max Kellermann wrote:
> > h323-04-split_conntrack_into_3.patch
> > - splitted ip_conntrack_h323.c into 3 sources
> >
> > 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
>
> This file looks a bit unnecessary, I suggest to put register/unregister
> in ip_conntrack_h323_h225.c.
I splitted the file because it became very large (I dislike sources >
500 lines). I decided to make a _core.c because this way, the _h225.c
and _h245.c contain only protocol parser code, and nothing else -
still having the option to add more "common" code to _core.c (whatever
happens in further development).
In the compiled binary, there is no advantage of merging _core and
_h225.c.
A matter of personal taste. If you vote me down on this one, I'll
change it.
Max
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH pom-ng 7/6] H.323: reimplement the H.225 parser using the ASN.1/PER library
2005-05-11 18:16 ` [PATCH pom-ng 7/6] H.323: reimplement the H.225 parser using the ASN.1/PER library Max Kellermann
@ 2005-05-17 15:18 ` Patrick McHardy
0 siblings, 0 replies; 13+ messages in thread
From: Patrick McHardy @ 2005-05-17 15:18 UTC (permalink / raw)
To: Max Kellermann; +Cc: netfilter-devel, Jozsef Kadlecsik
Max Kellermann wrote:
> An additional patch to this patch series, which I developed today:
>
> h323-07-reimplement_h225_parser_with_asn1_per.patch
> - reimplement the H.225 parser using the ASN.1/PER library
All applied, great work Max.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources
2005-05-12 5:26 ` Max Kellermann
@ 2005-05-17 15:39 ` Patrick McHardy
0 siblings, 0 replies; 13+ messages in thread
From: Patrick McHardy @ 2005-05-17 15:39 UTC (permalink / raw)
To: Max Kellermann; +Cc: netfilter-devel, laforge
Max Kellermann wrote:
> On 2005/05/12 01:40, Patrick McHardy <kaber@trash.net> wrote:
>
>>This file looks a bit unnecessary, I suggest to put register/unregister
>>in ip_conntrack_h323_h225.c.
>
> I splitted the file because it became very large (I dislike sources >
> 500 lines). I decided to make a _core.c because this way, the _h225.c
> and _h245.c contain only protocol parser code, and nothing else -
> still having the option to add more "common" code to _core.c (whatever
> happens in further development).
>
> In the compiled binary, there is no advantage of merging _core and
> _h225.c.
>
> A matter of personal taste. If you vote me down on this one, I'll
> change it.
Well, lets keep it this way for now and wait if something else is added.
If we decide to merge it some day we can still change it.
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2005-05-17 15:39 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-10 22:50 [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Max Kellermann
2005-05-10 22:51 ` [PATCH pom-ng 1/6] H.323: remove struct ip_ct_h225_master Max Kellermann
2005-05-10 22:51 ` [PATCH pom-ng 2/6] add ip_nat_h245() Max Kellermann
2005-05-10 22:52 ` [PATCH pom-ng 3/6] H.323: minor code style fixes Max Kellermann
2005-05-10 22:52 ` [PATCH pom-ng 4/6] H.323: splitted ip_conntrack_h323.c into 3 sources Max Kellermann
2005-05-11 23:40 ` Patrick McHardy
2005-05-12 5:26 ` Max Kellermann
2005-05-17 15:39 ` Patrick McHardy
2005-05-10 22:53 ` [PATCH pom-ng 5/6] H.323: ASN.1/PER parser Max Kellermann
2005-05-10 22:54 ` [PATCH pom-ng 6/6] H.323: H.245/ASN.1 parser Max Kellermann
2005-05-11 8:01 ` [PATCH pom-ng 0/6] H.323: implement a "real" H.245 parser Harald Welte
2005-05-11 18:16 ` [PATCH pom-ng 7/6] H.323: reimplement the H.225 parser using the ASN.1/PER library Max Kellermann
2005-05-17 15:18 ` Patrick McHardy
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.