Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / net / ipv4 / netfilter / nf_nat_h323.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * H.323 extension for NAT alteration.
4  *
5  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
6  * Copyright (c) 2006-2012 Patrick McHardy <kaber@trash.net>
7  *
8  * Based on the 'brute force' H.323 NAT module by
9  * Jozsef Kadlecsik <kadlec@netfilter.org>
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_ensure_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, 0);
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, 0);
229                         if (ret == 0)
230                                 break;
231                         else if (ret == -EBUSY) {
232                                 nf_ct_unexpect_related(rtp_exp);
233                                 continue;
234                         } else if (ret < 0) {
235                                 nf_ct_unexpect_related(rtp_exp);
236                                 nated_port = 0;
237                                 break;
238                         }
239                 } else if (ret != -EBUSY) {
240                         nated_port = 0;
241                         break;
242                 }
243         }
244
245         if (nated_port == 0) {  /* No port available */
246                 net_notice_ratelimited("nf_nat_h323: out of RTP ports\n");
247                 return 0;
248         }
249
250         /* Modify signal */
251         if (set_h245_addr(skb, protoff, data, dataoff, taddr,
252                           &ct->tuplehash[!dir].tuple.dst.u3,
253                           htons((port & htons(1)) ? nated_port + 1 :
254                                                     nated_port))) {
255                 nf_ct_unexpect_related(rtp_exp);
256                 nf_ct_unexpect_related(rtcp_exp);
257                 return -1;
258         }
259
260         /* Save ports */
261         info->rtp_port[i][dir] = rtp_port;
262         info->rtp_port[i][!dir] = htons(nated_port);
263
264         /* Success */
265         pr_debug("nf_nat_h323: expect RTP %pI4:%hu->%pI4:%hu\n",
266                  &rtp_exp->tuple.src.u3.ip,
267                  ntohs(rtp_exp->tuple.src.u.udp.port),
268                  &rtp_exp->tuple.dst.u3.ip,
269                  ntohs(rtp_exp->tuple.dst.u.udp.port));
270         pr_debug("nf_nat_h323: expect RTCP %pI4:%hu->%pI4:%hu\n",
271                  &rtcp_exp->tuple.src.u3.ip,
272                  ntohs(rtcp_exp->tuple.src.u.udp.port),
273                  &rtcp_exp->tuple.dst.u3.ip,
274                  ntohs(rtcp_exp->tuple.dst.u.udp.port));
275
276         return 0;
277 }
278
279 /****************************************************************************/
280 static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
281                     enum ip_conntrack_info ctinfo,
282                     unsigned int protoff, unsigned char **data, int dataoff,
283                     H245_TransportAddress *taddr, __be16 port,
284                     struct nf_conntrack_expect *exp)
285 {
286         int dir = CTINFO2DIR(ctinfo);
287         u_int16_t nated_port = ntohs(port);
288
289         /* Set expectations for NAT */
290         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
291         exp->expectfn = nf_nat_follow_master;
292         exp->dir = !dir;
293
294         /* Try to get same port: if not, try to change it. */
295         for (; nated_port != 0; nated_port++) {
296                 int ret;
297
298                 exp->tuple.dst.u.tcp.port = htons(nated_port);
299                 ret = nf_ct_expect_related(exp, 0);
300                 if (ret == 0)
301                         break;
302                 else if (ret != -EBUSY) {
303                         nated_port = 0;
304                         break;
305                 }
306         }
307
308         if (nated_port == 0) {  /* No port available */
309                 net_notice_ratelimited("nf_nat_h323: out of TCP ports\n");
310                 return 0;
311         }
312
313         /* Modify signal */
314         if (set_h245_addr(skb, protoff, data, dataoff, taddr,
315                           &ct->tuplehash[!dir].tuple.dst.u3,
316                           htons(nated_port)) < 0) {
317                 nf_ct_unexpect_related(exp);
318                 return -1;
319         }
320
321         pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n",
322                  &exp->tuple.src.u3.ip,
323                  ntohs(exp->tuple.src.u.tcp.port),
324                  &exp->tuple.dst.u3.ip,
325                  ntohs(exp->tuple.dst.u.tcp.port));
326
327         return 0;
328 }
329
330 /****************************************************************************/
331 static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
332                     enum ip_conntrack_info ctinfo,
333                     unsigned int protoff, unsigned char **data, int dataoff,
334                     TransportAddress *taddr, __be16 port,
335                     struct nf_conntrack_expect *exp)
336 {
337         struct nf_ct_h323_master *info = nfct_help_data(ct);
338         int dir = CTINFO2DIR(ctinfo);
339         u_int16_t nated_port = ntohs(port);
340
341         /* Set expectations for NAT */
342         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
343         exp->expectfn = nf_nat_follow_master;
344         exp->dir = !dir;
345
346         /* Check existing expects */
347         if (info->sig_port[dir] == port)
348                 nated_port = ntohs(info->sig_port[!dir]);
349
350         /* Try to get same port: if not, try to change it. */
351         for (; nated_port != 0; nated_port++) {
352                 int ret;
353
354                 exp->tuple.dst.u.tcp.port = htons(nated_port);
355                 ret = nf_ct_expect_related(exp, 0);
356                 if (ret == 0)
357                         break;
358                 else if (ret != -EBUSY) {
359                         nated_port = 0;
360                         break;
361                 }
362         }
363
364         if (nated_port == 0) {  /* No port available */
365                 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
366                 return 0;
367         }
368
369         /* Modify signal */
370         if (set_h225_addr(skb, protoff, data, dataoff, taddr,
371                           &ct->tuplehash[!dir].tuple.dst.u3,
372                           htons(nated_port))) {
373                 nf_ct_unexpect_related(exp);
374                 return -1;
375         }
376
377         /* Save ports */
378         info->sig_port[dir] = port;
379         info->sig_port[!dir] = htons(nated_port);
380
381         pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n",
382                  &exp->tuple.src.u3.ip,
383                  ntohs(exp->tuple.src.u.tcp.port),
384                  &exp->tuple.dst.u3.ip,
385                  ntohs(exp->tuple.dst.u.tcp.port));
386
387         return 0;
388 }
389
390 /****************************************************************************
391  * This conntrack expect function replaces nf_conntrack_q931_expect()
392  * which was set by nf_conntrack_h323.c.
393  ****************************************************************************/
394 static void ip_nat_q931_expect(struct nf_conn *new,
395                                struct nf_conntrack_expect *this)
396 {
397         struct nf_nat_range2 range;
398
399         if (this->tuple.src.u3.ip != 0) {       /* Only accept calls from GK */
400                 nf_nat_follow_master(new, this);
401                 return;
402         }
403
404         /* This must be a fresh one. */
405         BUG_ON(new->status & IPS_NAT_DONE_MASK);
406
407         /* Change src to where master sends to */
408         range.flags = NF_NAT_RANGE_MAP_IPS;
409         range.min_addr = range.max_addr =
410             new->tuplehash[!this->dir].tuple.src.u3;
411         nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
412
413         /* For DST manip, map port here to where it's expected. */
414         range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
415         range.min_proto = range.max_proto = this->saved_proto;
416         range.min_addr = range.max_addr =
417             new->master->tuplehash[!this->dir].tuple.src.u3;
418         nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
419 }
420
421 /****************************************************************************/
422 static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
423                     enum ip_conntrack_info ctinfo,
424                     unsigned int protoff, unsigned char **data,
425                     TransportAddress *taddr, int idx,
426                     __be16 port, struct nf_conntrack_expect *exp)
427 {
428         struct nf_ct_h323_master *info = nfct_help_data(ct);
429         int dir = CTINFO2DIR(ctinfo);
430         u_int16_t nated_port = ntohs(port);
431         union nf_inet_addr addr;
432
433         /* Set expectations for NAT */
434         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
435         exp->expectfn = ip_nat_q931_expect;
436         exp->dir = !dir;
437
438         /* Check existing expects */
439         if (info->sig_port[dir] == port)
440                 nated_port = ntohs(info->sig_port[!dir]);
441
442         /* Try to get same port: if not, try to change it. */
443         for (; nated_port != 0; nated_port++) {
444                 int ret;
445
446                 exp->tuple.dst.u.tcp.port = htons(nated_port);
447                 ret = nf_ct_expect_related(exp, 0);
448                 if (ret == 0)
449                         break;
450                 else if (ret != -EBUSY) {
451                         nated_port = 0;
452                         break;
453                 }
454         }
455
456         if (nated_port == 0) {  /* No port available */
457                 net_notice_ratelimited("nf_nat_ras: out of TCP ports\n");
458                 return 0;
459         }
460
461         /* Modify signal */
462         if (set_h225_addr(skb, protoff, data, 0, &taddr[idx],
463                           &ct->tuplehash[!dir].tuple.dst.u3,
464                           htons(nated_port))) {
465                 nf_ct_unexpect_related(exp);
466                 return -1;
467         }
468
469         /* Save ports */
470         info->sig_port[dir] = port;
471         info->sig_port[!dir] = htons(nated_port);
472
473         /* Fix for Gnomemeeting */
474         if (idx > 0 &&
475             get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
476             (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
477                 if (set_h225_addr(skb, protoff, data, 0, &taddr[0],
478                                   &ct->tuplehash[!dir].tuple.dst.u3,
479                                   info->sig_port[!dir])) {
480                         nf_ct_unexpect_related(exp);
481                         return -1;
482                 }
483         }
484
485         /* Success */
486         pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n",
487                  &exp->tuple.src.u3.ip,
488                  ntohs(exp->tuple.src.u.tcp.port),
489                  &exp->tuple.dst.u3.ip,
490                  ntohs(exp->tuple.dst.u.tcp.port));
491
492         return 0;
493 }
494
495 /****************************************************************************/
496 static void ip_nat_callforwarding_expect(struct nf_conn *new,
497                                          struct nf_conntrack_expect *this)
498 {
499         struct nf_nat_range2 range;
500
501         /* This must be a fresh one. */
502         BUG_ON(new->status & IPS_NAT_DONE_MASK);
503
504         /* Change src to where master sends to */
505         range.flags = NF_NAT_RANGE_MAP_IPS;
506         range.min_addr = range.max_addr =
507             new->tuplehash[!this->dir].tuple.src.u3;
508         nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
509
510         /* For DST manip, map port here to where it's expected. */
511         range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
512         range.min_proto = range.max_proto = this->saved_proto;
513         range.min_addr = range.max_addr = this->saved_addr;
514         nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
515 }
516
517 /****************************************************************************/
518 static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
519                               enum ip_conntrack_info ctinfo,
520                               unsigned int protoff,
521                               unsigned char **data, int dataoff,
522                               TransportAddress *taddr, __be16 port,
523                               struct nf_conntrack_expect *exp)
524 {
525         int dir = CTINFO2DIR(ctinfo);
526         u_int16_t nated_port;
527
528         /* Set expectations for NAT */
529         exp->saved_addr = exp->tuple.dst.u3;
530         exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
531         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
532         exp->expectfn = ip_nat_callforwarding_expect;
533         exp->dir = !dir;
534
535         /* Try to get same port: if not, try to change it. */
536         for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
537                 int ret;
538
539                 exp->tuple.dst.u.tcp.port = htons(nated_port);
540                 ret = nf_ct_expect_related(exp, 0);
541                 if (ret == 0)
542                         break;
543                 else if (ret != -EBUSY) {
544                         nated_port = 0;
545                         break;
546                 }
547         }
548
549         if (nated_port == 0) {  /* No port available */
550                 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
551                 return 0;
552         }
553
554         /* Modify signal */
555         if (set_h225_addr(skb, protoff, data, dataoff, taddr,
556                           &ct->tuplehash[!dir].tuple.dst.u3,
557                           htons(nated_port))) {
558                 nf_ct_unexpect_related(exp);
559                 return -1;
560         }
561
562         /* Success */
563         pr_debug("nf_nat_q931: expect Call Forwarding %pI4:%hu->%pI4:%hu\n",
564                  &exp->tuple.src.u3.ip,
565                  ntohs(exp->tuple.src.u.tcp.port),
566                  &exp->tuple.dst.u3.ip,
567                  ntohs(exp->tuple.dst.u.tcp.port));
568
569         return 0;
570 }
571
572 static struct nf_ct_helper_expectfn q931_nat = {
573         .name           = "Q.931",
574         .expectfn       = ip_nat_q931_expect,
575 };
576
577 static struct nf_ct_helper_expectfn callforwarding_nat = {
578         .name           = "callforwarding",
579         .expectfn       = ip_nat_callforwarding_expect,
580 };
581
582 /****************************************************************************/
583 static int __init init(void)
584 {
585         BUG_ON(set_h245_addr_hook != NULL);
586         BUG_ON(set_h225_addr_hook != NULL);
587         BUG_ON(set_sig_addr_hook != NULL);
588         BUG_ON(set_ras_addr_hook != NULL);
589         BUG_ON(nat_rtp_rtcp_hook != NULL);
590         BUG_ON(nat_t120_hook != NULL);
591         BUG_ON(nat_h245_hook != NULL);
592         BUG_ON(nat_callforwarding_hook != NULL);
593         BUG_ON(nat_q931_hook != NULL);
594
595         RCU_INIT_POINTER(set_h245_addr_hook, set_h245_addr);
596         RCU_INIT_POINTER(set_h225_addr_hook, set_h225_addr);
597         RCU_INIT_POINTER(set_sig_addr_hook, set_sig_addr);
598         RCU_INIT_POINTER(set_ras_addr_hook, set_ras_addr);
599         RCU_INIT_POINTER(nat_rtp_rtcp_hook, nat_rtp_rtcp);
600         RCU_INIT_POINTER(nat_t120_hook, nat_t120);
601         RCU_INIT_POINTER(nat_h245_hook, nat_h245);
602         RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
603         RCU_INIT_POINTER(nat_q931_hook, nat_q931);
604         nf_ct_helper_expectfn_register(&q931_nat);
605         nf_ct_helper_expectfn_register(&callforwarding_nat);
606         return 0;
607 }
608
609 /****************************************************************************/
610 static void __exit fini(void)
611 {
612         RCU_INIT_POINTER(set_h245_addr_hook, NULL);
613         RCU_INIT_POINTER(set_h225_addr_hook, NULL);
614         RCU_INIT_POINTER(set_sig_addr_hook, NULL);
615         RCU_INIT_POINTER(set_ras_addr_hook, NULL);
616         RCU_INIT_POINTER(nat_rtp_rtcp_hook, NULL);
617         RCU_INIT_POINTER(nat_t120_hook, NULL);
618         RCU_INIT_POINTER(nat_h245_hook, NULL);
619         RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
620         RCU_INIT_POINTER(nat_q931_hook, NULL);
621         nf_ct_helper_expectfn_unregister(&q931_nat);
622         nf_ct_helper_expectfn_unregister(&callforwarding_nat);
623         synchronize_rcu();
624 }
625
626 /****************************************************************************/
627 module_init(init);
628 module_exit(fini);
629
630 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
631 MODULE_DESCRIPTION("H.323 NAT helper");
632 MODULE_LICENSE("GPL");
633 MODULE_ALIAS_NF_NAT_HELPER("h323");