lsm: Relocate the IPv4 security_inet_conn_request() hooks
[safe/jmp/linux-2.6] / net / ipv4 / inet_diag.c
index 605ed2c..588a779 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * inet_diag.c Module for monitoring INET transport protocols sockets.
  *
- * Version:    $Id: inet_diag.c,v 1.3 2002/02/01 22:01:04 davem Exp $
- *
  * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
  *     This program is free software; you can redistribute it and/or
@@ -55,11 +53,9 @@ static DEFINE_MUTEX(inet_diag_table_mutex);
 
 static const struct inet_diag_handler *inet_diag_lock_handler(int type)
 {
-#ifdef CONFIG_KMOD
        if (!inet_diag_table[type])
                request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
                               NETLINK_INET_DIAG, type);
-#endif
 
        mutex_lock(&inet_diag_table_mutex);
        if (!inet_diag_table[type])
@@ -259,20 +255,22 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,
        const struct inet_diag_handler *handler;
 
        handler = inet_diag_lock_handler(nlh->nlmsg_type);
-       if (!handler)
-               return -ENOENT;
+       if (IS_ERR(handler)) {
+               err = PTR_ERR(handler);
+               goto unlock;
+       }
 
        hashinfo = handler->idiag_hashinfo;
        err = -EINVAL;
 
        if (req->idiag_family == AF_INET) {
-               sk = inet_lookup(hashinfo, req->id.idiag_dst[0],
+               sk = inet_lookup(&init_net, hashinfo, req->id.idiag_dst[0],
                                 req->id.idiag_dport, req->id.idiag_src[0],
                                 req->id.idiag_sport, req->id.idiag_if);
        }
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
        else if (req->idiag_family == AF_INET6) {
-               sk = inet6_lookup(hashinfo,
+               sk = inet6_lookup(&init_net, hashinfo,
                                  (struct in6_addr *)req->id.idiag_dst,
                                  req->id.idiag_dport,
                                  (struct in6_addr *)req->id.idiag_src,
@@ -708,8 +706,8 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
        struct inet_hashinfo *hashinfo;
 
        handler = inet_diag_lock_handler(cb->nlh->nlmsg_type);
-       if (!handler)
-               goto no_handler;
+       if (IS_ERR(handler))
+               goto unlock;
 
        hashinfo = handler->idiag_hashinfo;
 
@@ -720,13 +718,15 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
                if (!(r->idiag_states & (TCPF_LISTEN | TCPF_SYN_RECV)))
                        goto skip_listen_ht;
 
-               inet_listen_lock(hashinfo);
                for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
                        struct sock *sk;
-                       struct hlist_node *node;
+                       struct hlist_nulls_node *node;
+                       struct inet_listen_hashbucket *ilb;
 
                        num = 0;
-                       sk_for_each(sk, node, &hashinfo->listening_hash[i]) {
+                       ilb = &hashinfo->listening_hash[i];
+                       spin_lock_bh(&ilb->lock);
+                       sk_nulls_for_each(sk, node, &ilb->head) {
                                struct inet_sock *inet = inet_sk(sk);
 
                                if (num < s_num) {
@@ -744,7 +744,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                        goto syn_recv;
 
                                if (inet_csk_diag_dump(sk, skb, cb) < 0) {
-                                       inet_listen_unlock(hashinfo);
+                                       spin_unlock_bh(&ilb->lock);
                                        goto done;
                                }
 
@@ -753,7 +753,7 @@ syn_recv:
                                        goto next_listen;
 
                                if (inet_diag_dump_reqs(skb, sk, cb) < 0) {
-                                       inet_listen_unlock(hashinfo);
+                                       spin_unlock_bh(&ilb->lock);
                                        goto done;
                                }
 
@@ -762,12 +762,12 @@ next_listen:
                                cb->args[4] = 0;
                                ++num;
                        }
+                       spin_unlock_bh(&ilb->lock);
 
                        s_num = 0;
                        cb->args[3] = 0;
                        cb->args[4] = 0;
                }
-               inet_listen_unlock(hashinfo);
 skip_listen_ht:
                cb->args[0] = 1;
                s_i = num = s_num = 0;
@@ -778,16 +778,21 @@ skip_listen_ht:
 
        for (i = s_i; i < hashinfo->ehash_size; i++) {
                struct inet_ehash_bucket *head = &hashinfo->ehash[i];
-               rwlock_t *lock = inet_ehash_lockp(hashinfo, i);
+               spinlock_t *lock = inet_ehash_lockp(hashinfo, i);
                struct sock *sk;
-               struct hlist_node *node;
+               struct hlist_nulls_node *node;
+
+               num = 0;
+
+               if (hlist_nulls_empty(&head->chain) &&
+                       hlist_nulls_empty(&head->twchain))
+                       continue;
 
                if (i > s_i)
                        s_num = 0;
 
-               read_lock_bh(lock);
-               num = 0;
-               sk_for_each(sk, node, &head->chain) {
+               spin_lock_bh(lock);
+               sk_nulls_for_each(sk, node, &head->chain) {
                        struct inet_sock *inet = inet_sk(sk);
 
                        if (num < s_num)
@@ -801,7 +806,7 @@ skip_listen_ht:
                            r->id.idiag_dport)
                                goto next_normal;
                        if (inet_csk_diag_dump(sk, skb, cb) < 0) {
-                               read_unlock_bh(lock);
+                               spin_unlock_bh(lock);
                                goto done;
                        }
 next_normal:
@@ -823,14 +828,14 @@ next_normal:
                                    r->id.idiag_dport)
                                        goto next_dying;
                                if (inet_twsk_diag_dump(tw, skb, cb) < 0) {
-                                       read_unlock_bh(lock);
+                                       spin_unlock_bh(lock);
                                        goto done;
                                }
 next_dying:
                                ++num;
                        }
                }
-               read_unlock_bh(lock);
+               spin_unlock_bh(lock);
        }
 
 done:
@@ -838,7 +843,6 @@ done:
        cb->args[2] = num;
 unlock:
        inet_diag_unlock_handler(handler);
-no_handler:
        return skb->len;
 }