]> err.no Git - linux-2.6/blobdiff - net/netlink/af_netlink.c
Merge /spare/repo/linux-2.6/
[linux-2.6] / net / netlink / af_netlink.c
index 733bf52cef3e72c663a9f4bc7f90cecab421c706..70bcd4744d9370e44f0389f28754df5aaaa3bee6 100644 (file)
@@ -735,11 +735,15 @@ static inline int do_one_broadcast(struct sock *sk,
 
        sock_hold(sk);
        if (p->skb2 == NULL) {
-               if (atomic_read(&p->skb->users) != 1) {
+               if (skb_shared(p->skb)) {
                        p->skb2 = skb_clone(p->skb, p->allocation);
                } else {
-                       p->skb2 = p->skb;
-                       atomic_inc(&p->skb->users);
+                       p->skb2 = skb_get(p->skb);
+                       /*
+                        * skb ownership may have been set when
+                        * delivered to a previous socket.
+                        */
+                       skb_orphan(p->skb2);
                }
        }
        if (p->skb2 == NULL) {
@@ -785,11 +789,12 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
        sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
                do_one_broadcast(sk, &info);
 
+       kfree_skb(skb);
+
        netlink_unlock_table();
 
        if (info.skb2)
                kfree_skb(info.skb2);
-       kfree_skb(skb);
 
        if (info.delivered) {
                if (info.congested && (allocation & __GFP_WAIT))
@@ -1090,8 +1095,7 @@ static int netlink_dump(struct sock *sk)
                return 0;
        }
 
-       nlh = __nlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLMSG_DONE, sizeof(int));
-       nlh->nlmsg_flags |= NLM_F_MULTI;
+       nlh = NLMSG_NEW_ANSWER(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
        memcpy(NLMSG_DATA(nlh), &len, sizeof(len));
        skb_queue_tail(&sk->sk_receive_queue, skb);
        sk->sk_data_ready(sk, skb->len);
@@ -1102,6 +1106,9 @@ static int netlink_dump(struct sock *sk)
 
        netlink_destroy_callback(cb);
        return 0;
+
+nlmsg_failure:
+       return -ENOBUFS;
 }
 
 int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
@@ -1173,7 +1180,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
        }
 
        rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
-                         NLMSG_ERROR, sizeof(struct nlmsgerr));
+                         NLMSG_ERROR, sizeof(struct nlmsgerr), 0);
        errmsg = NLMSG_DATA(rep);
        errmsg->error = err;
        memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr));