linux/net/ipv4/netfilter/nf_nat_h323.c
<<
>>
Prefs
   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/****************************************************************************/
  23static 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/****************************************************************************/
  71static 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/****************************************************************************/
  81static 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/****************************************************************************/
  92static 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/****************************************************************************/
 145static 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/****************************************************************************/
 174static 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/****************************************************************************/
 280static 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/****************************************************************************/
 331static 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 ****************************************************************************/
 394static 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/****************************************************************************/
 422static 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/****************************************************************************/
 496static 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/****************************************************************************/
 518static 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
 572static struct nf_ct_helper_expectfn q931_nat = {
 573        .name           = "Q.931",
 574        .expectfn       = ip_nat_q931_expect,
 575};
 576
 577static struct nf_ct_helper_expectfn callforwarding_nat = {
 578        .name           = "callforwarding",
 579        .expectfn       = ip_nat_callforwarding_expect,
 580};
 581
 582/****************************************************************************/
 583static 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/****************************************************************************/
 610static 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/****************************************************************************/
 627module_init(init);
 628module_exit(fini);
 629
 630MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
 631MODULE_DESCRIPTION("H.323 NAT helper");
 632MODULE_LICENSE("GPL");
 633MODULE_ALIAS_NF_NAT_HELPER("h323");
 634