char pbuf[sizeof("65535")], *tmp;
        u_int16_t port, len;
        int ret = NF_ACCEPT;
+       typeof(ip_nat_amanda_hook) ip_nat_amanda;
 
        /* Only look at packets from the Amanda server */
        if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
                exp->mask.dst.protonum = 0xFF;
                exp->mask.dst.u.tcp.port = htons(0xFFFF);
 
-               if (ip_nat_amanda_hook)
-                       ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
-                                                len, exp);
+               /* RCU read locked by nf_hook_slow */
+               ip_nat_amanda = rcu_dereference(ip_nat_amanda_hook);
+               if (ip_nat_amanda)
+                       ret = ip_nat_amanda(pskb, ctinfo, off - dataoff,
+                                           len, exp);
                else if (ip_conntrack_expect_related(exp) != 0)
                        ret = NF_DROP;
                ip_conntrack_expect_put(exp);
 
        struct ip_conntrack_expect *exp;
        unsigned int i;
        int found = 0, ends_in_nl;
+       typeof(ip_nat_ftp_hook) ip_nat_ftp;
 
        /* Until there's been traffic both ways, don't look in packets. */
        if (ctinfo != IP_CT_ESTABLISHED
 
        /* Now, NAT might want to mangle the packet, and register the
         * (possibly changed) expectation itself. */
-       if (ip_nat_ftp_hook)
-               ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
-                                     matchoff, matchlen, exp, &seq);
+       ip_nat_ftp = rcu_dereference(ip_nat_ftp_hook);
+       if (ip_nat_ftp)
+               ret = ip_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
+                                matchoff, matchlen, exp, &seq);
        else {
                /* Can't expect this?  Best to drop packet now. */
                if (ip_conntrack_expect_related(exp) != 0)
 
        u_int16_t rtp_port;
        struct ip_conntrack_expect *rtp_exp;
        struct ip_conntrack_expect *rtcp_exp;
+       typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
 
        /* Read RTP or RTCP address */
        if (!get_h245_addr(*data, addr, &ip, &port) ||
        rtcp_exp->flags = 0;
 
        if (ct->tuplehash[dir].tuple.src.ip !=
-           ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) {
+           ct->tuplehash[!dir].tuple.dst.ip &&
+           (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook))) {
                /* NAT needed */
-               ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff,
-                                       addr, port, rtp_port, rtp_exp,
-                                       rtcp_exp);
+               ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
+                                  addr, port, rtp_port, rtp_exp, rtcp_exp);
        } else {                /* Conntrack only */
                rtp_exp->expectfn = NULL;
                rtcp_exp->expectfn = NULL;
        __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp = NULL;
+       typeof(nat_t120_hook) nat_t120;
 
        /* Read T.120 address */
        if (!get_h245_addr(*data, addr, &ip, &port) ||
        exp->flags = IP_CT_EXPECT_PERMANENT;    /* Accept multiple channels */
 
        if (ct->tuplehash[dir].tuple.src.ip !=
-           ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) {
+           ct->tuplehash[!dir].tuple.dst.ip &&
+           (nat_t120 = rcu_dereference(nat_t120_hook))) {
                /* NAT needed */
-               ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr,
-                                   port, exp);
+               ret = nat_t120(pskb, ct, ctinfo, data, dataoff, addr,
+                              port, exp);
        } else {                /* Conntrack only */
                exp->expectfn = NULL;
                if (ip_conntrack_expect_related(exp) == 0) {
        __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp = NULL;
+       typeof(nat_h245_hook) nat_h245;
 
        /* Read h245Address */
        if (!get_h225_addr(*data, addr, &ip, &port) ||
        exp->flags = 0;
 
        if (ct->tuplehash[dir].tuple.src.ip !=
-           ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) {
+           ct->tuplehash[!dir].tuple.dst.ip &&
+           (nat_h245 = rcu_dereference(nat_h245_hook))) {
                /* NAT needed */
-               ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr,
-                                   port, exp);
+               ret = nat_h245(pskb, ct, ctinfo, data, dataoff, addr,
+                              port, exp);
        } else {                /* Conntrack only */
                exp->expectfn = ip_conntrack_h245_expect;
 
        __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp = NULL;
+       typeof(nat_callforwarding_hook) nat_callforwarding;
 
        /* Read alternativeAddress */
        if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
        exp->flags = 0;
 
        if (ct->tuplehash[dir].tuple.src.ip !=
-           ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) {
+           ct->tuplehash[!dir].tuple.dst.ip &&
+           (nat_callforwarding = rcu_dereference(nat_callforwarding_hook))) {
                /* Need NAT */
-               ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff,
-                                             addr, port, exp);
+               ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
+                                        addr, port, exp);
        } else {                /* Conntrack only */
                exp->expectfn = ip_conntrack_q931_expect;
 
        int i;
        __be32 ip;
        u_int16_t port;
+       typeof(set_h225_addr_hook) set_h225_addr;
 
        DEBUGP("ip_ct_q931: Setup\n");
 
                        return -1;
        }
 
+       set_h225_addr = rcu_dereference(set_h225_addr_hook);
+
        if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
-           (set_h225_addr_hook) &&
+           (set_h225_addr) &&
            get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
            ip != ct->tuplehash[!dir].tuple.src.ip) {
                DEBUGP("ip_ct_q931: set destCallSignalAddress "
                       NIPQUAD(ip), port,
                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
                       ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
-               ret = set_h225_addr_hook(pskb, data, dataoff,
-                                        &setup->destCallSignalAddress,
-                                        ct->tuplehash[!dir].tuple.src.ip,
-                                        ntohs(ct->tuplehash[!dir].tuple.src.
-                                              u.tcp.port));
+               ret = set_h225_addr(pskb, data, dataoff,
+                                   &setup->destCallSignalAddress,
+                                   ct->tuplehash[!dir].tuple.src.ip,
+                                   ntohs(ct->tuplehash[!dir].tuple.src.
+                                         u.tcp.port));
                if (ret < 0)
                        return -1;
        }
 
        if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
-           (set_h225_addr_hook) &&
+           (set_h225_addr) &&
            get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
            && ip != ct->tuplehash[!dir].tuple.dst.ip) {
                DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
                       NIPQUAD(ip), port,
                       NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
                       ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
-               ret = set_h225_addr_hook(pskb, data, dataoff,
-                                        &setup->sourceCallSignalAddress,
-                                        ct->tuplehash[!dir].tuple.dst.ip,
-                                        ntohs(ct->tuplehash[!dir].tuple.dst.
-                                              u.tcp.port));
+               ret = set_h225_addr(pskb, data, dataoff,
+                                   &setup->sourceCallSignalAddress,
+                                   ct->tuplehash[!dir].tuple.dst.ip,
+                                   ntohs(ct->tuplehash[!dir].tuple.dst.
+                                         u.tcp.port));
                if (ret < 0)
                        return -1;
        }
        __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp;
+       typeof(nat_q931_hook) nat_q931;
 
        /* Look for the first related address */
        for (i = 0; i < count; i++) {
        exp->mask.dst.protonum = 0xFF;
        exp->flags = IP_CT_EXPECT_PERMANENT;    /* Accept multiple calls */
 
-       if (nat_q931_hook) {    /* Need NAT */
-               ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i,
-                                   port, exp);
+       nat_q931 = rcu_dereference(nat_q931_hook);
+       if (nat_q931) { /* Need NAT */
+               ret = nat_q931(pskb, ct, ctinfo, data, addr, i, port, exp);
        } else {                /* Conntrack only */
                exp->expectfn = ip_conntrack_q931_expect;
 
                       enum ip_conntrack_info ctinfo,
                       unsigned char **data, GatekeeperRequest * grq)
 {
+       typeof(set_ras_addr_hook) set_ras_addr;
+
        DEBUGP("ip_ct_ras: GRQ\n");
 
-       if (set_ras_addr_hook)  /* NATed */
-               return set_ras_addr_hook(pskb, ct, ctinfo, data,
-                                        &grq->rasAddress, 1);
+       set_ras_addr = rcu_dereference(set_ras_addr_hook);
+       if (set_ras_addr)       /* NATed */
+               return set_ras_addr(pskb, ct, ctinfo, data,
+                                   &grq->rasAddress, 1);
        return 0;
 }
 
 {
        struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
        int ret;
+       typeof(set_ras_addr_hook) set_ras_addr;
 
        DEBUGP("ip_ct_ras: RRQ\n");
 
        if (ret < 0)
                return -1;
 
-       if (set_ras_addr_hook) {
-               ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
-                                       rrq->rasAddress.item,
-                                       rrq->rasAddress.count);
+       set_ras_addr = rcu_dereference(set_ras_addr_hook);
+       if (set_ras_addr) {
+               ret = set_ras_addr(pskb, ct, ctinfo, data,
+                                  rrq->rasAddress.item,
+                                  rrq->rasAddress.count);
                if (ret < 0)
                        return -1;
        }
        int dir = CTINFO2DIR(ctinfo);
        int ret;
        struct ip_conntrack_expect *exp;
+       typeof(set_sig_addr_hook) set_sig_addr;
 
        DEBUGP("ip_ct_ras: RCF\n");
 
-       if (set_sig_addr_hook) {
-               ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
-                                       rcf->callSignalAddress.item,
-                                       rcf->callSignalAddress.count);
+       set_sig_addr = rcu_dereference(set_sig_addr_hook);
+       if (set_sig_addr) {
+               ret = set_sig_addr(pskb, ct, ctinfo, data,
+                                  rcf->callSignalAddress.item,
+                                  rcf->callSignalAddress.count);
                if (ret < 0)
                        return -1;
        }
        struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
        int dir = CTINFO2DIR(ctinfo);
        int ret;
+       typeof(set_sig_addr_hook) set_sig_addr;
 
        DEBUGP("ip_ct_ras: URQ\n");
 
-       if (set_sig_addr_hook) {
-               ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
-                                       urq->callSignalAddress.item,
-                                       urq->callSignalAddress.count);
+       set_sig_addr = rcu_dereference(set_sig_addr_hook);
+       if (set_sig_addr) {
+               ret = set_sig_addr(pskb, ct, ctinfo, data,
+                                  urq->callSignalAddress.item,
+                                  urq->callSignalAddress.count);
                if (ret < 0)
                        return -1;
        }
        int dir = CTINFO2DIR(ctinfo);
        __be32 ip;
        u_int16_t port;
+       typeof(set_h225_addr_hook) set_h225_addr;
 
        DEBUGP("ip_ct_ras: ARQ\n");
 
+       set_h225_addr = rcu_dereference(set_h225_addr_hook);
        if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
            get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
            ip == ct->tuplehash[dir].tuple.src.ip &&
-           port == info->sig_port[dir] && set_h225_addr_hook) {
+           port == info->sig_port[dir] && set_h225_addr) {
                /* Answering ARQ */
-               return set_h225_addr_hook(pskb, data, 0,
-                                         &arq->destCallSignalAddress,
-                                         ct->tuplehash[!dir].tuple.dst.ip,
-                                         info->sig_port[!dir]);
+               return set_h225_addr(pskb, data, 0,
+                                    &arq->destCallSignalAddress,
+                                    ct->tuplehash[!dir].tuple.dst.ip,
+                                    info->sig_port[!dir]);
        }
 
        if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
            get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
-           ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) {
+           ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr) {
                /* Calling ARQ */
-               return set_h225_addr_hook(pskb, data, 0,
-                                         &arq->srcCallSignalAddress,
-                                         ct->tuplehash[!dir].tuple.dst.ip,
-                                         port);
+               return set_h225_addr(pskb, data, 0,
+                                    &arq->srcCallSignalAddress,
+                                    ct->tuplehash[!dir].tuple.dst.ip,
+                                    port);
        }
 
        return 0;
        __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp;
+       typeof(set_sig_addr_hook) set_sig_addr;
 
        DEBUGP("ip_ct_ras: ACF\n");
 
                return 0;
 
        if (ip == ct->tuplehash[dir].tuple.dst.ip) {    /* Answering ACF */
-               if (set_sig_addr_hook)
-                       return set_sig_addr_hook(pskb, ct, ctinfo, data,
-                                                &acf->destCallSignalAddress,
-                                                1);
+               set_sig_addr = rcu_dereference(set_sig_addr_hook);
+               if (set_sig_addr)
+                       return set_sig_addr(pskb, ct, ctinfo, data,
+                                           &acf->destCallSignalAddress, 1);
                return 0;
        }
 
                       enum ip_conntrack_info ctinfo,
                       unsigned char **data, LocationRequest * lrq)
 {
+       typeof(set_ras_addr_hook) set_ras_addr;
+
        DEBUGP("ip_ct_ras: LRQ\n");
 
-       if (set_ras_addr_hook)
-               return set_ras_addr_hook(pskb, ct, ctinfo, data,
-                                        &lrq->replyAddress, 1);
+       set_ras_addr = rcu_dereference(set_ras_addr_hook);
+       if (set_ras_addr)
+               return set_ras_addr(pskb, ct, ctinfo, data,
+                                   &lrq->replyAddress, 1);
        return 0;
 }
 
                       unsigned char **data, InfoRequestResponse * irr)
 {
        int ret;
+       typeof(set_ras_addr_hook) set_ras_addr;
+       typeof(set_sig_addr_hook) set_sig_addr;
 
        DEBUGP("ip_ct_ras: IRR\n");
 
-       if (set_ras_addr_hook) {
-               ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
-                                       &irr->rasAddress, 1);
+       set_ras_addr = rcu_dereference(set_ras_addr_hook);
+       if (set_ras_addr) {
+               ret = set_ras_addr(pskb, ct, ctinfo, data,
+                                  &irr->rasAddress, 1);
                if (ret < 0)
                        return -1;
        }
 
-       if (set_sig_addr_hook) {
-               ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
-                                       irr->callSignalAddress.item,
-                                       irr->callSignalAddress.count);
+       set_sig_addr = rcu_dereference(set_sig_addr_hook);
+       if (set_sig_addr) {
+               ret = set_sig_addr(pskb, ct, ctinfo, data,
+                                  irr->callSignalAddress.item,
+                                  irr->callSignalAddress.count);
                if (ret < 0)
                        return -1;
        }
 
 static void pptp_expectfn(struct ip_conntrack *ct,
                         struct ip_conntrack_expect *exp)
 {
+       typeof(ip_nat_pptp_hook_expectfn) ip_nat_pptp_expectfn;
+
        DEBUGP("increasing timeouts\n");
 
        /* increase timeout of GRE data channel conntrack entry */
        /* Can you see how rusty this code is, compared with the pre-2.6.11
         * one? That's what happened to my shiny newnat of 2002 ;( -HW */
 
-       if (!ip_nat_pptp_hook_expectfn) {
+       rcu_read_lock();
+       ip_nat_pptp_expectfn = rcu_dereference(ip_nat_pptp_hook_expectfn);
+       if (!ip_nat_pptp_expectfn) {
                struct ip_conntrack_tuple inv_t;
                struct ip_conntrack_expect *exp_other;
 
                }
        } else {
                /* we need more than simple inversion */
-               ip_nat_pptp_hook_expectfn(ct, exp);
+               ip_nat_pptp_expectfn(ct, exp);
        }
+       rcu_read_unlock();
 }
 
 static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
 {
        struct ip_conntrack_expect *exp_orig, *exp_reply;
        int ret = 1;
+       typeof(ip_nat_pptp_hook_exp_gre) ip_nat_pptp_exp_gre;
 
        exp_orig = ip_conntrack_expect_alloc(ct);
        if (exp_orig == NULL)
        exp_reply->tuple.dst.u.gre.key = peer_callid;
        exp_reply->tuple.dst.protonum = IPPROTO_GRE;
 
-       if (ip_nat_pptp_hook_exp_gre)
-               ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
+       ip_nat_pptp_exp_gre = rcu_dereference(ip_nat_pptp_hook_exp_gre);
+       if (ip_nat_pptp_exp_gre)
+               ip_nat_pptp_exp_gre(exp_orig, exp_reply);
        if (ip_conntrack_expect_related(exp_orig) != 0)
                goto out_put_both;
        if (ip_conntrack_expect_related(exp_reply) != 0)
        struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
        u_int16_t msg;
        __be16 cid = 0, pcid = 0;
+       typeof(ip_nat_pptp_hook_inbound) ip_nat_pptp_inbound;
 
        msg = ntohs(ctlh->messageType);
        DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
                goto invalid;
        }
 
-       if (ip_nat_pptp_hook_inbound)
-               return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
-                                               pptpReq);
+       ip_nat_pptp_inbound = rcu_dereference(ip_nat_pptp_hook_inbound);
+       if (ip_nat_pptp_inbound)
+               return ip_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq);
        return NF_ACCEPT;
 
 invalid:
        struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
        u_int16_t msg;
        __be16 cid = 0, pcid = 0;
+       typeof(ip_nat_pptp_hook_outbound) ip_nat_pptp_outbound;
 
        msg = ntohs(ctlh->messageType);
        DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
                goto invalid;
        }
 
-       if (ip_nat_pptp_hook_outbound)
-               return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
-                                                pptpReq);
+       ip_nat_pptp_outbound = rcu_dereference(ip_nat_pptp_hook_outbound);
+       if (ip_nat_pptp_outbound)
+               return ip_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq);
        return NF_ACCEPT;
 
 invalid:
 
        u_int16_t dcc_port;
        int i, ret = NF_ACCEPT;
        char *addr_beg_p, *addr_end_p;
+       typeof(ip_nat_irc_hook) ip_nat_irc;
 
        DEBUGP("entered\n");
 
                                        { .tcp = { htons(0xFFFF) } }, 0xFF }});
                        exp->expectfn = NULL;
                        exp->flags = 0;
-                       if (ip_nat_irc_hook)
-                               ret = ip_nat_irc_hook(pskb, ctinfo, 
-                                                     addr_beg_p - ib_ptr,
-                                                     addr_end_p - addr_beg_p,
-                                                     exp);
+                       ip_nat_irc = rcu_dereference(ip_nat_irc_hook);
+                       if (ip_nat_irc)
+                               ret = ip_nat_irc(pskb, ctinfo,
+                                                addr_beg_p - ib_ptr,
+                                                addr_end_p - addr_beg_p,
+                                                exp);
                        else if (ip_conntrack_expect_related(exp) != 0)
                                ret = NF_DROP;
                        ip_conntrack_expect_put(exp);
 
        struct ip_conntrack_expect *exp;
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
        int ret;
+       typeof(ip_nat_sdp_hook) ip_nat_sdp;
 
        exp = ip_conntrack_expect_alloc(ct);
        if (exp == NULL)
        exp->expectfn = NULL;
        exp->flags = 0;
 
-       if (ip_nat_sdp_hook)
-               ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
+       ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook);
+       if (ip_nat_sdp)
+               ret = ip_nat_sdp(pskb, ctinfo, exp, dptr);
        else {
                if (ip_conntrack_expect_related(exp) != 0)
                        ret = NF_DROP;
        int matchoff, matchlen;
        __be32 ipaddr;
        u_int16_t port;
+       typeof(ip_nat_sip_hook) ip_nat_sip;
 
        /* No Data ? */
        dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
                goto out;
        }
 
-       if (ip_nat_sip_hook) {
-               if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
+       ip_nat_sip = rcu_dereference(ip_nat_sip_hook);
+       if (ip_nat_sip) {
+               if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) {
                        ret = NF_DROP;
                        goto out;
                }
 
        struct tftphdr _tftph, *tfh;
        struct ip_conntrack_expect *exp;
        unsigned int ret = NF_ACCEPT;
+       typeof(ip_nat_tftp_hook) ip_nat_tftp;
 
        tfh = skb_header_pointer(*pskb,
                                 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
                DEBUGP("expect: ");
                DUMP_TUPLE(&exp->tuple);
                DUMP_TUPLE(&exp->mask);
-               if (ip_nat_tftp_hook)
-                       ret = ip_nat_tftp_hook(pskb, ctinfo, exp);
+               ip_nat_tftp = rcu_dereference(ip_nat_tftp_hook);
+               if (ip_nat_tftp)
+                       ret = ip_nat_tftp(pskb, ctinfo, exp);
                else if (ip_conntrack_expect_related(exp) != 0)
                        ret = NF_DROP;
                ip_conntrack_expect_put(exp);
 
 
 static void __exit ip_nat_amanda_fini(void)
 {
-       ip_nat_amanda_hook = NULL;
-       /* Make sure noone calls it, meanwhile. */
-       synchronize_net();
+       rcu_assign_pointer(ip_nat_amanda_hook, NULL);
+       synchronize_rcu();
 }
 
 static int __init ip_nat_amanda_init(void)
 {
-       BUG_ON(ip_nat_amanda_hook);
-       ip_nat_amanda_hook = help;
+       BUG_ON(rcu_dereference(ip_nat_amanda_hook));
+       rcu_assign_pointer(ip_nat_amanda_hook, help);
        return 0;
 }
 
 
 
 static void __exit ip_nat_ftp_fini(void)
 {
-       ip_nat_ftp_hook = NULL;
-       /* Make sure noone calls it, meanwhile. */
-       synchronize_net();
+       rcu_assign_pointer(ip_nat_ftp_hook, NULL);
+       synchronize_rcu();
 }
 
 static int __init ip_nat_ftp_init(void)
 {
-       BUG_ON(ip_nat_ftp_hook);
-       ip_nat_ftp_hook = ip_nat_ftp;
+       BUG_ON(rcu_dereference(ip_nat_ftp_hook));
+       rcu_assign_pointer(ip_nat_ftp_hook, ip_nat_ftp);
        return 0;
 }
 
 
 /****************************************************************************/
 static int __init init(void)
 {
-       BUG_ON(set_h245_addr_hook != NULL);
-       BUG_ON(set_h225_addr_hook != NULL);
-       BUG_ON(set_sig_addr_hook != NULL);
-       BUG_ON(set_ras_addr_hook != NULL);
-       BUG_ON(nat_rtp_rtcp_hook != NULL);
-       BUG_ON(nat_t120_hook != NULL);
-       BUG_ON(nat_h245_hook != NULL);
-       BUG_ON(nat_callforwarding_hook != NULL);
-       BUG_ON(nat_q931_hook != NULL);
-
-       set_h245_addr_hook = set_h245_addr;
-       set_h225_addr_hook = set_h225_addr;
-       set_sig_addr_hook = set_sig_addr;
-       set_ras_addr_hook = set_ras_addr;
-       nat_rtp_rtcp_hook = nat_rtp_rtcp;
-       nat_t120_hook = nat_t120;
-       nat_h245_hook = nat_h245;
-       nat_callforwarding_hook = nat_callforwarding;
-       nat_q931_hook = nat_q931;
+       BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
+       BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
+       BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
+       BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
+       BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
+       BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
+       BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
+       BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
+       BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
+
+       rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
+       rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
+       rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
+       rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
+       rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
+       rcu_assign_pointer(nat_t120_hook, nat_t120);
+       rcu_assign_pointer(nat_h245_hook, nat_h245);
+       rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
+       rcu_assign_pointer(nat_q931_hook, nat_q931);
 
        DEBUGP("ip_nat_h323: init success\n");
        return 0;
 /****************************************************************************/
 static void __exit fini(void)
 {
-       set_h245_addr_hook = NULL;
-       set_h225_addr_hook = NULL;
-       set_sig_addr_hook = NULL;
-       set_ras_addr_hook = NULL;
-       nat_rtp_rtcp_hook = NULL;
-       nat_t120_hook = NULL;
-       nat_h245_hook = NULL;
-       nat_callforwarding_hook = NULL;
-       nat_q931_hook = NULL;
-       synchronize_net();
+       rcu_assign_pointer(set_h245_addr_hook, NULL);
+       rcu_assign_pointer(set_h225_addr_hook, NULL);
+       rcu_assign_pointer(set_sig_addr_hook, NULL);
+       rcu_assign_pointer(set_ras_addr_hook, NULL);
+       rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
+       rcu_assign_pointer(nat_t120_hook, NULL);
+       rcu_assign_pointer(nat_h245_hook, NULL);
+       rcu_assign_pointer(nat_callforwarding_hook, NULL);
+       rcu_assign_pointer(nat_q931_hook, NULL);
+       synchronize_rcu();
 }
 
 /****************************************************************************/
 
        if (ret < 0)
                return ret;
 
-       BUG_ON(ip_nat_pptp_hook_outbound);
-       ip_nat_pptp_hook_outbound = &pptp_outbound_pkt;
+       BUG_ON(rcu_dereference(ip_nat_pptp_hook_outbound));
+       rcu_assign_pointer(ip_nat_pptp_hook_outbound, pptp_outbound_pkt);
 
-       BUG_ON(ip_nat_pptp_hook_inbound);
-       ip_nat_pptp_hook_inbound = &pptp_inbound_pkt;
+       BUG_ON(rcu_dereference(ip_nat_pptp_hook_inbound));
+       rcu_assign_pointer(ip_nat_pptp_hook_inbound, pptp_inbound_pkt);
 
-       BUG_ON(ip_nat_pptp_hook_exp_gre);
-       ip_nat_pptp_hook_exp_gre = &pptp_exp_gre;
+       BUG_ON(rcu_dereference(ip_nat_pptp_hook_exp_gre));
+       rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, pptp_exp_gre);
 
-       BUG_ON(ip_nat_pptp_hook_expectfn);
-       ip_nat_pptp_hook_expectfn = &pptp_nat_expected;
+       BUG_ON(rcu_dereference(ip_nat_pptp_hook_expectfn));
+       rcu_assign_pointer(ip_nat_pptp_hook_expectfn, pptp_nat_expected);
 
        printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
        return 0;
 {
        DEBUGP("cleanup_module\n" );
 
-       ip_nat_pptp_hook_expectfn = NULL;
-       ip_nat_pptp_hook_exp_gre = NULL;
-       ip_nat_pptp_hook_inbound = NULL;
-       ip_nat_pptp_hook_outbound = NULL;
+       rcu_assign_pointer(ip_nat_pptp_hook_expectfn, NULL);
+       rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, NULL);
+       rcu_assign_pointer(ip_nat_pptp_hook_inbound, NULL);
+       rcu_assign_pointer(ip_nat_pptp_hook_outbound, NULL);
+       synchronize_rcu();
 
        ip_nat_proto_gre_fini();
-       /* Make sure noone calls it, meanwhile */
-       synchronize_net();
 
        printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
 }
 
 
 static void __exit ip_nat_irc_fini(void)
 {
-       ip_nat_irc_hook = NULL;
-       /* Make sure noone calls it, meanwhile. */
-       synchronize_net();
+       rcu_assign_pointer(ip_nat_irc_hook, NULL);
+       synchronize_rcu();
 }
 
 static int __init ip_nat_irc_init(void)
 {
-       BUG_ON(ip_nat_irc_hook);
-       ip_nat_irc_hook = help;
+       BUG_ON(rcu_dereference(ip_nat_irc_hook));
+       rcu_assign_pointer(ip_nat_irc_hook, help);
        return 0;
 }
 
 
 
 static void __exit fini(void)
 {
-       ip_nat_sip_hook = NULL;
-       ip_nat_sdp_hook = NULL;
-       /* Make sure noone calls it, meanwhile. */
-       synchronize_net();
+       rcu_assign_pointer(ip_nat_sip_hook, NULL);
+       rcu_assign_pointer(ip_nat_sdp_hook, NULL);
+       synchronize_rcu();
 }
 
 static int __init init(void)
 {
-       BUG_ON(ip_nat_sip_hook);
-       BUG_ON(ip_nat_sdp_hook);
-       ip_nat_sip_hook = ip_nat_sip;
-       ip_nat_sdp_hook = ip_nat_sdp;
+       BUG_ON(rcu_dereference(ip_nat_sip_hook));
+       BUG_ON(rcu_dereference(ip_nat_sdp_hook));
+       rcu_assign_pointer(ip_nat_sip_hook, ip_nat_sip);
+       rcu_assign_pointer(ip_nat_sdp_hook, ip_nat_sdp);
        return 0;
 }
 
 
 
 static void __exit ip_nat_tftp_fini(void)
 {
-       ip_nat_tftp_hook = NULL;
-       /* Make sure noone calls it, meanwhile. */
-       synchronize_net();
+       rcu_assign_pointer(ip_nat_tftp_hook, NULL);
+       synchronize_rcu();
 }
 
 static int __init ip_nat_tftp_init(void)
 {
-       BUG_ON(ip_nat_tftp_hook);
-       ip_nat_tftp_hook = help;
+       BUG_ON(rcu_dereference(ip_nat_tftp_hook));
+       rcu_assign_pointer(ip_nat_tftp_hook, help);
        return 0;
 }
 
 
        struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
        struct nf_conntrack_expect *exp;
        struct nf_conntrack_man cmd = {};
-
        unsigned int i;
        int found = 0, ends_in_nl;
+       typeof(nf_nat_ftp_hook) nf_nat_ftp;
 
        /* Until there's been traffic both ways, don't look in packets. */
        if (ctinfo != IP_CT_ESTABLISHED
 
        /* Now, NAT might want to mangle the packet, and register the
         * (possibly changed) expectation itself. */
-       if (nf_nat_ftp_hook)
-               ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
-                                     matchoff, matchlen, exp, &seq);
+       nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
+       if (nf_nat_ftp)
+               ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
+                                matchoff, matchlen, exp, &seq);
        else {
                /* Can't expect this?  Best to drop packet now. */
                if (nf_conntrack_expect_related(exp) != 0)