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