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