[netfilter-cvslog] r3601 - in
trunk/patch-o-matic-ng/h323-conntrack-nat: . linux-2.6
linux-2.6/net/ipv4/netfilter
kadlec at netfilter.org
kadlec at netfilter.org
Wed Jan 19 15:18:49 CET 2005
Author: kadlec at netfilter.org
Date: 2005-01-19 15:18:49 +0100 (Wed, 19 Jan 2005)
New Revision: 3601
Added:
trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/
Removed:
trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/Documentation/
Modified:
trunk/patch-o-matic-ng/h323-conntrack-nat/info
trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/Makefile.ladd
trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/ip_conntrack_h323.c
trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/ip_nat_h323.c
Log:
Max Kellermann's 2.6 port added
Modified: trunk/patch-o-matic-ng/h323-conntrack-nat/info
===================================================================
--- trunk/patch-o-matic-ng/h323-conntrack-nat/info 2005-01-16 19:59:42 UTC (rev 3600)
+++ trunk/patch-o-matic-ng/h323-conntrack-nat/info 2005-01-19 14:18:49 UTC (rev 3601)
@@ -1,4 +1,4 @@
-Author: Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+Author: Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>, Max Kellermann <max at duempel.org>
Status: Alpha
Repository: extra
-Requires: linux < 2.6.0
+Requires: linux-2.6 >= 2.6.11
Copied: trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6 (from rev 3600, trunk/patch-o-matic-ng/h323-conntrack-nat/linux)
Modified: trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/Makefile.ladd
===================================================================
--- trunk/patch-o-matic-ng/h323-conntrack-nat/linux/net/ipv4/netfilter/Makefile.ladd 2005-01-16 19:59:42 UTC (rev 3600)
+++ trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/Makefile.ladd 2005-01-19 14:18:49 UTC (rev 3601)
@@ -2,8 +2,5 @@
# H.323 support
obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
-ifdef CONFIG_IP_NF_H323
- export-objs += ip_conntrack_h323.o
-endif
obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
Modified: trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/ip_conntrack_h323.c
===================================================================
--- trunk/patch-o-matic-ng/h323-conntrack-nat/linux/net/ipv4/netfilter/ip_conntrack_h323.c 2005-01-16 19:59:42 UTC (rev 3600)
+++ trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/ip_conntrack_h323.c 2005-01-19 14:18:49 UTC (rev 3601)
@@ -1,6 +1,7 @@
-/*
- * H.323 'brute force' extension for H.323 connection tracking.
+/*
+ * H.323 'brute force' extension for H.323 connection tracking.
* Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ * (c) 2005 Max Kellermann <max at duempel.org>
*
* Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
* (http://www.coritel.it/projects/sofia/nat/)
@@ -26,6 +27,10 @@
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(h323_buffer_lock);
+
DECLARE_LOCK(ip_h323_lock);
struct module *ip_conntrack_h323 = THIS_MODULE;
@@ -36,31 +41,24 @@
#endif
/* FIXME: This should be in userspace. Later. */
-static int h245_help(const struct iphdr *iph, size_t len,
+static int h245_help(struct sk_buff *skb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo)
{
- struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
- unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
+ struct iphdr *iph = skb->nh.iph;
+ struct tcphdr _tcph, *tcph;
+ unsigned char *data;
unsigned char *data_limit;
- u_int32_t tcplen = len - iph->ihl * 4;
- u_int32_t datalen = tcplen - tcph->doff * 4;
+ unsigned dataoff, datalen;
int dir = CTINFO2DIR(ctinfo);
struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
- struct ip_conntrack_expect expect, *exp = &expect;
- struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
+ struct ip_conntrack_expect *exp;
+ struct ip_ct_h225_expect *exp_info;
u_int16_t data_port;
u_int32_t data_ip;
unsigned int i;
+ int ret;
- DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
- NIPQUAD(iph->saddr), ntohs(tcph->source),
- NIPQUAD(iph->daddr), ntohs(tcph->dest));
-
- /* Can't track connections formed before we registered */
- if (!info)
- return NF_ACCEPT;
-
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED
&& ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
@@ -68,34 +66,49 @@
return NF_ACCEPT;
}
- /* Not whole TCP header or too short packet? */
- if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
- DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
+ tcph = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+ sizeof(_tcph), &_tcph);
+ if (tcph == NULL)
return NF_ACCEPT;
- }
- /* Checksum invalid? Ignore. */
- /* FIXME: Source route IP option packets --RR */
- if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
- csum_partial((char *)tcph, tcplen, 0))) {
- DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
- tcph, tcplen, NIPQUAD(iph->saddr),
- NIPQUAD(iph->daddr));
+ DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+ NIPQUAD(iph->saddr), ntohs(tcph->source),
+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
+
+ dataoff = skb->nh.iph->ihl*4 + tcph->doff*4;
+ /* No data? */
+ if (dataoff >= skb->len) {
+ DEBUGP("ct_h245_help: skblen = %u\n", skb->len);
return NF_ACCEPT;
}
+ datalen = skb->len - dataoff;
- data_limit = (unsigned char *) data + datalen;
+ LOCK_BH(&h323_buffer_lock);
+ data = skb_header_pointer(skb, dataoff,
+ datalen, h323_buffer);
+ BUG_ON(data == NULL);
+
+ data_limit = data + datalen - 6;
/* bytes: 0123 45
ipadrr port */
- for (i = 0; data < (data_limit - 5); data++, i++) {
+ for (i = 0; data <= data_limit; data++, i++) {
data_ip = *((u_int32_t *)data);
if (data_ip == iph->saddr) {
data_port = *((u_int16_t *)(data + 4));
- memset(&expect, 0, sizeof(expect));
+
/* update the H.225 info */
DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
NIPQUAD(iph->saddr), ntohs(data_port));
+
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL) {
+ ret = NF_ACCEPT;
+ goto out;
+ }
+
+ exp_info = &exp->help.exp_h225_info;
+
LOCK_BH(&ip_h323_lock);
info->is_h225 = H225_PORT + 1;
exp_info->port = data_port;
@@ -103,7 +116,7 @@
exp_info->offset = i;
exp->seq = ntohl(tcph->seq) + i;
-
+
exp->tuple = ((struct ip_conntrack_tuple)
{ { ct->tuplehash[!dir].tuple.src.ip,
{ 0 } },
@@ -113,34 +126,33 @@
exp->mask = ((struct ip_conntrack_tuple)
{ { 0xFFFFFFFF, { 0 } },
{ 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
-
+
exp->expectfn = NULL;
-
+
/* Ignore failure; should only happen with NAT */
- ip_conntrack_expect_related(ct, exp);
+ ip_conntrack_expect_related(exp, ct);
UNLOCK_BH(&ip_h323_lock);
}
}
- return NF_ACCEPT;
-
+ ret = NF_ACCEPT;
+ out:
+ UNLOCK_BH(&h323_buffer_lock);
+ return ret;
}
/* H.245 helper is not registered! */
-static struct ip_conntrack_helper h245 =
- { { NULL, NULL },
- "H.245", /* name */
- IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
- NULL, /* module */
- 8, /* max_ expected */
- 240, /* timeout */
- { { 0, { 0 } }, /* tuple */
- { 0, { 0 }, IPPROTO_TCP } },
- { { 0, { 0xFFFF } }, /* mask */
- { 0, { 0 }, 0xFFFF } },
- h245_help /* helper */
- };
+static struct ip_conntrack_helper h245 = {
+ .name = "H.245",
+ .flags = IP_CT_HELPER_F_REUSE_EXPECT,
+ .max_expected = 8,
+ .timeout = 240,
+ .tuple = { .dst = { .protonum = IPPROTO_TCP } },
+ .mask = { .src = { .u = { 0xFFFF } },
+ .dst = { .protonum = 0xFFFF } },
+ .help = h245_help
+};
static int h225_expect(struct ip_conntrack *ct)
{
@@ -148,36 +160,29 @@
ct->helper = &h245;
DEBUGP("h225_expect: helper for %p added\n", ct);
WRITE_UNLOCK(&ip_conntrack_lock);
-
+
return NF_ACCEPT; /* unused */
}
/* FIXME: This should be in userspace. Later. */
-static int h225_help(const struct iphdr *iph, size_t len,
+static int h225_help(struct sk_buff *skb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo)
{
- struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
- unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
+ struct iphdr *iph = skb->nh.iph;
+ struct tcphdr _tcph, *tcph;
+ unsigned char *data;
unsigned char *data_limit;
- u_int32_t tcplen = len - iph->ihl * 4;
- u_int32_t datalen = tcplen - tcph->doff * 4;
+ unsigned dataoff, datalen;
int dir = CTINFO2DIR(ctinfo);
struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
- struct ip_conntrack_expect expect, *exp = &expect;
- struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
+ struct ip_conntrack_expect *exp;
+ struct ip_ct_h225_expect *exp_info;
u_int16_t data_port;
u_int32_t data_ip;
unsigned int i;
-
- DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
- NIPQUAD(iph->saddr), ntohs(tcph->source),
- NIPQUAD(iph->daddr), ntohs(tcph->dest));
+ int ret;
- /* Can't track connections formed before we registered */
- if (!info)
- return NF_ACCEPT;
-
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED
&& ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
@@ -185,26 +190,32 @@
return NF_ACCEPT;
}
- /* Not whole TCP header or too short packet? */
- if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
- DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
+ tcph = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+ sizeof(_tcph), &_tcph);
+ if (tcph == NULL)
return NF_ACCEPT;
- }
- /* Checksum invalid? Ignore. */
- /* FIXME: Source route IP option packets --RR */
- if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
- csum_partial((char *)tcph, tcplen, 0))) {
- DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
- tcph, tcplen, NIPQUAD(iph->saddr),
- NIPQUAD(iph->daddr));
+ DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+ NIPQUAD(iph->saddr), ntohs(tcph->source),
+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
+
+ dataoff = skb->nh.iph->ihl*4 + tcph->doff*4;
+ /* No data? */
+ if (dataoff >= skb->len) {
+ DEBUGP("ct_h225_help: skblen = %u\n", skb->len);
return NF_ACCEPT;
}
-
- data_limit = (unsigned char *) data + datalen;
+ datalen = skb->len - dataoff;
+
+ LOCK_BH(&h323_buffer_lock);
+ data = skb_header_pointer(skb, dataoff,
+ datalen, h323_buffer);
+ BUG_ON(data == NULL);
+
+ data_limit = data + datalen - 6;
/* bytes: 0123 45
ipadrr port */
- for (i = 0; data < (data_limit - 5); data++, i++) {
+ for (i = 0; data <= data_limit; data++, i++) {
data_ip = *((u_int32_t *)data);
if (data_ip == iph->saddr) {
data_port = *((u_int16_t *)(data + 4));
@@ -222,9 +233,15 @@
UNLOCK_BH(&ip_h323_lock);
#endif
} else {
- memset(&expect, 0, sizeof(expect));
+ /* update the H.225 info */
+ exp = ip_conntrack_expect_alloc();
+ if (exp == NULL) {
+ ret = NF_ACCEPT;
+ goto out;
+ }
- /* update the H.225 info */
+ exp_info = &exp->help.exp_h225_info;
+
LOCK_BH(&ip_h323_lock);
info->is_h225 = H225_PORT;
exp_info->port = data_port;
@@ -242,18 +259,18 @@
exp->mask = ((struct ip_conntrack_tuple)
{ { 0xFFFFFFFF, { 0 } },
{ 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
-
+
exp->expectfn = h225_expect;
-
+
/* Ignore failure */
- ip_conntrack_expect_related(ct, exp);
+ ip_conntrack_expect_related(exp, ct);
DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
NIPQUAD(iph->saddr), ntohs(data_port));
UNLOCK_BH(&ip_h323_lock);
- }
+ }
#ifdef CONFIG_IP_NF_NAT_NEEDED
} else if (data_ip == iph->daddr) {
data_port = *((u_int16_t *)(data + 4));
@@ -273,23 +290,24 @@
}
}
- return NF_ACCEPT;
-
+ ret = NF_ACCEPT;
+ out:
+ UNLOCK_BH(&h323_buffer_lock);
+ return ret;
}
-static struct ip_conntrack_helper h225 =
- { { NULL, NULL },
- "H.225", /* name */
- IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
- THIS_MODULE, /* module */
- 2, /* max_expected */
- 240, /* timeout */
- { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
- { 0, { 0 }, IPPROTO_TCP } },
- { { 0, { 0xFFFF } }, /* mask */
- { 0, { 0 }, 0xFFFF } },
- h225_help /* helper */
- };
+static struct ip_conntrack_helper h225 = {
+ .name = "H.225",
+ .flags = IP_CT_HELPER_F_REUSE_EXPECT,
+ .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 = 0xFFFF } },
+ .help = h225_help
+};
static int __init init(void)
{
@@ -298,11 +316,13 @@
static void __exit fini(void)
{
- /* Unregister H.225 helper */
+ /* Unregister H.225 helper */
ip_conntrack_helper_unregister(&h225);
}
EXPORT_SYMBOL(ip_h323_lock);
+PROVIDES_CONNTRACK(h225);
+PROVIDES_CONNTRACK(h245);
module_init(init);
module_exit(fini);
Modified: trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/ip_nat_h323.c
===================================================================
--- trunk/patch-o-matic-ng/h323-conntrack-nat/linux/net/ipv4/netfilter/ip_nat_h323.c 2005-01-16 19:59:42 UTC (rev 3600)
+++ trunk/patch-o-matic-ng/h323-conntrack-nat/linux-2.6/net/ipv4/netfilter/ip_nat_h323.c 2005-01-19 14:18:49 UTC (rev 3601)
@@ -1,6 +1,7 @@
-/*
- * H.323 'brute force' extension for NAT alteration.
+/*
+ * H.323 'brute force' extension for NAT alteration.
* Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ * (c) 2005 Max Kellermann <max at duempel.org>
*
* Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
* (http://www.coritel.it/projects/sofia/nat.html)
@@ -38,7 +39,7 @@
/* FIXME: Time out? --RR */
-static unsigned int
+static unsigned int
h225_nat_expected(struct sk_buff **pskb,
unsigned int hooknum,
struct ip_conntrack *ct,
@@ -46,38 +47,38 @@
static unsigned int h225_nat_help(struct ip_conntrack *ct,
struct ip_conntrack_expect *exp,
- struct ip_nat_info *info,
- enum ip_conntrack_info ctinfo,
- unsigned int hooknum,
- struct sk_buff **pskb);
-
-static struct ip_nat_helper h245 =
- { { NULL, NULL },
- "H.245", /* name */
- 0, /* flags */
- NULL, /* module */
- { { 0, { 0 } }, /* tuple */
- { 0, { 0 }, IPPROTO_TCP } },
- { { 0, { 0xFFFF } }, /* mask */
- { 0, { 0 }, 0xFFFF } },
- h225_nat_help, /* helper */
- h225_nat_expected /* expectfn */
- };
+ struct ip_nat_info *info,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb);
+static struct ip_nat_helper h245 = {
+ .list = { NULL, NULL },
+ .name = "H.245",
+ .flags = 0,
+ .me = THIS_MODULE,
+ .tuple = { { 0, { 0 } },
+ { 0, { 0 }, IPPROTO_TCP } },
+ .mask = { { 0, { 0xFFFF } },
+ { 0, { 0 }, 0xFFFF } },
+ .help = h225_nat_help,
+ .expect = h225_nat_expected
+};
+
static unsigned int
h225_nat_expected(struct sk_buff **pskb,
unsigned int hooknum,
struct ip_conntrack *ct,
struct ip_nat_info *info)
{
- struct ip_nat_multi_range mr;
+ struct ip_nat_range range;
u_int32_t newdstip, newsrcip, newip;
u_int16_t port;
struct ip_ct_h225_expect *exp_info;
struct ip_ct_h225_master *master_info;
struct ip_conntrack *master = master_ct(ct);
unsigned int is_h225, ret;
-
+
IP_NF_ASSERT(info);
IP_NF_ASSERT(master);
@@ -110,7 +111,7 @@
port = exp_info->port;
is_h225 = master_info->is_h225 == H225_PORT;
UNLOCK_BH(&ip_h323_lock);
-
+
if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
newip = newsrcip;
else
@@ -118,22 +119,21 @@
DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
- mr.rangesize = 1;
/* We don't want to manip the per-protocol, just the IPs... */
- mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
- mr.range[0].min_ip = mr.range[0].max_ip = newip;
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip = newip;
/* ... unless we're doing a MANIP_DST, in which case, make
sure we map to the correct port */
if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
- mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
- mr.range[0].min = mr.range[0].max
+ range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ range.min = range.max
= ((union ip_conntrack_manip_proto)
{ .tcp = { port } });
}
- ret = ip_nat_setup_info(ct, &mr, hooknum);
-
+ ret = ip_nat_setup_info(ct, &range, hooknum);
+
if (is_h225) {
DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
/* NAT expectfn called with ip_nat_lock write-locked */
@@ -143,19 +143,27 @@
}
static int h323_signal_address_fixup(struct ip_conntrack *ct,
- struct sk_buff **pskb,
- enum ip_conntrack_info ctinfo)
+ struct sk_buff **pskb,
+ enum ip_conntrack_info ctinfo)
{
struct iphdr *iph = (*pskb)->nh.iph;
- struct tcphdr *tcph = (void *)iph + iph->ihl*4;
- char *data = (char *) tcph + tcph->doff * 4;
- u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
- u_int32_t datalen = tcplen - tcph->doff*4;
- struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
- u_int32_t newip;
- u_int16_t port;
+ struct tcphdr _tcph, *tcph;
+ u_int32_t tcplen, datalen;
+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
+ struct {
+ u_int32_t ip;
+ u_int16_t port;
+ } __attribute__ ((__packed__)) newdata;
int i;
+ int ret;
+ tcph = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_tcph), &_tcph);
+ if (tcph == NULL)
+ return NF_ACCEPT;
+
+ tcplen = (*pskb)->len - iph->ihl * 4;
+ datalen = tcplen - tcph->doff * 4;
+
MUST_BE_LOCKED(&ip_h323_lock);
DEBUGP("h323_signal_address_fixup: %s %s\n",
@@ -167,8 +175,8 @@
|| between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
return 1;
- DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
- info->offset[IP_CT_DIR_ORIGINAL],
+ DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
+ info->offset[IP_CT_DIR_ORIGINAL],
info->offset[IP_CT_DIR_REPLY],
tcplen);
DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
@@ -178,7 +186,7 @@
DEBUGP("h323_signal_address_fixup: %s %s\n",
info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
- if (!between(info->seq[i], ntohl(tcph->seq),
+ if (!between(info->seq[i], ntohl(tcph->seq),
ntohl(tcph->seq) + datalen))
continue;
if (!between(info->seq[i] + 6, ntohl(tcph->seq),
@@ -196,39 +204,22 @@
/* Change address inside packet to match way we're mapping
this connection. */
if (i == IP_CT_DIR_ORIGINAL) {
- newip = ct->tuplehash[!info->dir].tuple.dst.ip;
- port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
+ newdata.ip = ct->tuplehash[!info->dir].tuple.dst.ip;
+ newdata.port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
} else {
- newip = ct->tuplehash[!info->dir].tuple.src.ip;
- port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
+ newdata.ip = ct->tuplehash[!info->dir].tuple.src.ip;
+ newdata.port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
}
- DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
- i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
- NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
- ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
-
/* Modify the packet */
- *(u_int32_t *)(data + info->offset[i]) = newip;
- *(u_int16_t *)(data + info->offset[i] + 4) = port;
-
- DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
- i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
- NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
- ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
+ ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ info->seq[i] - ntohl(tcph->seq),
+ sizeof(newdata),
+ (const char*)&newdata, sizeof(newdata));
+ if (!ret)
+ return 0;
}
- /* fix checksum information */
-
- (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
- datalen, 0);
-
- tcph->check = 0;
- tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
- csum_partial((char *)tcph, tcph->doff*4,
- (*pskb)->csum));
- ip_send_check(iph);
-
return 1;
}
@@ -238,16 +229,24 @@
enum ip_conntrack_info ctinfo,
struct ip_conntrack_expect *expect)
{
- u_int32_t newip;
- u_int16_t port;
+ struct {
+ u_int32_t ip;
+ u_int16_t port;
+ } __attribute__ ((__packed__)) newdata;
struct ip_conntrack_tuple newtuple;
struct iphdr *iph = (*pskb)->nh.iph;
- struct tcphdr *tcph = (void *)iph + iph->ihl*4;
- char *data = (char *) tcph + tcph->doff * 4;
- u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
+ struct tcphdr _tcph, *tcph;
+ u_int32_t tcplen;
struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
int is_h225;
+ int ret;
+ tcph = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_tcph), &_tcph);
+ if (tcph == NULL)
+ return NF_ACCEPT;
+
+ tcplen = (*pskb)->len - iph->ihl * 4;
+
MUST_BE_LOCKED(&ip_h323_lock);
DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
@@ -269,13 +268,13 @@
this connection. */
if (info->dir == IP_CT_DIR_REPLY) {
/* Must be where client thinks server is */
- newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+ newdata.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
/* Expect something from client->server */
newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
} else {
/* Must be where server thinks client is */
- newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+ newdata.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
/* Expect something from server->client */
newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
@@ -290,61 +289,45 @@
newtuple.dst.protonum = IPPROTO_UDP;
newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
}
-
+
/* Try to get same port: if not, try to change it. */
- for (port = ntohs(info->port); port != 0; port++) {
+ for (newdata.port = ntohs(info->port); newdata.port != 0; newdata.port++) {
if (is_h225)
- newtuple.dst.u.tcp.port = htons(port);
+ newtuple.dst.u.tcp.port = htons(newdata.port);
else
- newtuple.dst.u.udp.port = htons(port);
+ newtuple.dst.u.udp.port = htons(newdata.port);
if (ip_conntrack_change_expect(expect, &newtuple) == 0)
break;
}
- if (port == 0) {
+ if (newdata.port == 0) {
DEBUGP("h323_data_fixup: no free port found!\n");
return 0;
}
- port = htons(port);
+ newdata.port = htons(newdata.port);
- DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
- NIPQUAD(*((u_int32_t *)(data + info->offset))),
- ntohs(*((u_int16_t *)(data + info->offset + 4))));
-
/* Modify the packet */
- *(u_int32_t *)(data + info->offset) = newip;
- *(u_int16_t *)(data + info->offset + 4) = port;
-
- DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
- NIPQUAD(*((u_int32_t *)(data + info->offset))),
- ntohs(*((u_int16_t *)(data + info->offset + 4))));
+ ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ expect->seq - ntohl(tcph->seq),
+ sizeof(newdata),
+ (const char*)&newdata, sizeof(newdata));
+ if (!ret)
+ return 0;
- /* fix checksum information */
- /* FIXME: usually repeated multiple times in the case of H.245! */
-
- (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
- tcplen - tcph->doff*4, 0);
-
- tcph->check = 0;
- tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
- csum_partial((char *)tcph, tcph->doff*4,
- (*pskb)->csum));
- ip_send_check(iph);
-
return 1;
}
static unsigned int h225_nat_help(struct ip_conntrack *ct,
struct ip_conntrack_expect *exp,
- struct ip_nat_info *info,
- enum ip_conntrack_info ctinfo,
- unsigned int hooknum,
- struct sk_buff **pskb)
+ struct ip_nat_info *info,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum,
+ struct sk_buff **pskb)
{
int dir;
struct ip_ct_h225_expect *exp_info;
-
+
/* Only mangle things once: original direction in POST_ROUTING
and reply direction on PRE_ROUTING. */
dir = CTINFO2DIR(ctinfo);
@@ -372,7 +355,7 @@
UNLOCK_BH(&ip_h323_lock);
return NF_ACCEPT;
}
-
+
exp_info = &exp->help.exp_h225_info;
LOCK_BH(&ip_h323_lock);
@@ -385,23 +368,23 @@
return NF_ACCEPT;
}
-static struct ip_nat_helper h225 =
- { { NULL, NULL },
- "H.225", /* name */
- IP_NAT_HELPER_F_ALWAYS, /* flags */
- THIS_MODULE, /* module */
- { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
- { 0, { 0 }, IPPROTO_TCP } },
- { { 0, { .tcp = { 0xFFFF } } }, /* mask */
- { 0, { 0 }, 0xFFFF } },
- h225_nat_help, /* helper */
- h225_nat_expected /* expectfn */
- };
+static struct ip_nat_helper h225 = {
+ .list = { NULL, NULL },
+ .name = "H.225",
+ .flags = IP_NAT_HELPER_F_ALWAYS,
+ .me = THIS_MODULE,
+ .tuple = { { 0, { .tcp = { __constant_htons(H225_PORT) } } },
+ { 0, { 0 }, IPPROTO_TCP } },
+ .mask = { { 0, { .tcp = { 0xFFFF } } },
+ { 0, { 0 }, 0xFFFF } },
+ .help = h225_nat_help,
+ .expect = h225_nat_expected
+};
static int __init init(void)
{
int ret;
-
+
ret = ip_nat_helper_register(&h225);
if (ret != 0)
@@ -415,5 +398,7 @@
ip_nat_helper_unregister(&h225);
}
+NEEDS_CONNTRACK(h225);
+NEEDS_CONNTRACK(h245);
module_init(init);
module_exit(fini);
More information about the netfilter-cvslog
mailing list