netfilter: xtables: add struct xt_mtchk_param::net
[safe/jmp/linux-2.6] / net / ipv4 / netfilter / nf_nat_h323.c
1 /*
2  * H.323 extension for NAT alteration.
3  *
4  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
5  *
6  * This source code is licensed under General Public License version 2.
7  *
8  * Based on the 'brute force' H.323 NAT module by
9  * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10  */
11
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/tcp.h>
15 #include <net/tcp.h>
16
17 #include <net/netfilter/nf_nat.h>
18 #include <net/netfilter/nf_nat_helper.h>
19 #include <net/netfilter/nf_nat_rule.h>
20 #include <net/netfilter/nf_conntrack_helper.h>
21 #include <net/netfilter/nf_conntrack_expect.h>
22 #include <linux/netfilter/nf_conntrack_h323.h>
23
24 /****************************************************************************/
25 static int set_addr(struct sk_buff *skb,
26                     unsigned char **data, int dataoff,
27                     unsigned int addroff, __be32 ip, __be16 port)
28 {
29         enum ip_conntrack_info ctinfo;
30         struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
31         struct {
32                 __be32 ip;
33                 __be16 port;
34         } __attribute__ ((__packed__)) buf;
35         const struct tcphdr *th;
36         struct tcphdr _tcph;
37
38         buf.ip = ip;
39         buf.port = port;
40         addroff += dataoff;
41
42         if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
43                 if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
44                                               addroff, sizeof(buf),
45                                               (char *) &buf, sizeof(buf))) {
46                         if (net_ratelimit())
47                                 printk("nf_nat_h323: nf_nat_mangle_tcp_packet"
48                                        " error\n");
49                         return -1;
50                 }
51
52                 /* Relocate data pointer */
53                 th = skb_header_pointer(skb, ip_hdrlen(skb),
54                                         sizeof(_tcph), &_tcph);
55                 if (th == NULL)
56                         return -1;
57                 *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff;
58         } else {
59                 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
60                                               addroff, sizeof(buf),
61                                               (char *) &buf, sizeof(buf))) {
62                         if (net_ratelimit())
63                                 printk("nf_nat_h323: nf_nat_mangle_udp_packet"
64                                        " error\n");
65                         return -1;
66                 }
67                 /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
68                  * or pull everything in a linear buffer, so we can safely
69                  * use the skb pointers now */
70                 *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
71         }
72
73         return 0;
74 }
75
76 /****************************************************************************/
77 static int set_h225_addr(struct sk_buff *skb,
78                          unsigned char **data, int dataoff,
79                          TransportAddress *taddr,
80                          union nf_inet_addr *addr, __be16 port)
81 {
82         return set_addr(skb, data, dataoff, taddr->ipAddress.ip,
83                         addr->ip, port);
84 }
85
86 /****************************************************************************/
87 static int set_h245_addr(struct sk_buff *skb,
88                          unsigned char **data, int dataoff,
89                          H245_TransportAddress *taddr,
90                          union nf_inet_addr *addr, __be16 port)
91 {
92         return set_addr(skb, data, dataoff,
93                         taddr->unicastAddress.iPAddress.network,
94                         addr->ip, port);
95 }
96
97 /****************************************************************************/
98 static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
99                         enum ip_conntrack_info ctinfo,
100                         unsigned char **data,
101                         TransportAddress *taddr, int count)
102 {
103         const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
104         int dir = CTINFO2DIR(ctinfo);
105         int i;
106         __be16 port;
107         union nf_inet_addr addr;
108
109         for (i = 0; i < count; i++) {
110                 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
111                         if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
112                             port == info->sig_port[dir]) {
113                                 /* GW->GK */
114
115                                 /* Fix for Gnomemeeting */
116                                 if (i > 0 &&
117                                     get_h225_addr(ct, *data, &taddr[0],
118                                                   &addr, &port) &&
119                                     (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
120                                         i = 0;
121
122                                 pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
123                                          &addr.ip, port,
124                                          &ct->tuplehash[!dir].tuple.dst.u3.ip,
125                                          info->sig_port[!dir]);
126                                 return set_h225_addr(skb, data, 0, &taddr[i],
127                                                      &ct->tuplehash[!dir].
128                                                      tuple.dst.u3,
129                                                      info->sig_port[!dir]);
130                         } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
131                                    port == info->sig_port[dir]) {
132                                 /* GK->GW */
133                                 pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
134                                          &addr.ip, port,
135                                          &ct->tuplehash[!dir].tuple.src.u3.ip,
136                                          info->sig_port[!dir]);
137                                 return set_h225_addr(skb, data, 0, &taddr[i],
138                                                      &ct->tuplehash[!dir].
139                                                      tuple.src.u3,
140                                                      info->sig_port[!dir]);
141                         }
142                 }
143         }
144
145         return 0;
146 }
147
148 /****************************************************************************/
149 static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
150                         enum ip_conntrack_info ctinfo,
151                         unsigned char **data,
152                         TransportAddress *taddr, int count)
153 {
154         int dir = CTINFO2DIR(ctinfo);
155         int i;
156         __be16 port;
157         union nf_inet_addr addr;
158
159         for (i = 0; i < count; i++) {
160                 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
161                     addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
162                     port == ct->tuplehash[dir].tuple.src.u.udp.port) {
163                         pr_debug("nf_nat_ras: set rasAddress %pI4:%hu->%pI4:%hu\n",
164                                  &addr.ip, ntohs(port),
165                                  &ct->tuplehash[!dir].tuple.dst.u3.ip,
166                                  ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
167                         return set_h225_addr(skb, data, 0, &taddr[i],
168                                              &ct->tuplehash[!dir].tuple.dst.u3,
169                                              ct->tuplehash[!dir].tuple.
170                                                                 dst.u.udp.port);
171                 }
172         }
173
174         return 0;
175 }
176
177 /****************************************************************************/
178 static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
179                         enum ip_conntrack_info ctinfo,
180                         unsigned char **data, int dataoff,
181                         H245_TransportAddress *taddr,
182                         __be16 port, __be16 rtp_port,
183                         struct nf_conntrack_expect *rtp_exp,
184                         struct nf_conntrack_expect *rtcp_exp)
185 {
186         struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
187         int dir = CTINFO2DIR(ctinfo);
188         int i;
189         u_int16_t nated_port;
190
191         /* Set expectations for NAT */
192         rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
193         rtp_exp->expectfn = nf_nat_follow_master;
194         rtp_exp->dir = !dir;
195         rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
196         rtcp_exp->expectfn = nf_nat_follow_master;
197         rtcp_exp->dir = !dir;
198
199         /* Lookup existing expects */
200         for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
201                 if (info->rtp_port[i][dir] == rtp_port) {
202                         /* Expected */
203
204                         /* Use allocated ports first. This will refresh
205                          * the expects */
206                         rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];
207                         rtcp_exp->tuple.dst.u.udp.port =
208                             htons(ntohs(info->rtp_port[i][dir]) + 1);
209                         break;
210                 } else if (info->rtp_port[i][dir] == 0) {
211                         /* Not expected */
212                         break;
213                 }
214         }
215
216         /* Run out of expectations */
217         if (i >= H323_RTP_CHANNEL_MAX) {
218                 if (net_ratelimit())
219                         printk("nf_nat_h323: out of expectations\n");
220                 return 0;
221         }
222
223         /* Try to get a pair of ports. */
224         for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
225              nated_port != 0; nated_port += 2) {
226                 rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
227                 if (nf_ct_expect_related(rtp_exp) == 0) {
228                         rtcp_exp->tuple.dst.u.udp.port =
229                             htons(nated_port + 1);
230                         if (nf_ct_expect_related(rtcp_exp) == 0)
231                                 break;
232                         nf_ct_unexpect_related(rtp_exp);
233                 }
234         }
235
236         if (nated_port == 0) {  /* No port available */
237                 if (net_ratelimit())
238                         printk("nf_nat_h323: out of RTP ports\n");
239                 return 0;
240         }
241
242         /* Modify signal */
243         if (set_h245_addr(skb, data, dataoff, taddr,
244                           &ct->tuplehash[!dir].tuple.dst.u3,
245                           htons((port & htons(1)) ? nated_port + 1 :
246                                                     nated_port)) == 0) {
247                 /* Save ports */
248                 info->rtp_port[i][dir] = rtp_port;
249                 info->rtp_port[i][!dir] = htons(nated_port);
250         } else {
251                 nf_ct_unexpect_related(rtp_exp);
252                 nf_ct_unexpect_related(rtcp_exp);
253                 return -1;
254         }
255
256         /* Success */
257         pr_debug("nf_nat_h323: expect RTP %pI4:%hu->%pI4:%hu\n",
258                  &rtp_exp->tuple.src.u3.ip,
259                  ntohs(rtp_exp->tuple.src.u.udp.port),
260                  &rtp_exp->tuple.dst.u3.ip,
261                  ntohs(rtp_exp->tuple.dst.u.udp.port));
262         pr_debug("nf_nat_h323: expect RTCP %pI4:%hu->%pI4:%hu\n",
263                  &rtcp_exp->tuple.src.u3.ip,
264                  ntohs(rtcp_exp->tuple.src.u.udp.port),
265                  &rtcp_exp->tuple.dst.u3.ip,
266                  ntohs(rtcp_exp->tuple.dst.u.udp.port));
267
268         return 0;
269 }
270
271 /****************************************************************************/
272 static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
273                     enum ip_conntrack_info ctinfo,
274                     unsigned char **data, int dataoff,
275                     H245_TransportAddress *taddr, __be16 port,
276                     struct nf_conntrack_expect *exp)
277 {
278         int dir = CTINFO2DIR(ctinfo);
279         u_int16_t nated_port = ntohs(port);
280
281         /* Set expectations for NAT */
282         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
283         exp->expectfn = nf_nat_follow_master;
284         exp->dir = !dir;
285
286         /* Try to get same port: if not, try to change it. */
287         for (; nated_port != 0; nated_port++) {
288                 exp->tuple.dst.u.tcp.port = htons(nated_port);
289                 if (nf_ct_expect_related(exp) == 0)
290                         break;
291         }
292
293         if (nated_port == 0) {  /* No port available */
294                 if (net_ratelimit())
295                         printk("nf_nat_h323: out of TCP ports\n");
296                 return 0;
297         }
298
299         /* Modify signal */
300         if (set_h245_addr(skb, data, dataoff, taddr,
301                           &ct->tuplehash[!dir].tuple.dst.u3,
302                           htons(nated_port)) < 0) {
303                 nf_ct_unexpect_related(exp);
304                 return -1;
305         }
306
307         pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n",
308                  &exp->tuple.src.u3.ip,
309                  ntohs(exp->tuple.src.u.tcp.port),
310                  &exp->tuple.dst.u3.ip,
311                  ntohs(exp->tuple.dst.u.tcp.port));
312
313         return 0;
314 }
315
316 /****************************************************************************/
317 static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
318                     enum ip_conntrack_info ctinfo,
319                     unsigned char **data, int dataoff,
320                     TransportAddress *taddr, __be16 port,
321                     struct nf_conntrack_expect *exp)
322 {
323         struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
324         int dir = CTINFO2DIR(ctinfo);
325         u_int16_t nated_port = ntohs(port);
326
327         /* Set expectations for NAT */
328         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
329         exp->expectfn = nf_nat_follow_master;
330         exp->dir = !dir;
331
332         /* Check existing expects */
333         if (info->sig_port[dir] == port)
334                 nated_port = ntohs(info->sig_port[!dir]);
335
336         /* Try to get same port: if not, try to change it. */
337         for (; nated_port != 0; nated_port++) {
338                 exp->tuple.dst.u.tcp.port = htons(nated_port);
339                 if (nf_ct_expect_related(exp) == 0)
340                         break;
341         }
342
343         if (nated_port == 0) {  /* No port available */
344                 if (net_ratelimit())
345                         printk("nf_nat_q931: out of TCP ports\n");
346                 return 0;
347         }
348
349         /* Modify signal */
350         if (set_h225_addr(skb, data, dataoff, taddr,
351                           &ct->tuplehash[!dir].tuple.dst.u3,
352                           htons(nated_port)) == 0) {
353                 /* Save ports */
354                 info->sig_port[dir] = port;
355                 info->sig_port[!dir] = htons(nated_port);
356         } else {
357                 nf_ct_unexpect_related(exp);
358                 return -1;
359         }
360
361         pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n",
362                  &exp->tuple.src.u3.ip,
363                  ntohs(exp->tuple.src.u.tcp.port),
364                  &exp->tuple.dst.u3.ip,
365                  ntohs(exp->tuple.dst.u.tcp.port));
366
367         return 0;
368 }
369
370 /****************************************************************************
371  * This conntrack expect function replaces nf_conntrack_q931_expect()
372  * which was set by nf_conntrack_h323.c.
373  ****************************************************************************/
374 static void ip_nat_q931_expect(struct nf_conn *new,
375                                struct nf_conntrack_expect *this)
376 {
377         struct nf_nat_range range;
378
379         if (this->tuple.src.u3.ip != 0) {       /* Only accept calls from GK */
380                 nf_nat_follow_master(new, this);
381                 return;
382         }
383
384         /* This must be a fresh one. */
385         BUG_ON(new->status & IPS_NAT_DONE_MASK);
386
387         /* Change src to where master sends to */
388         range.flags = IP_NAT_RANGE_MAP_IPS;
389         range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
390         nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC);
391
392         /* For DST manip, map port here to where it's expected. */
393         range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
394         range.min = range.max = this->saved_proto;
395         range.min_ip = range.max_ip =
396             new->master->tuplehash[!this->dir].tuple.src.u3.ip;
397         nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST);
398 }
399
400 /****************************************************************************/
401 static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
402                     enum ip_conntrack_info ctinfo,
403                     unsigned char **data, TransportAddress *taddr, int idx,
404                     __be16 port, struct nf_conntrack_expect *exp)
405 {
406         struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
407         int dir = CTINFO2DIR(ctinfo);
408         u_int16_t nated_port = ntohs(port);
409         union nf_inet_addr addr;
410
411         /* Set expectations for NAT */
412         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
413         exp->expectfn = ip_nat_q931_expect;
414         exp->dir = !dir;
415
416         /* Check existing expects */
417         if (info->sig_port[dir] == port)
418                 nated_port = ntohs(info->sig_port[!dir]);
419
420         /* Try to get same port: if not, try to change it. */
421         for (; nated_port != 0; nated_port++) {
422                 exp->tuple.dst.u.tcp.port = htons(nated_port);
423                 if (nf_ct_expect_related(exp) == 0)
424                         break;
425         }
426
427         if (nated_port == 0) {  /* No port available */
428                 if (net_ratelimit())
429                         printk("nf_nat_ras: out of TCP ports\n");
430                 return 0;
431         }
432
433         /* Modify signal */
434         if (set_h225_addr(skb, data, 0, &taddr[idx],
435                           &ct->tuplehash[!dir].tuple.dst.u3,
436                           htons(nated_port)) == 0) {
437                 /* Save ports */
438                 info->sig_port[dir] = port;
439                 info->sig_port[!dir] = htons(nated_port);
440
441                 /* Fix for Gnomemeeting */
442                 if (idx > 0 &&
443                     get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
444                     (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
445                         set_h225_addr(skb, data, 0, &taddr[0],
446                                       &ct->tuplehash[!dir].tuple.dst.u3,
447                                       info->sig_port[!dir]);
448                 }
449         } else {
450                 nf_ct_unexpect_related(exp);
451                 return -1;
452         }
453
454         /* Success */
455         pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n",
456                  &exp->tuple.src.u3.ip,
457                  ntohs(exp->tuple.src.u.tcp.port),
458                  &exp->tuple.dst.u3.ip,
459                  ntohs(exp->tuple.dst.u.tcp.port));
460
461         return 0;
462 }
463
464 /****************************************************************************/
465 static void ip_nat_callforwarding_expect(struct nf_conn *new,
466                                          struct nf_conntrack_expect *this)
467 {
468         struct nf_nat_range range;
469
470         /* This must be a fresh one. */
471         BUG_ON(new->status & IPS_NAT_DONE_MASK);
472
473         /* Change src to where master sends to */
474         range.flags = IP_NAT_RANGE_MAP_IPS;
475         range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
476         nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC);
477
478         /* For DST manip, map port here to where it's expected. */
479         range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
480         range.min = range.max = this->saved_proto;
481         range.min_ip = range.max_ip = this->saved_ip;
482         nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST);
483 }
484
485 /****************************************************************************/
486 static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
487                               enum ip_conntrack_info ctinfo,
488                               unsigned char **data, int dataoff,
489                               TransportAddress *taddr, __be16 port,
490                               struct nf_conntrack_expect *exp)
491 {
492         int dir = CTINFO2DIR(ctinfo);
493         u_int16_t nated_port;
494
495         /* Set expectations for NAT */
496         exp->saved_ip = exp->tuple.dst.u3.ip;
497         exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
498         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
499         exp->expectfn = ip_nat_callforwarding_expect;
500         exp->dir = !dir;
501
502         /* Try to get same port: if not, try to change it. */
503         for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
504                 exp->tuple.dst.u.tcp.port = htons(nated_port);
505                 if (nf_ct_expect_related(exp) == 0)
506                         break;
507         }
508
509         if (nated_port == 0) {  /* No port available */
510                 if (net_ratelimit())
511                         printk("nf_nat_q931: out of TCP ports\n");
512                 return 0;
513         }
514
515         /* Modify signal */
516         if (!set_h225_addr(skb, data, dataoff, taddr,
517                            &ct->tuplehash[!dir].tuple.dst.u3,
518                            htons(nated_port)) == 0) {
519                 nf_ct_unexpect_related(exp);
520                 return -1;
521         }
522
523         /* Success */
524         pr_debug("nf_nat_q931: expect Call Forwarding %pI4:%hu->%pI4:%hu\n",
525                  &exp->tuple.src.u3.ip,
526                  ntohs(exp->tuple.src.u.tcp.port),
527                  &exp->tuple.dst.u3.ip,
528                  ntohs(exp->tuple.dst.u.tcp.port));
529
530         return 0;
531 }
532
533 /****************************************************************************/
534 static int __init init(void)
535 {
536         BUG_ON(set_h245_addr_hook != NULL);
537         BUG_ON(set_h225_addr_hook != NULL);
538         BUG_ON(set_sig_addr_hook != NULL);
539         BUG_ON(set_ras_addr_hook != NULL);
540         BUG_ON(nat_rtp_rtcp_hook != NULL);
541         BUG_ON(nat_t120_hook != NULL);
542         BUG_ON(nat_h245_hook != NULL);
543         BUG_ON(nat_callforwarding_hook != NULL);
544         BUG_ON(nat_q931_hook != NULL);
545
546         rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
547         rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
548         rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
549         rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
550         rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
551         rcu_assign_pointer(nat_t120_hook, nat_t120);
552         rcu_assign_pointer(nat_h245_hook, nat_h245);
553         rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
554         rcu_assign_pointer(nat_q931_hook, nat_q931);
555         return 0;
556 }
557
558 /****************************************************************************/
559 static void __exit fini(void)
560 {
561         rcu_assign_pointer(set_h245_addr_hook, NULL);
562         rcu_assign_pointer(set_h225_addr_hook, NULL);
563         rcu_assign_pointer(set_sig_addr_hook, NULL);
564         rcu_assign_pointer(set_ras_addr_hook, NULL);
565         rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
566         rcu_assign_pointer(nat_t120_hook, NULL);
567         rcu_assign_pointer(nat_h245_hook, NULL);
568         rcu_assign_pointer(nat_callforwarding_hook, NULL);
569         rcu_assign_pointer(nat_q931_hook, NULL);
570         synchronize_rcu();
571 }
572
573 /****************************************************************************/
574 module_init(init);
575 module_exit(fini);
576
577 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
578 MODULE_DESCRIPTION("H.323 NAT helper");
579 MODULE_LICENSE("GPL");
580 MODULE_ALIAS("ip_nat_h323");