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