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