]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/netlink/af_netlink.c
Merge branch 'master' of ../net-2.6/
[linux-2.6-omap-h63xx.git] / net / netlink / af_netlink.c
index 1ab0da2632e19c5a0a74546a67a3e9c4d11bbc50..86bd8660a8f2789c5e1ec83c1f66c1b8c9131bd4 100644 (file)
@@ -886,6 +886,13 @@ retry:
        if (netlink_is_kernel(sk))
                return netlink_unicast_kernel(sk, skb);
 
+       if (sk_filter(sk, skb)) {
+               int err = skb->len;
+               kfree_skb(skb);
+               sock_put(sk);
+               return err;
+       }
+
        err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
        if (err == 1)
                goto retry;
@@ -980,6 +987,9 @@ static inline int do_one_broadcast(struct sock *sk,
                netlink_overrun(sk);
                /* Clone failed. Notify ALL listeners. */
                p->failure = 1;
+       } else if (sk_filter(sk, p->skb2)) {
+               kfree_skb(p->skb2);
+               p->skb2 = NULL;
        } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
                netlink_overrun(sk);
        } else {
@@ -1344,22 +1354,6 @@ static void netlink_data_ready(struct sock *sk, int len)
  *     queueing.
  */
 
-static void __netlink_release(struct sock *sk)
-{
-       /*
-        * Last sock_put should drop referrence to sk->sk_net. It has already
-        * been dropped in netlink_kernel_create. Taking referrence to stopping
-        * namespace is not an option.
-        * Take referrence to a socket to remove it from netlink lookup table
-        * _alive_ and after that destroy it in the context of init_net.
-        */
-
-       sock_hold(sk);
-       sock_release(sk->sk_socket);
-       sk->sk_net = get_net(&init_net);
-       sock_put(sk);
-}
-
 struct sock *
 netlink_kernel_create(struct net *net, int unit, unsigned int groups,
                      void (*input)(struct sk_buff *skb),
@@ -1388,8 +1382,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
                goto out_sock_release_nosk;
 
        sk = sock->sk;
-       put_net(sk->sk_net);
-       sk->sk_net = net;
+       sk_change_net(sk, net);
 
        if (groups < 32)
                groups = 32;
@@ -1424,7 +1417,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
 
 out_sock_release:
        kfree(listeners);
-       __netlink_release(sk);
+       netlink_kernel_release(sk);
        return NULL;
 
 out_sock_release_nosk:
@@ -1437,10 +1430,7 @@ EXPORT_SYMBOL(netlink_kernel_create);
 void
 netlink_kernel_release(struct sock *sk)
 {
-       if (sk == NULL || sk->sk_socket == NULL)
-               return;
-
-       __netlink_release(sk);
+       sk_release_kernel(sk);
 }
 EXPORT_SYMBOL(netlink_kernel_release);
 
@@ -1553,8 +1543,13 @@ static int netlink_dump(struct sock *sk)
 
        if (len > 0) {
                mutex_unlock(nlk->cb_mutex);
-               skb_queue_tail(&sk->sk_receive_queue, skb);
-               sk->sk_data_ready(sk, len);
+
+               if (sk_filter(sk, skb))
+                       kfree_skb(skb);
+               else {
+                       skb_queue_tail(&sk->sk_receive_queue, skb);
+                       sk->sk_data_ready(sk, skb->len);
+               }
                return 0;
        }
 
@@ -1564,8 +1559,12 @@ static int netlink_dump(struct sock *sk)
 
        memcpy(nlmsg_data(nlh), &len, sizeof(len));
 
-       skb_queue_tail(&sk->sk_receive_queue, skb);
-       sk->sk_data_ready(sk, skb->len);
+       if (sk_filter(sk, skb))
+               kfree_skb(skb);
+       else {
+               skb_queue_tail(&sk->sk_receive_queue, skb);
+               sk->sk_data_ready(sk, skb->len);
+       }
 
        if (cb->done)
                cb->done(cb);