1 Index: linux-2.4.35.4/net/ipv4/netfilter/Config.in
2 ===================================================================
3 --- linux-2.4.35.4.orig/net/ipv4/netfilter/Config.in 2009-06-06 22:34:34.000000000 +0000
4 +++ linux-2.4.35.4/net/ipv4/netfilter/Config.in 2009-06-06 22:37:34.000000000 +0000
6 dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
7 dep_tristate ' Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK
8 dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
9 + dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
12 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
14 define_tristate CONFIG_IP_NF_NAT_AMANDA $CONFIG_IP_NF_NAT
17 + if [ "$CONFIG_IP_NF_H323" = "m" ]; then
18 + define_tristate CONFIG_IP_NF_NAT_H323 m
20 + if [ "$CONFIG_IP_NF_H323" = "y" ]; then
21 + define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
24 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25 dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
27 Index: linux-2.4.35.4/net/ipv4/netfilter/Makefile
28 ===================================================================
29 --- linux-2.4.35.4.orig/net/ipv4/netfilter/Makefile 2009-06-06 22:34:34.000000000 +0000
30 +++ linux-2.4.35.4/net/ipv4/netfilter/Makefile 2009-06-06 22:46:32.000000000 +0000
32 ifdef CONFIG_IP_NF_IRC
33 export-objs += ip_conntrack_irc.o
35 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
36 +ifdef CONFIG_IP_NF_NAT_H323
37 + export-objs += ip_conntrack_h323.o
41 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
42 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
43 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
44 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
45 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
48 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
49 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_h323.c
50 ===================================================================
51 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
52 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_conntrack_h323.c 2009-06-06 22:34:50.000000000 +0000
55 + * H.323 'brute force' extension for H.323 connection tracking.
56 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
58 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
59 + * (http://www.coritel.it/projects/sofia/nat/)
60 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
61 + * the unregistered helpers to the conntrack entries.
65 +#include <linux/module.h>
66 +#include <linux/netfilter.h>
67 +#include <linux/ip.h>
68 +#include <net/checksum.h>
71 +#include <linux/netfilter_ipv4/lockhelp.h>
72 +#include <linux/netfilter_ipv4/ip_conntrack.h>
73 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
74 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
75 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
76 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
78 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
79 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
80 +MODULE_LICENSE("GPL");
82 +DECLARE_LOCK(ip_h323_lock);
83 +struct module *ip_conntrack_h323 = THIS_MODULE;
85 +#define DEBUGP(format, args...)
87 +static int h245_help(const struct iphdr *iph, size_t len,
88 + struct ip_conntrack *ct,
89 + enum ip_conntrack_info ctinfo)
91 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
92 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
93 + unsigned char *data_limit;
94 + u_int32_t tcplen = len - iph->ihl * 4;
95 + u_int32_t datalen = tcplen - tcph->doff * 4;
96 + int dir = CTINFO2DIR(ctinfo);
97 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
98 + struct ip_conntrack_expect expect, *exp = &expect;
99 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
100 + u_int16_t data_port;
104 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
105 + NIPQUAD(iph->saddr), ntohs(tcph->source),
106 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
108 + /* Can't track connections formed before we registered */
112 + /* Until there's been traffic both ways, don't look in packets. */
113 + if (ctinfo != IP_CT_ESTABLISHED
114 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
115 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
119 + /* Not whole TCP header or too short packet? */
120 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
121 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
125 + /* Checksum invalid? Ignore. */
126 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
127 + csum_partial((char *)tcph, tcplen, 0))) {
128 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
129 + tcph, tcplen, NIPQUAD(iph->saddr),
130 + NIPQUAD(iph->daddr));
134 + data_limit = (unsigned char *) data + datalen;
137 + for (i = 0; data < (data_limit - 5); data++, i++) {
138 + memcpy(&data_ip, data, sizeof(u_int32_t));
139 + if (data_ip == iph->saddr) {
140 + memcpy(&data_port, data + 4, sizeof(u_int16_t));
141 + memset(&expect, 0, sizeof(expect));
142 + /* update the H.225 info */
143 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
144 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
145 + NIPQUAD(iph->saddr), ntohs(data_port));
146 + LOCK_BH(&ip_h323_lock);
147 + info->is_h225 = H225_PORT + 1;
148 + exp_info->port = data_port;
149 + exp_info->dir = dir;
150 + exp_info->offset = i;
152 + exp->seq = ntohl(tcph->seq) + i;
154 + exp->tuple = ((struct ip_conntrack_tuple)
155 + { { ct->tuplehash[!dir].tuple.src.ip,
160 + exp->mask = ((struct ip_conntrack_tuple)
161 + { { 0xFFFFFFFF, { 0 } },
162 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
164 + exp->expectfn = NULL;
166 + /* Ignore failure; should only happen with NAT */
167 + ip_conntrack_expect_related(ct, exp);
169 + UNLOCK_BH(&ip_h323_lock);
177 +/* H.245 helper is not registered! */
178 +static struct ip_conntrack_helper h245 =
180 + "H.245", /* name */
181 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
183 + 8, /* max_ expected */
185 + { { 0, { 0 } }, /* tuple */
186 + { 0, { 0 }, IPPROTO_TCP } },
187 + { { 0, { 0xFFFF } }, /* mask */
188 + { 0, { 0 }, 0xFFFF } },
189 + h245_help /* helper */
192 +static int h225_expect(struct ip_conntrack *ct)
194 + WRITE_LOCK(&ip_conntrack_lock);
195 + ct->helper = &h245;
196 + DEBUGP("h225_expect: helper for %p added\n", ct);
197 + WRITE_UNLOCK(&ip_conntrack_lock);
199 + return NF_ACCEPT; /* unused */
202 +static int h225_help(const struct iphdr *iph, size_t len,
203 + struct ip_conntrack *ct,
204 + enum ip_conntrack_info ctinfo)
206 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
207 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
208 + unsigned char *data_limit;
209 + u_int32_t tcplen = len - iph->ihl * 4;
210 + u_int32_t datalen = tcplen - tcph->doff * 4;
211 + int dir = CTINFO2DIR(ctinfo);
212 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
213 + struct ip_conntrack_expect expect, *exp = &expect;
214 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
215 + u_int16_t data_port;
219 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
220 + NIPQUAD(iph->saddr), ntohs(tcph->source),
221 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
223 + /* Can't track connections formed before we registered */
227 + /* Until there's been traffic both ways, don't look in packets. */
228 + if (ctinfo != IP_CT_ESTABLISHED
229 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
230 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
234 + /* Not whole TCP header or too short packet? */
235 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
236 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
240 + /* Checksum invalid? Ignore. */
241 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
242 + csum_partial((char *)tcph, tcplen, 0))) {
243 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
244 + tcph, tcplen, NIPQUAD(iph->saddr),
245 + NIPQUAD(iph->daddr));
249 + data_limit = (unsigned char *) data + datalen;
252 + for (i = 0; data < (data_limit - 5); data++, i++) {
253 + memcpy(&data_ip, data, sizeof(u_int32_t));
254 + if (data_ip == iph->saddr) {
255 + memcpy(&data_port, data + 4, sizeof(u_int16_t));
256 + if (data_port == tcph->source) {
257 + /* Signal address */
258 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
259 + NIPQUAD(iph->saddr));
260 + /* Update the H.225 info so that NAT can mangle the address/port
261 + even when we have no expected connection! */
262 +#ifdef CONFIG_IP_NF_NAT_NEEDED
263 + LOCK_BH(&ip_h323_lock);
265 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
266 + info->offset[IP_CT_DIR_ORIGINAL] = i;
267 + UNLOCK_BH(&ip_h323_lock);
270 + memset(&expect, 0, sizeof(expect));
272 + /* update the H.225 info */
273 + LOCK_BH(&ip_h323_lock);
274 + info->is_h225 = H225_PORT;
275 + exp_info->port = data_port;
276 + exp_info->dir = dir;
277 + exp_info->offset = i;
279 + exp->seq = ntohl(tcph->seq) + i;
281 + exp->tuple = ((struct ip_conntrack_tuple)
282 + { { ct->tuplehash[!dir].tuple.src.ip,
287 + exp->mask = ((struct ip_conntrack_tuple)
288 + { { 0xFFFFFFFF, { 0 } },
289 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
291 + exp->expectfn = h225_expect;
293 + /* Ignore failure */
294 + ip_conntrack_expect_related(ct, exp);
296 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
297 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
298 + NIPQUAD(iph->saddr), ntohs(data_port));
300 + UNLOCK_BH(&ip_h323_lock);
302 +#ifdef CONFIG_IP_NF_NAT_NEEDED
303 + } else if (data_ip == iph->daddr) {
304 + memcpy(&data_port, data + 4, sizeof(u_int16_t));
305 + if (data_port == tcph->dest) {
306 + /* Signal address */
307 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
308 + NIPQUAD(iph->daddr));
309 + /* Update the H.225 info so that NAT can mangle the address/port
310 + even when we have no expected connection! */
311 + LOCK_BH(&ip_h323_lock);
313 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
314 + info->offset[IP_CT_DIR_REPLY] = i;
315 + UNLOCK_BH(&ip_h323_lock);
325 +static struct ip_conntrack_helper h225 =
327 + "H.225", /* name */
328 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
329 + THIS_MODULE, /* module */
330 + 2, /* max_expected */
332 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
333 + { 0, { 0 }, IPPROTO_TCP } },
334 + { { 0, { 0xFFFF } }, /* mask */
335 + { 0, { 0 }, 0xFFFF } },
336 + h225_help /* helper */
339 +static int __init init(void)
341 + return ip_conntrack_helper_register(&h225);
344 +static void __exit fini(void)
346 + /* Unregister H.225 helper */
347 + ip_conntrack_helper_unregister(&h225);
350 +#ifdef CONFIG_IP_NF_NAT_NEEDED
351 +EXPORT_SYMBOL(ip_h323_lock);
356 Index: linux-2.4.35.4/net/ipv4/netfilter/ip_nat_h323.c
357 ===================================================================
358 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
359 +++ linux-2.4.35.4/net/ipv4/netfilter/ip_nat_h323.c 2009-06-06 22:34:50.000000000 +0000
362 + * H.323 'brute force' extension for NAT alteration.
363 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
365 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
366 + * (http://www.coritel.it/projects/sofia/nat.html)
367 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
368 + * the unregistered helpers to the conntrack entries.
372 +#include <linux/module.h>
373 +#include <linux/netfilter.h>
374 +#include <linux/ip.h>
375 +#include <net/checksum.h>
376 +#include <net/tcp.h>
378 +#include <linux/netfilter_ipv4/lockhelp.h>
379 +#include <linux/netfilter_ipv4/ip_nat.h>
380 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
381 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
382 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
383 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
384 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
386 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
387 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
388 +MODULE_LICENSE("GPL");
390 +DECLARE_LOCK_EXTERN(ip_h323_lock);
391 +struct module *ip_nat_h323 = THIS_MODULE;
393 +#define DEBUGP(format, args...)
397 +h225_nat_expected(struct sk_buff **pskb,
398 + unsigned int hooknum,
399 + struct ip_conntrack *ct,
400 + struct ip_nat_info *info);
402 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
403 + struct ip_conntrack_expect *exp,
404 + struct ip_nat_info *info,
405 + enum ip_conntrack_info ctinfo,
406 + unsigned int hooknum,
407 + struct sk_buff **pskb);
409 +static struct ip_nat_helper h245 =
411 + "H.245", /* name */
414 + { { 0, { 0 } }, /* tuple */
415 + { 0, { 0 }, IPPROTO_TCP } },
416 + { { 0, { 0xFFFF } }, /* mask */
417 + { 0, { 0 }, 0xFFFF } },
418 + h225_nat_help, /* helper */
419 + h225_nat_expected /* expectfn */
423 +h225_nat_expected(struct sk_buff **pskb,
424 + unsigned int hooknum,
425 + struct ip_conntrack *ct,
426 + struct ip_nat_info *info)
428 + struct ip_nat_multi_range mr;
429 + u_int32_t newdstip, newsrcip, newip;
431 + struct ip_ct_h225_expect *exp_info;
432 + struct ip_ct_h225_master *master_info;
433 + struct ip_conntrack *master = master_ct(ct);
434 + unsigned int is_h225, ret;
436 + IP_NF_ASSERT(info);
437 + IP_NF_ASSERT(master);
439 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
441 + DEBUGP("h225_nat_expected: We have a connection!\n");
442 + master_info = &ct->master->expectant->help.ct_h225_info;
443 + exp_info = &ct->master->help.exp_h225_info;
445 + LOCK_BH(&ip_h323_lock);
447 + DEBUGP("master: ");
448 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
449 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
450 + DEBUGP("conntrack: ");
451 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
452 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
453 + /* Make connection go to the client. */
454 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
455 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
456 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
457 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
459 + /* Make the connection go to the server */
460 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
461 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
462 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
463 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
465 + port = exp_info->port;
466 + is_h225 = master_info->is_h225 == H225_PORT;
467 + UNLOCK_BH(&ip_h323_lock);
469 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
474 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
477 + /* We don't want to manip the per-protocol, just the IPs... */
478 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
479 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
481 + /* ... unless we're doing a MANIP_DST, in which case, make
482 + sure we map to the correct port */
483 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
484 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
485 + mr.range[0].min = mr.range[0].max
486 + = ((union ip_conntrack_manip_proto)
490 + ret = ip_nat_setup_info(ct, &mr, hooknum);
493 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
494 + /* NAT expectfn called with ip_nat_lock write-locked */
495 + info->helper = &h245;
500 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
501 + struct sk_buff **pskb,
502 + enum ip_conntrack_info ctinfo)
504 + struct iphdr *iph = (*pskb)->nh.iph;
505 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
506 + unsigned char *data;
507 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
508 + u_int32_t datalen = tcplen - tcph->doff*4;
509 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
512 + u_int8_t buffer[6];
515 + MUST_BE_LOCKED(&ip_h323_lock);
517 + DEBUGP("h323_signal_address_fixup: %s %s\n",
518 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
520 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
522 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
523 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
526 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
527 + info->offset[IP_CT_DIR_ORIGINAL],
528 + info->offset[IP_CT_DIR_REPLY],
530 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
531 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
533 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
534 + DEBUGP("h323_signal_address_fixup: %s %s\n",
535 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
536 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
537 + if (!between(info->seq[i], ntohl(tcph->seq),
538 + ntohl(tcph->seq) + datalen))
540 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
541 + ntohl(tcph->seq) + datalen)) {
542 + /* Partial retransmisison. It's a cracker being funky. */
543 + if (net_ratelimit()) {
544 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
547 + ntohl(tcph->seq) + datalen);
552 + /* Change address inside packet to match way we're mapping
553 + this connection. */
554 + if (i == IP_CT_DIR_ORIGINAL) {
555 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
556 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
558 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
559 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
562 + data = (char *) tcph + tcph->doff * 4 + info->offset[i];
564 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
565 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
566 + data[0], data[1], data[2], data[3],
567 + (data[4] << 8 | data[5]));
569 + /* Modify the packet */
570 + memcpy(buffer, &newip, 4);
571 + memcpy(buffer + 4, &port, 2);
572 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset[i],
576 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
577 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
578 + data[0], data[1], data[2], data[3],
579 + (data[4] << 8 | data[5]));
585 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
586 + struct ip_conntrack *ct,
587 + struct sk_buff **pskb,
588 + enum ip_conntrack_info ctinfo,
589 + struct ip_conntrack_expect *expect)
593 + u_int8_t buffer[6];
594 + struct ip_conntrack_tuple newtuple;
595 + struct iphdr *iph = (*pskb)->nh.iph;
596 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
597 + unsigned char *data;
598 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
599 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
602 + MUST_BE_LOCKED(&ip_h323_lock);
603 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
604 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
605 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
607 + if (!between(expect->seq + 6, ntohl(tcph->seq),
608 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
609 + /* Partial retransmisison. It's a cracker being funky. */
610 + if (net_ratelimit()) {
611 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
614 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
619 + /* Change address inside packet to match way we're mapping
620 + this connection. */
621 + if (info->dir == IP_CT_DIR_REPLY) {
622 + /* Must be where client thinks server is */
623 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
624 + /* Expect something from client->server */
625 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
626 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
628 + /* Must be where server thinks client is */
629 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
630 + /* Expect something from server->client */
631 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
632 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
635 + is_h225 = (master_info->is_h225 == H225_PORT);
638 + newtuple.dst.protonum = IPPROTO_TCP;
639 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
641 + newtuple.dst.protonum = IPPROTO_UDP;
642 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
645 + /* Try to get same port: if not, try to change it. */
646 + for (port = ntohs(info->port); port != 0; port++) {
648 + newtuple.dst.u.tcp.port = htons(port);
650 + newtuple.dst.u.udp.port = htons(port);
652 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
656 + DEBUGP("h323_data_fixup: no free port found!\n");
660 + port = htons(port);
662 + data = (char *) tcph + tcph->doff * 4 + info->offset;
664 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
665 + data[0], data[1], data[2], data[3],
666 + (data[4] << 8 | data[5]));
668 + /* Modify the packet */
669 + memcpy(buffer, &newip, 4);
670 + memcpy(buffer + 4, &port, 2);
671 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset,
675 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
676 + data[0], data[1], data[2], data[3],
677 + (data[4] << 8 | data[5]));
682 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
683 + struct ip_conntrack_expect *exp,
684 + struct ip_nat_info *info,
685 + enum ip_conntrack_info ctinfo,
686 + unsigned int hooknum,
687 + struct sk_buff **pskb)
690 + struct ip_ct_h225_expect *exp_info;
692 + /* Only mangle things once: original direction in POST_ROUTING
693 + and reply direction on PRE_ROUTING. */
694 + dir = CTINFO2DIR(ctinfo);
695 + DEBUGP("nat_h323: dir %s at hook %s\n",
696 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
697 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
698 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
699 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
700 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
701 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
702 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
703 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
704 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
705 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
706 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
711 + LOCK_BH(&ip_h323_lock);
712 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
713 + UNLOCK_BH(&ip_h323_lock);
716 + UNLOCK_BH(&ip_h323_lock);
720 + exp_info = &exp->help.exp_h225_info;
722 + LOCK_BH(&ip_h323_lock);
723 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
724 + UNLOCK_BH(&ip_h323_lock);
727 + UNLOCK_BH(&ip_h323_lock);
732 +static struct ip_nat_helper h225 =
734 + "H.225", /* name */
735 + IP_NAT_HELPER_F_ALWAYS, /* flags */
736 + THIS_MODULE, /* module */
737 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
738 + { 0, { 0 }, IPPROTO_TCP } },
739 + { { 0, { 0xFFFF } }, /* mask */
740 + { 0, { 0 }, 0xFFFF } },
741 + h225_nat_help, /* helper */
742 + h225_nat_expected /* expectfn */
745 +static int __init init(void)
749 + ret = ip_nat_helper_register(&h225);
752 + printk("ip_nat_h323: cannot initialize the module!\n");
757 +static void __exit fini(void)
759 + ip_nat_helper_unregister(&h225);
764 Index: linux-2.4.35.4/include/linux/netfilter_ipv4/ip_conntrack.h
765 ===================================================================
766 --- linux-2.4.35.4.orig/include/linux/netfilter_ipv4/ip_conntrack.h 2009-06-06 22:06:48.000000000 +0000
767 +++ linux-2.4.35.4/include/linux/netfilter_ipv4/ip_conntrack.h 2009-06-06 22:53:09.000000000 +0000
770 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
771 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
772 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
774 /* per expectation: application helper private data */
775 union ip_conntrack_expect_help {
777 struct ip_ct_amanda_expect exp_amanda_info;
778 struct ip_ct_ftp_expect exp_ftp_info;
779 struct ip_ct_irc_expect exp_irc_info;
780 + struct ip_ct_h225_expect exp_h225_info;
782 #ifdef CONFIG_IP_NF_NAT_NEEDED
785 /* insert conntrack helper private data (master) here */
786 struct ip_ct_ftp_master ct_ftp_info;
787 struct ip_ct_irc_master ct_irc_info;
788 + struct ip_ct_h225_master ct_h225_info;
791 #ifdef CONFIG_IP_NF_NAT_NEEDED
792 Index: linux-2.4.35.4/include/linux/netfilter_ipv4/ip_conntrack_h323.h
793 ===================================================================
794 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
795 +++ linux-2.4.35.4/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2009-06-06 22:34:50.000000000 +0000
797 +#ifndef _IP_CONNTRACK_H323_H
798 +#define _IP_CONNTRACK_H323_H
799 +/* H.323 connection tracking. */
802 +/* Protects H.323 related data */
803 +DECLARE_LOCK_EXTERN(ip_h323_lock);
806 +/* Default H.225 port */
807 +#define H225_PORT 1720
809 +/* This structure is per expected connection */
810 +struct ip_ct_h225_expect {
811 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
812 + enum ip_conntrack_dir dir; /* Direction of the original connection */
813 + unsigned int offset; /* offset of the address in the payload */
816 +/* This structure exists only once per master */
817 +struct ip_ct_h225_master {
818 + int is_h225; /* H.225 or H.245 connection */
819 +#ifdef CONFIG_IP_NF_NAT_NEEDED
820 + enum ip_conntrack_dir dir; /* Direction of the original connection */
821 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
822 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
826 +#endif /* _IP_CONNTRACK_H323_H */