mac80211: fix modprobe deadlock by not calling wep_init under rtnl_lock
[safe/jmp/linux-2.6] / net / ipv4 / udp.c
index b7faffe..7a1d1ce 100644 (file)
@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                return -EOPNOTSUPP;
 
        ipc.opt = NULL;
+       ipc.shtx.flags = 0;
 
        if (up->pending) {
                /*
@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        ipc.addr = inet->saddr;
 
        ipc.oif = sk->sk_bound_dev_if;
+       err = sock_tx_timestamp(msg, sk, &ipc.shtx);
+       if (err)
+               return err;
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sock_net(sk), msg, &ipc);
                if (err)
@@ -1015,9 +1019,11 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
        if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) {
                /* Note that an ENOMEM error is charged twice */
-               if (rc == -ENOMEM)
+               if (rc == -ENOMEM) {
                        UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS,
                                         is_udplite);
+                       atomic_inc(&sk->sk_drops);
+               }
                goto drop;
        }
 
@@ -1178,7 +1184,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
                        sk = sknext;
                } while (sknext);
        } else
-               kfree_skb(skb);
+               consume_skb(skb);
        spin_unlock(&hslot->lock);
        return 0;
 }
@@ -1229,11 +1235,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
                   int proto)
 {
        struct sock *sk;
-       struct udphdr *uh = udp_hdr(skb);
+       struct udphdr *uh;
        unsigned short ulen;
        struct rtable *rt = (struct rtable*)skb->dst;
-       __be32 saddr = ip_hdr(skb)->saddr;
-       __be32 daddr = ip_hdr(skb)->daddr;
+       __be32 saddr, daddr;
        struct net *net = dev_net(skb->dev);
 
        /*
@@ -1242,6 +1247,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
        if (!pskb_may_pull(skb, sizeof(struct udphdr)))
                goto drop;              /* No space for header. */
 
+       uh   = udp_hdr(skb);
        ulen = ntohs(uh->len);
        if (ulen > skb->len)
                goto short_packet;
@@ -1256,6 +1262,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
        if (udp4_csum_init(skb, uh, proto))
                goto csum_error;
 
+       saddr = ip_hdr(skb)->saddr;
+       daddr = ip_hdr(skb)->daddr;
+
        if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
                return __udp4_lib_mcast_deliver(net, skb, uh,
                                saddr, daddr, udptable);
@@ -1609,7 +1618,8 @@ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
        } while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family));
 
        if (!sk) {
-               spin_unlock_bh(&state->udp_table->hash[state->bucket].lock);
+               if (state->bucket < UDP_HTABLE_SIZE)
+                       spin_unlock_bh(&state->udp_table->hash[state->bucket].lock);
                return udp_get_first(seq, state->bucket + 1);
        }
        return sk;
@@ -1627,6 +1637,9 @@ static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos)
 
 static void *udp_seq_start(struct seq_file *seq, loff_t *pos)
 {
+       struct udp_iter_state *state = seq->private;
+       state->bucket = UDP_HTABLE_SIZE;
+
        return *pos ? udp_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
 }