fix libgd dependency problem
[openwrt.git] / target / linux / generic-2.4 / patches / 614-netfilter_nat_h323.patch
1 diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32/net/ipv4/netfilter/Config.in
2 --- linux-2.4.32/net/ipv4/netfilter/Config.in   2005-12-12 11:13:17.000000000 +0100
3 +++ linux-2.4.32/net/ipv4/netfilter/Config.in   2005-12-12 11:18:47.000000000 +0100
4 @@ -16,6 +16,7 @@
5    dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
6    dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
7    dep_tristate '  SIP protocol support' CONFIG_IP_NF_SIP $CONFIG_IP_NF_CONNTRACK
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 @@ -112,6 +113,13 @@
13           define_tristate CONFIG_IP_NF_NAT_SIP $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_IP_NF_AMANDA" = "m" ]; then
24          define_tristate CONFIG_IP_NF_NAT_AMANDA m
25        else
26 diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32/net/ipv4/netfilter/Makefile
27 --- linux-2.4.32/net/ipv4/netfilter/Makefile    2005-12-12 11:13:17.000000000 +0100
28 +++ linux-2.4.32/net/ipv4/netfilter/Makefile    2005-12-12 11:17:37.000000000 +0100
29 @@ -57,6 +57,10 @@
30  ifdef CONFIG_IP_NF_NAT_SIP
31          export-objs += ip_conntrack_sip.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 @@ -67,6 +71,7 @@
41  obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
42  obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
43  obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.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/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/net/ipv4/netfilter/ip_conntrack_h323.c 2005-12-12 11:14:54.000000000 +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/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/net/ipv4/netfilter/ip_nat_h323.c       2005-12-12 11:14:54.000000000 +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/include/linux/netfilter_ipv4/ip_conntrack.h
762 --- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h    2005-12-12 11:13:17.000000000 +0100
763 +++ linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h    2005-12-12 11:16:13.000000000 +0100
764 @@ -72,6 +72,7 @@
765  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
766  #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
767  #include <linux/netfilter_ipv4/ip_conntrack_sip.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 @@ -81,6 +82,7 @@
773         struct ip_ct_irc_expect exp_irc_info;
774         struct ip_ct_pptp_expect exp_pptp_info;
775         struct ip_ct_sip_expect exp_sip_info;
776 +       struct ip_ct_h225_expect exp_h225_info;
777  
778  #ifdef CONFIG_IP_NF_NAT_NEEDED
779         union {
780 @@ -96,6 +98,7 @@
781         struct ip_ct_irc_master ct_irc_info;
782         struct ip_ct_pptp_master ct_pptp_info;
783         struct ip_ct_sip_master ct_sip_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/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/include/linux/netfilter_ipv4/ip_conntrack_h323.h       2005-12-12 11:14:54.000000000 +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 */