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