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