]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/netfilter/nf_conntrack_h323_main.c
nf_conntrack_h323: fix module unload crash
[karo-tx-linux.git] / net / netfilter / nf_conntrack_h323_main.c
index f23fd9598e199d3b6be8cada071222db7b6a61ee..ea48f71845145286805de0fdb5255b30ee92678e 100644 (file)
@@ -50,12 +50,12 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
 int (*set_h245_addr_hook) (struct sk_buff *skb,
                           unsigned char **data, int dataoff,
                           H245_TransportAddress *taddr,
-                          union nf_conntrack_address *addr, __be16 port)
+                          union nf_inet_addr *addr, __be16 port)
                           __read_mostly;
 int (*set_h225_addr_hook) (struct sk_buff *skb,
                           unsigned char **data, int dataoff,
                           TransportAddress *taddr,
-                          union nf_conntrack_address *addr, __be16 port)
+                          union nf_inet_addr *addr, __be16 port)
                           __read_mostly;
 int (*set_sig_addr_hook) (struct sk_buff *skb,
                          struct nf_conn *ct,
@@ -114,7 +114,8 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
 {
        struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
        int dir = CTINFO2DIR(ctinfo);
-       struct tcphdr _tcph, *th;
+       const struct tcphdr *th;
+       struct tcphdr _tcph;
        int tcpdatalen;
        int tcpdataoff;
        unsigned char *tpkt;
@@ -212,11 +213,11 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
 }
 
 /****************************************************************************/
-static int get_h245_addr(struct nf_conn *ct, unsigned char *data,
+static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
                         H245_TransportAddress *taddr,
-                        union nf_conntrack_address *addr, __be16 *port)
+                        union nf_inet_addr *addr, __be16 *port)
 {
-       unsigned char *p;
+       const unsigned char *p;
        int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
        int len;
 
@@ -257,7 +258,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
        int ret = 0;
        __be16 port;
        __be16 rtp_port, rtcp_port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *rtp_exp;
        struct nf_conntrack_expect *rtcp_exp;
        typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
@@ -330,7 +331,7 @@ static int expect_t120(struct sk_buff *skb,
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
        typeof(nat_t120_hook) nat_t120;
 
@@ -616,6 +617,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
        .me                     = THIS_MODULE,
        .max_expected           = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
        .timeout                = 240,
+       .tuple.src.l3num        = AF_UNSPEC,
        .tuple.dst.protonum     = IPPROTO_UDP,
        .help                   = h245_help
 };
@@ -623,9 +625,9 @@ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
 /****************************************************************************/
 int get_h225_addr(struct nf_conn *ct, unsigned char *data,
                  TransportAddress *taddr,
-                 union nf_conntrack_address *addr, __be16 *port)
+                 union nf_inet_addr *addr, __be16 *port)
 {
-       unsigned char *p;
+       const unsigned char *p;
        int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
        int len;
 
@@ -662,7 +664,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
        typeof(nat_h245_hook) nat_h245;
 
@@ -704,13 +706,18 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
 
 /* If the calling party is on the same side of the forward-to party,
  * we don't need to track the second call */
-static int callforward_do_filter(union nf_conntrack_address *src,
-                                union nf_conntrack_address *dst,
-                                int family)
+static int callforward_do_filter(const union nf_inet_addr *src,
+                                 const union nf_inet_addr *dst, int family)
 {
+       const struct nf_afinfo *afinfo;
        struct flowi fl1, fl2;
        int ret = 0;
 
+       /* rcu_read_lock()ed by nf_hook_slow() */
+       afinfo = nf_get_afinfo(family);
+       if (!afinfo)
+               return 0;
+
        memset(&fl1, 0, sizeof(fl1));
        memset(&fl2, 0, sizeof(fl2));
 
@@ -720,8 +727,8 @@ static int callforward_do_filter(union nf_conntrack_address *src,
 
                fl1.fl4_dst = src->ip;
                fl2.fl4_dst = dst->ip;
-               if (ip_route_output_key(&rt1, &fl1) == 0) {
-                       if (ip_route_output_key(&rt2, &fl2) == 0) {
+               if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) {
+                       if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) {
                                if (rt1->rt_gateway == rt2->rt_gateway &&
                                    rt1->u.dst.dev  == rt2->u.dst.dev)
                                        ret = 1;
@@ -731,16 +738,15 @@ static int callforward_do_filter(union nf_conntrack_address *src,
                }
                break;
        }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if defined(CONFIG_NF_CONNTRACK_IPV6) || \
+    defined(CONFIG_NF_CONNTRACK_IPV6_MODULE)
        case AF_INET6: {
                struct rt6_info *rt1, *rt2;
 
                memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst));
                memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst));
-               rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1);
-               if (rt1) {
-                       rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2);
-                       if (rt2) {
+               if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) {
+                       if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) {
                                if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
                                            sizeof(rt1->rt6i_gateway)) &&
                                    rt1->u.dst.dev == rt2->u.dst.dev)
@@ -767,7 +773,7 @@ static int expect_callforwarding(struct sk_buff *skb,
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
        typeof(nat_callforwarding_hook) nat_callforwarding;
 
@@ -823,7 +829,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
        int ret;
        int i;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        typeof(set_h225_addr_hook) set_h225_addr;
 
        pr_debug("nf_ct_q931: Setup\n");
@@ -837,7 +843,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
 
        set_h225_addr = rcu_dereference(set_h225_addr_hook);
        if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
-           (set_h225_addr) && ct->status && IPS_NAT_MASK &&
+           (set_h225_addr) && ct->status & IPS_NAT_MASK &&
            get_h225_addr(ct, *data, &setup->destCallSignalAddress,
                          &addr, &port) &&
            memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
@@ -1180,7 +1186,8 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
 static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff,
                                   int *datalen)
 {
-       struct udphdr _uh, *uh;
+       const struct udphdr *uh;
+       struct udphdr _uh;
        int dataoff;
 
        uh = skb_header_pointer(skb, protoff, sizeof(_uh), &_uh);
@@ -1195,7 +1202,7 @@ static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff,
 
 /****************************************************************************/
 static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
-                                              union nf_conntrack_address *addr,
+                                              union nf_inet_addr *addr,
                                               __be16 port)
 {
        struct nf_conntrack_expect *exp;
@@ -1237,7 +1244,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
        int ret = 0;
        int i;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
        typeof(nat_q931_hook) nat_q931;
 
@@ -1306,7 +1313,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
 
        pr_debug("nf_ct_ras: GCF\n");
@@ -1410,7 +1417,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
                nf_ct_refresh(ct, skb, info->timeout * HZ);
 
                /* Set expect timeout */
-               read_lock_bh(&nf_conntrack_lock);
+               spin_lock_bh(&nf_conntrack_lock);
                exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
                                  info->sig_port[!dir]);
                if (exp) {
@@ -1420,7 +1427,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
                        NF_CT_DUMP_TUPLE(&exp->tuple);
                        set_expect_timeout(exp, info->timeout);
                }
-               read_unlock_bh(&nf_conntrack_lock);
+               spin_unlock_bh(&nf_conntrack_lock);
        }
 
        return 0;
@@ -1463,10 +1470,10 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
                       enum ip_conntrack_info ctinfo,
                       unsigned char **data, AdmissionRequest *arq)
 {
-       struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
+       const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
        int dir = CTINFO2DIR(ctinfo);
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        typeof(set_h225_addr_hook) set_h225_addr;
 
        pr_debug("nf_ct_ras: ARQ\n");
@@ -1508,7 +1515,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
        typeof(set_sig_addr_hook) set_sig_addr;
 
@@ -1571,7 +1578,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
        __be16 port;
-       union nf_conntrack_address addr;
+       union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
 
        pr_debug("nf_ct_ras: LCF\n");
@@ -1752,6 +1759,7 @@ static void __exit nf_conntrack_h323_fini(void)
        nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
        nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
        nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
+       nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
        kfree(h323_buffer);
        pr_debug("nf_ct_h323: fini\n");
 }
@@ -1764,27 +1772,32 @@ static int __init nf_conntrack_h323_init(void)
        h323_buffer = kmalloc(65536, GFP_KERNEL);
        if (!h323_buffer)
                return -ENOMEM;
-       ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]);
+       ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245);
        if (ret < 0)
                goto err1;
-       ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]);
+       ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]);
        if (ret < 0)
                goto err2;
-       ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]);
+       ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]);
        if (ret < 0)
                goto err3;
-       ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
+       ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]);
        if (ret < 0)
                goto err4;
+       ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
+       if (ret < 0)
+               goto err5;
        pr_debug("nf_ct_h323: init success\n");
        return 0;
 
-err4:
+err5:
        nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
-err3:
+err4:
        nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
-err2:
+err3:
        nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
+err2:
+       nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
 err1:
        return ret;
 }