finally move buildroot-ng to trunk
[openwrt/svn-archive/archive.git] / target / linux / generic-2.4 / patches / 613-netfilter_nat_h323.patch
1 diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.new/net/ipv4/netfilter/Config.in
2 --- linux-2.4.32/net/ipv4/netfilter/Config.in 2006-03-01 00:49:36.652505800 +0100
3 +++ linux-2.4.32.new/net/ipv4/netfilter/Config.in 2006-03-01 00:50:18.692114808 +0100
4 @@ -15,6 +15,7 @@
5 dep_tristate ' Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
6 dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
7 dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
8 + dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
9 fi
10
11 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
12 @@ -111,6 +112,13 @@
13 define_tristate CONFIG_IP_NF_NAT_AMANDA $CONFIG_IP_NF_NAT
14 fi
15 fi
16 + if [ "$CONFIG_IP_NF_H323" = "m" ]; then
17 + define_tristate CONFIG_IP_NF_NAT_H323 m
18 + else
19 + if [ "$CONFIG_IP_NF_H323" = "y" ]; then
20 + define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
21 + fi
22 + fi
23 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
24 dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
25 fi
26 diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.new/net/ipv4/netfilter/Makefile
27 --- linux-2.4.32/net/ipv4/netfilter/Makefile 2006-03-01 00:49:36.654505496 +0100
28 +++ linux-2.4.32.new/net/ipv4/netfilter/Makefile 2006-03-01 00:50:18.693114656 +0100
29 @@ -53,6 +53,10 @@
30 ifdef CONFIG_IP_NF_NAT_PPTP
31 export-objs += ip_conntrack_pptp.o
32 endif
33 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
34 +ifdef CONFIG_IP_NF_NAT_H323
35 + export-objs += ip_conntrack_h323.o
36 +endif
37
38
39 # NAT helpers
40 @@ -62,6 +66,7 @@
41 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
42 obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
43 obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
44 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
45
46 # generic IP tables
47 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
48 diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_h323.c
49 --- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
50 +++ linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_h323.c 2006-03-01 00:50:18.694114504 +0100
51 @@ -0,0 +1,302 @@
52 +/*
53 + * H.323 'brute force' extension for H.323 connection tracking.
54 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
55 + *
56 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
57 + * (http://www.coritel.it/projects/sofia/nat/)
58 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
59 + * the unregistered helpers to the conntrack entries.
60 + */
61 +
62 +
63 +#include <linux/module.h>
64 +#include <linux/netfilter.h>
65 +#include <linux/ip.h>
66 +#include <net/checksum.h>
67 +#include <net/tcp.h>
68 +
69 +#include <linux/netfilter_ipv4/lockhelp.h>
70 +#include <linux/netfilter_ipv4/ip_conntrack.h>
71 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
72 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
73 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
74 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
75 +
76 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
77 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
78 +MODULE_LICENSE("GPL");
79 +
80 +DECLARE_LOCK(ip_h323_lock);
81 +struct module *ip_conntrack_h323 = THIS_MODULE;
82 +
83 +#define DEBUGP(format, args...)
84 +
85 +static int h245_help(const struct iphdr *iph, size_t len,
86 + struct ip_conntrack *ct,
87 + enum ip_conntrack_info ctinfo)
88 +{
89 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
90 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
91 + unsigned char *data_limit;
92 + u_int32_t tcplen = len - iph->ihl * 4;
93 + u_int32_t datalen = tcplen - tcph->doff * 4;
94 + int dir = CTINFO2DIR(ctinfo);
95 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
96 + struct ip_conntrack_expect expect, *exp = &expect;
97 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
98 + u_int16_t data_port;
99 + u_int32_t data_ip;
100 + unsigned int i;
101 +
102 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
103 + NIPQUAD(iph->saddr), ntohs(tcph->source),
104 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
105 +
106 + /* Can't track connections formed before we registered */
107 + if (!info)
108 + return NF_ACCEPT;
109 +
110 + /* Until there's been traffic both ways, don't look in packets. */
111 + if (ctinfo != IP_CT_ESTABLISHED
112 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
113 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
114 + return NF_ACCEPT;
115 + }
116 +
117 + /* Not whole TCP header or too short packet? */
118 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
119 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
120 + return NF_ACCEPT;
121 + }
122 +
123 + /* Checksum invalid? Ignore. */
124 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
125 + csum_partial((char *)tcph, tcplen, 0))) {
126 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
127 + tcph, tcplen, NIPQUAD(iph->saddr),
128 + NIPQUAD(iph->daddr));
129 + return NF_ACCEPT;
130 + }
131 +
132 + data_limit = (unsigned char *) data + datalen;
133 + /* bytes: 0123 45
134 + ipadrr port */
135 + for (i = 0; data < (data_limit - 5); data++, i++) {
136 + memcpy(&data_ip, data, sizeof(u_int32_t));
137 + if (data_ip == iph->saddr) {
138 + memcpy(&data_port, data + 4, sizeof(u_int16_t));
139 + memset(&expect, 0, sizeof(expect));
140 + /* update the H.225 info */
141 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
142 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
143 + NIPQUAD(iph->saddr), ntohs(data_port));
144 + LOCK_BH(&ip_h323_lock);
145 + info->is_h225 = H225_PORT + 1;
146 + exp_info->port = data_port;
147 + exp_info->dir = dir;
148 + exp_info->offset = i;
149 +
150 + exp->seq = ntohl(tcph->seq) + i;
151 +
152 + exp->tuple = ((struct ip_conntrack_tuple)
153 + { { ct->tuplehash[!dir].tuple.src.ip,
154 + { 0 } },
155 + { data_ip,
156 + { data_port },
157 + IPPROTO_UDP }});
158 + exp->mask = ((struct ip_conntrack_tuple)
159 + { { 0xFFFFFFFF, { 0 } },
160 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
161 +
162 + exp->expectfn = NULL;
163 +
164 + /* Ignore failure; should only happen with NAT */
165 + ip_conntrack_expect_related(ct, exp);
166 +
167 + UNLOCK_BH(&ip_h323_lock);
168 + }
169 + }
170 +
171 + return NF_ACCEPT;
172 +
173 +}
174 +
175 +/* H.245 helper is not registered! */
176 +static struct ip_conntrack_helper h245 =
177 + { { NULL, NULL },
178 + "H.245", /* name */
179 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
180 + NULL, /* module */
181 + 8, /* max_ expected */
182 + 240, /* timeout */
183 + { { 0, { 0 } }, /* tuple */
184 + { 0, { 0 }, IPPROTO_TCP } },
185 + { { 0, { 0xFFFF } }, /* mask */
186 + { 0, { 0 }, 0xFFFF } },
187 + h245_help /* helper */
188 + };
189 +
190 +static int h225_expect(struct ip_conntrack *ct)
191 +{
192 + WRITE_LOCK(&ip_conntrack_lock);
193 + ct->helper = &h245;
194 + DEBUGP("h225_expect: helper for %p added\n", ct);
195 + WRITE_UNLOCK(&ip_conntrack_lock);
196 +
197 + return NF_ACCEPT; /* unused */
198 +}
199 +
200 +static int h225_help(const struct iphdr *iph, size_t len,
201 + struct ip_conntrack *ct,
202 + enum ip_conntrack_info ctinfo)
203 +{
204 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
205 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
206 + unsigned char *data_limit;
207 + u_int32_t tcplen = len - iph->ihl * 4;
208 + u_int32_t datalen = tcplen - tcph->doff * 4;
209 + int dir = CTINFO2DIR(ctinfo);
210 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
211 + struct ip_conntrack_expect expect, *exp = &expect;
212 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
213 + u_int16_t data_port;
214 + u_int32_t data_ip;
215 + unsigned int i;
216 +
217 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
218 + NIPQUAD(iph->saddr), ntohs(tcph->source),
219 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
220 +
221 + /* Can't track connections formed before we registered */
222 + if (!info)
223 + return NF_ACCEPT;
224 +
225 + /* Until there's been traffic both ways, don't look in packets. */
226 + if (ctinfo != IP_CT_ESTABLISHED
227 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
228 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
229 + return NF_ACCEPT;
230 + }
231 +
232 + /* Not whole TCP header or too short packet? */
233 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
234 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
235 + return NF_ACCEPT;
236 + }
237 +
238 + /* Checksum invalid? Ignore. */
239 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
240 + csum_partial((char *)tcph, tcplen, 0))) {
241 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
242 + tcph, tcplen, NIPQUAD(iph->saddr),
243 + NIPQUAD(iph->daddr));
244 + return NF_ACCEPT;
245 + }
246 +
247 + data_limit = (unsigned char *) data + datalen;
248 + /* bytes: 0123 45
249 + ipadrr port */
250 + for (i = 0; data < (data_limit - 5); data++, i++) {
251 + memcpy(&data_ip, data, sizeof(u_int32_t));
252 + if (data_ip == iph->saddr) {
253 + memcpy(&data_port, data + 4, sizeof(u_int16_t));
254 + if (data_port == tcph->source) {
255 + /* Signal address */
256 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
257 + NIPQUAD(iph->saddr));
258 + /* Update the H.225 info so that NAT can mangle the address/port
259 + even when we have no expected connection! */
260 +#ifdef CONFIG_IP_NF_NAT_NEEDED
261 + LOCK_BH(&ip_h323_lock);
262 + info->dir = dir;
263 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
264 + info->offset[IP_CT_DIR_ORIGINAL] = i;
265 + UNLOCK_BH(&ip_h323_lock);
266 +#endif
267 + } else {
268 + memset(&expect, 0, sizeof(expect));
269 +
270 + /* update the H.225 info */
271 + LOCK_BH(&ip_h323_lock);
272 + info->is_h225 = H225_PORT;
273 + exp_info->port = data_port;
274 + exp_info->dir = dir;
275 + exp_info->offset = i;
276 +
277 + exp->seq = ntohl(tcph->seq) + i;
278 +
279 + exp->tuple = ((struct ip_conntrack_tuple)
280 + { { ct->tuplehash[!dir].tuple.src.ip,
281 + { 0 } },
282 + { data_ip,
283 + { data_port },
284 + IPPROTO_TCP }});
285 + exp->mask = ((struct ip_conntrack_tuple)
286 + { { 0xFFFFFFFF, { 0 } },
287 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
288 +
289 + exp->expectfn = h225_expect;
290 +
291 + /* Ignore failure */
292 + ip_conntrack_expect_related(ct, exp);
293 +
294 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
295 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
296 + NIPQUAD(iph->saddr), ntohs(data_port));
297 +
298 + UNLOCK_BH(&ip_h323_lock);
299 + }
300 +#ifdef CONFIG_IP_NF_NAT_NEEDED
301 + } else if (data_ip == iph->daddr) {
302 + memcpy(&data_port, data + 4, sizeof(u_int16_t));
303 + if (data_port == tcph->dest) {
304 + /* Signal address */
305 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
306 + NIPQUAD(iph->daddr));
307 + /* Update the H.225 info so that NAT can mangle the address/port
308 + even when we have no expected connection! */
309 + LOCK_BH(&ip_h323_lock);
310 + info->dir = dir;
311 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
312 + info->offset[IP_CT_DIR_REPLY] = i;
313 + UNLOCK_BH(&ip_h323_lock);
314 + }
315 +#endif
316 + }
317 + }
318 +
319 + return NF_ACCEPT;
320 +
321 +}
322 +
323 +static struct ip_conntrack_helper h225 =
324 + { { NULL, NULL },
325 + "H.225", /* name */
326 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
327 + THIS_MODULE, /* module */
328 + 2, /* max_expected */
329 + 240, /* timeout */
330 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
331 + { 0, { 0 }, IPPROTO_TCP } },
332 + { { 0, { 0xFFFF } }, /* mask */
333 + { 0, { 0 }, 0xFFFF } },
334 + h225_help /* helper */
335 + };
336 +
337 +static int __init init(void)
338 +{
339 + return ip_conntrack_helper_register(&h225);
340 +}
341 +
342 +static void __exit fini(void)
343 +{
344 + /* Unregister H.225 helper */
345 + ip_conntrack_helper_unregister(&h225);
346 +}
347 +
348 +#ifdef CONFIG_IP_NF_NAT_NEEDED
349 +EXPORT_SYMBOL(ip_h323_lock);
350 +#endif
351 +
352 +module_init(init);
353 +module_exit(fini);
354 diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c linux-2.4.32.new/net/ipv4/netfilter/ip_nat_h323.c
355 --- linux-2.4.32/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
356 +++ linux-2.4.32.new/net/ipv4/netfilter/ip_nat_h323.c 2006-03-01 00:50:18.698113896 +0100
357 @@ -0,0 +1,403 @@
358 +/*
359 + * H.323 'brute force' extension for NAT alteration.
360 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
361 + *
362 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
363 + * (http://www.coritel.it/projects/sofia/nat.html)
364 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
365 + * the unregistered helpers to the conntrack entries.
366 + */
367 +
368 +
369 +#include <linux/module.h>
370 +#include <linux/netfilter.h>
371 +#include <linux/ip.h>
372 +#include <net/checksum.h>
373 +#include <net/tcp.h>
374 +
375 +#include <linux/netfilter_ipv4/lockhelp.h>
376 +#include <linux/netfilter_ipv4/ip_nat.h>
377 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
378 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
379 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
380 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
381 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
382 +
383 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
384 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
385 +MODULE_LICENSE("GPL");
386 +
387 +DECLARE_LOCK_EXTERN(ip_h323_lock);
388 +struct module *ip_nat_h323 = THIS_MODULE;
389 +
390 +#define DEBUGP(format, args...)
391 +
392 +
393 +static unsigned int
394 +h225_nat_expected(struct sk_buff **pskb,
395 + unsigned int hooknum,
396 + struct ip_conntrack *ct,
397 + struct ip_nat_info *info);
398 +
399 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
400 + struct ip_conntrack_expect *exp,
401 + struct ip_nat_info *info,
402 + enum ip_conntrack_info ctinfo,
403 + unsigned int hooknum,
404 + struct sk_buff **pskb);
405 +
406 +static struct ip_nat_helper h245 =
407 + { { NULL, NULL },
408 + "H.245", /* name */
409 + 0, /* flags */
410 + NULL, /* module */
411 + { { 0, { 0 } }, /* tuple */
412 + { 0, { 0 }, IPPROTO_TCP } },
413 + { { 0, { 0xFFFF } }, /* mask */
414 + { 0, { 0 }, 0xFFFF } },
415 + h225_nat_help, /* helper */
416 + h225_nat_expected /* expectfn */
417 + };
418 +
419 +static unsigned int
420 +h225_nat_expected(struct sk_buff **pskb,
421 + unsigned int hooknum,
422 + struct ip_conntrack *ct,
423 + struct ip_nat_info *info)
424 +{
425 + struct ip_nat_multi_range mr;
426 + u_int32_t newdstip, newsrcip, newip;
427 + u_int16_t port;
428 + struct ip_ct_h225_expect *exp_info;
429 + struct ip_ct_h225_master *master_info;
430 + struct ip_conntrack *master = master_ct(ct);
431 + unsigned int is_h225, ret;
432 +
433 + IP_NF_ASSERT(info);
434 + IP_NF_ASSERT(master);
435 +
436 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
437 +
438 + DEBUGP("h225_nat_expected: We have a connection!\n");
439 + master_info = &ct->master->expectant->help.ct_h225_info;
440 + exp_info = &ct->master->help.exp_h225_info;
441 +
442 + LOCK_BH(&ip_h323_lock);
443 +
444 + DEBUGP("master: ");
445 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
446 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
447 + DEBUGP("conntrack: ");
448 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
449 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
450 + /* Make connection go to the client. */
451 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
452 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
453 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
454 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
455 + } else {
456 + /* Make the connection go to the server */
457 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
458 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
459 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
460 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
461 + }
462 + port = exp_info->port;
463 + is_h225 = master_info->is_h225 == H225_PORT;
464 + UNLOCK_BH(&ip_h323_lock);
465 +
466 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
467 + newip = newsrcip;
468 + else
469 + newip = newdstip;
470 +
471 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
472 +
473 + mr.rangesize = 1;
474 + /* We don't want to manip the per-protocol, just the IPs... */
475 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
476 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
477 +
478 + /* ... unless we're doing a MANIP_DST, in which case, make
479 + sure we map to the correct port */
480 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
481 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
482 + mr.range[0].min = mr.range[0].max
483 + = ((union ip_conntrack_manip_proto)
484 + { port });
485 + }
486 +
487 + ret = ip_nat_setup_info(ct, &mr, hooknum);
488 +
489 + if (is_h225) {
490 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
491 + /* NAT expectfn called with ip_nat_lock write-locked */
492 + info->helper = &h245;
493 + }
494 + return ret;
495 +}
496 +
497 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
498 + struct sk_buff **pskb,
499 + enum ip_conntrack_info ctinfo)
500 +{
501 + struct iphdr *iph = (*pskb)->nh.iph;
502 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
503 + unsigned char *data;
504 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
505 + u_int32_t datalen = tcplen - tcph->doff*4;
506 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
507 + u_int32_t newip;
508 + u_int16_t port;
509 + u_int8_t buffer[6];
510 + int i;
511 +
512 + MUST_BE_LOCKED(&ip_h323_lock);
513 +
514 + DEBUGP("h323_signal_address_fixup: %s %s\n",
515 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
516 + ? "yes" : "no",
517 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
518 + ? "yes" : "no");
519 + if (!(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)))
521 + return 1;
522 +
523 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
524 + info->offset[IP_CT_DIR_ORIGINAL],
525 + info->offset[IP_CT_DIR_REPLY],
526 + tcplen);
527 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
528 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
529 +
530 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
531 + DEBUGP("h323_signal_address_fixup: %s %s\n",
532 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
533 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
534 + if (!between(info->seq[i], ntohl(tcph->seq),
535 + ntohl(tcph->seq) + datalen))
536 + continue;
537 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
538 + ntohl(tcph->seq) + datalen)) {
539 + /* Partial retransmisison. It's a cracker being funky. */
540 + if (net_ratelimit()) {
541 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
542 + info->seq[i],
543 + ntohl(tcph->seq),
544 + ntohl(tcph->seq) + datalen);
545 + }
546 + return 0;
547 + }
548 +
549 + /* Change address inside packet to match way we're mapping
550 + this connection. */
551 + if (i == IP_CT_DIR_ORIGINAL) {
552 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
553 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
554 + } else {
555 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
556 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
557 + }
558 +
559 + data = (char *) tcph + tcph->doff * 4 + info->offset[i];
560 +
561 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
562 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
563 + data[0], data[1], data[2], data[3],
564 + (data[4] << 8 | data[5]));
565 +
566 + /* Modify the packet */
567 + memcpy(buffer, &newip, 4);
568 + memcpy(buffer + 4, &port, 2);
569 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset[i],
570 + 6, buffer, 6))
571 + return 0;
572 +
573 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
574 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
575 + data[0], data[1], data[2], data[3],
576 + (data[4] << 8 | data[5]));
577 + }
578 +
579 + return 1;
580 +}
581 +
582 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
583 + struct ip_conntrack *ct,
584 + struct sk_buff **pskb,
585 + enum ip_conntrack_info ctinfo,
586 + struct ip_conntrack_expect *expect)
587 +{
588 + u_int32_t newip;
589 + u_int16_t port;
590 + u_int8_t buffer[6];
591 + struct ip_conntrack_tuple newtuple;
592 + struct iphdr *iph = (*pskb)->nh.iph;
593 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
594 + unsigned char *data;
595 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
596 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
597 + int is_h225;
598 +
599 + MUST_BE_LOCKED(&ip_h323_lock);
600 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
601 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
602 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
603 +
604 + if (!between(expect->seq + 6, ntohl(tcph->seq),
605 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
606 + /* Partial retransmisison. It's a cracker being funky. */
607 + if (net_ratelimit()) {
608 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
609 + expect->seq,
610 + ntohl(tcph->seq),
611 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
612 + }
613 + return 0;
614 + }
615 +
616 + /* Change address inside packet to match way we're mapping
617 + this connection. */
618 + if (info->dir == IP_CT_DIR_REPLY) {
619 + /* Must be where client thinks server is */
620 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
621 + /* Expect something from client->server */
622 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
623 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
624 + } else {
625 + /* Must be where server thinks client is */
626 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
627 + /* Expect something from server->client */
628 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
629 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
630 + }
631 +
632 + is_h225 = (master_info->is_h225 == H225_PORT);
633 +
634 + if (is_h225) {
635 + newtuple.dst.protonum = IPPROTO_TCP;
636 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
637 + } else {
638 + newtuple.dst.protonum = IPPROTO_UDP;
639 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
640 + }
641 +
642 + /* Try to get same port: if not, try to change it. */
643 + for (port = ntohs(info->port); port != 0; port++) {
644 + if (is_h225)
645 + newtuple.dst.u.tcp.port = htons(port);
646 + else
647 + newtuple.dst.u.udp.port = htons(port);
648 +
649 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
650 + break;
651 + }
652 + if (port == 0) {
653 + DEBUGP("h323_data_fixup: no free port found!\n");
654 + return 0;
655 + }
656 +
657 + port = htons(port);
658 +
659 + data = (char *) tcph + tcph->doff * 4 + info->offset;
660 +
661 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
662 + data[0], data[1], data[2], data[3],
663 + (data[4] << 8 | data[5]));
664 +
665 + /* Modify the packet */
666 + memcpy(buffer, &newip, 4);
667 + memcpy(buffer + 4, &port, 2);
668 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, info->offset,
669 + 6, buffer, 6))
670 + return 0;
671 +
672 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
673 + data[0], data[1], data[2], data[3],
674 + (data[4] << 8 | data[5]));
675 +
676 + return 1;
677 +}
678 +
679 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
680 + struct ip_conntrack_expect *exp,
681 + struct ip_nat_info *info,
682 + enum ip_conntrack_info ctinfo,
683 + unsigned int hooknum,
684 + struct sk_buff **pskb)
685 +{
686 + int dir;
687 + struct ip_ct_h225_expect *exp_info;
688 +
689 + /* Only mangle things once: original direction in POST_ROUTING
690 + and reply direction on PRE_ROUTING. */
691 + dir = CTINFO2DIR(ctinfo);
692 + DEBUGP("nat_h323: dir %s at hook %s\n",
693 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
694 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
695 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
696 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
697 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
698 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
699 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
700 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
701 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
702 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
703 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
704 + return NF_ACCEPT;
705 + }
706 +
707 + if (!exp) {
708 + LOCK_BH(&ip_h323_lock);
709 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
710 + UNLOCK_BH(&ip_h323_lock);
711 + return NF_DROP;
712 + }
713 + UNLOCK_BH(&ip_h323_lock);
714 + return NF_ACCEPT;
715 + }
716 +
717 + exp_info = &exp->help.exp_h225_info;
718 +
719 + LOCK_BH(&ip_h323_lock);
720 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
721 + UNLOCK_BH(&ip_h323_lock);
722 + return NF_DROP;
723 + }
724 + UNLOCK_BH(&ip_h323_lock);
725 +
726 + return NF_ACCEPT;
727 +}
728 +
729 +static struct ip_nat_helper h225 =
730 + { { NULL, NULL },
731 + "H.225", /* name */
732 + IP_NAT_HELPER_F_ALWAYS, /* flags */
733 + THIS_MODULE, /* module */
734 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
735 + { 0, { 0 }, IPPROTO_TCP } },
736 + { { 0, { 0xFFFF } }, /* mask */
737 + { 0, { 0 }, 0xFFFF } },
738 + h225_nat_help, /* helper */
739 + h225_nat_expected /* expectfn */
740 + };
741 +
742 +static int __init init(void)
743 +{
744 + int ret;
745 +
746 + ret = ip_nat_helper_register(&h225);
747 +
748 + if (ret != 0)
749 + printk("ip_nat_h323: cannot initialize the module!\n");
750 +
751 + return ret;
752 +}
753 +
754 +static void __exit fini(void)
755 +{
756 + ip_nat_helper_unregister(&h225);
757 +}
758 +
759 +module_init(init);
760 +module_exit(fini);
761 diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h
762 --- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 00:49:36.474532856 +0100
763 +++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 00:50:18.699113744 +0100
764 @@ -71,6 +71,7 @@
765 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
766 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
767 #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
768 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
769
770 /* per expectation: application helper private data */
771 union ip_conntrack_expect_help {
772 @@ -79,6 +80,7 @@
773 struct ip_ct_ftp_expect exp_ftp_info;
774 struct ip_ct_irc_expect exp_irc_info;
775 struct ip_ct_pptp_expect exp_pptp_info;
776 + struct ip_ct_h225_expect exp_h225_info;
777
778 #ifdef CONFIG_IP_NF_NAT_NEEDED
779 union {
780 @@ -93,6 +95,7 @@
781 struct ip_ct_ftp_master ct_ftp_info;
782 struct ip_ct_irc_master ct_irc_info;
783 struct ip_ct_pptp_master ct_pptp_info;
784 + struct ip_ct_h225_master ct_h225_info;
785 };
786
787 #ifdef CONFIG_IP_NF_NAT_NEEDED
788 diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_h323.h
789 --- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
790 +++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2006-03-01 00:50:18.700113592 +0100
791 @@ -0,0 +1,30 @@
792 +#ifndef _IP_CONNTRACK_H323_H
793 +#define _IP_CONNTRACK_H323_H
794 +/* H.323 connection tracking. */
795 +
796 +#ifdef __KERNEL__
797 +/* Protects H.323 related data */
798 +DECLARE_LOCK_EXTERN(ip_h323_lock);
799 +#endif
800 +
801 +/* Default H.225 port */
802 +#define H225_PORT 1720
803 +
804 +/* This structure is per expected connection */
805 +struct ip_ct_h225_expect {
806 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
807 + enum ip_conntrack_dir dir; /* Direction of the original connection */
808 + unsigned int offset; /* offset of the address in the payload */
809 +};
810 +
811 +/* This structure exists only once per master */
812 +struct ip_ct_h225_master {
813 + int is_h225; /* H.225 or H.245 connection */
814 +#ifdef CONFIG_IP_NF_NAT_NEEDED
815 + enum ip_conntrack_dir dir; /* Direction of the original connection */
816 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
817 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
818 +#endif
819 +};
820 +
821 +#endif /* _IP_CONNTRACK_H323_H */