Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[powerpc.git] / net / ipv4 / udp.c
index aa18230..9e1bd37 100644 (file)
@@ -139,7 +139,7 @@ static inline int udp_lport_inuse(u16 num)
  *  @saddr_comp:  AF-dependent comparison of bound local IP addresses
  */
 int udp_get_port(struct sock *sk, unsigned short snum,
-                int (*saddr_cmp)(struct sock *sk1, struct sock *sk2))
+                int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2))
 {
        struct hlist_node *node;
        struct hlist_head *head;
@@ -210,7 +210,7 @@ fail:
        return error;
 }
 
-static inline int  ipv4_rcv_saddr_equal(struct sock *sk1, struct sock *sk2)
+static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
 {
        struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
 
@@ -243,8 +243,8 @@ static void udp_v4_unhash(struct sock *sk)
 /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
  * harder than this. -DaveM
  */
-static struct sock *udp_v4_lookup_longway(u32 saddr, u16 sport,
-                                         u32 daddr, u16 dport, int dif)
+static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport,
+                                         __be32 daddr, __be16 dport, int dif)
 {
        struct sock *sk, *result = NULL;
        struct hlist_node *node;
@@ -288,8 +288,8 @@ static struct sock *udp_v4_lookup_longway(u32 saddr, u16 sport,
        return result;
 }
 
-static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
-                                            u32 daddr, u16 dport, int dif)
+static __inline__ struct sock *udp_v4_lookup(__be32 saddr, __be16 sport,
+                                            __be32 daddr, __be16 dport, int dif)
 {
        struct sock *sk;
 
@@ -302,8 +302,8 @@ static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
 }
 
 static inline struct sock *udp_v4_mcast_next(struct sock *sk,
-                                            u16 loc_port, u32 loc_addr,
-                                            u16 rmt_port, u32 rmt_addr,
+                                            __be16 loc_port, __be32 loc_addr,
+                                            __be16 rmt_port, __be32 rmt_addr,
                                             int dif)
 {
        struct hlist_node *node;
@@ -498,7 +498,7 @@ out:
 }
 
 
-static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
+static unsigned short udp_check(struct udphdr *uh, int len, __be32 saddr, __be32 daddr, unsigned long base)
 {
        return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
 }
@@ -513,8 +513,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct rtable *rt = NULL;
        int free = 0;
        int connected = 0;
-       u32 daddr, faddr, saddr;
-       u16 dport;
+       __be32 daddr, faddr, saddr;
+       __be16 dport;
        u8  tos;
        int err;
        int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
@@ -675,6 +675,8 @@ do_append_data:
                udp_flush_pending_frames(sk);
        else if (!corkreq)
                err = udp_push_pending_frames(sk, up);
+       else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
+               up->pending = 0;
        release_sock(sk);
 
 out:
@@ -926,23 +928,32 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
        return 1; 
 #else
        struct udp_sock *up = udp_sk(sk);
-       struct udphdr *uh = skb->h.uh;
+       struct udphdr *uh;
        struct iphdr *iph;
        int iphlen, len;
   
-       __u8 *udpdata = (__u8 *)uh + sizeof(struct udphdr);
-       __u32 *udpdata32 = (__u32 *)udpdata;
+       __u8 *udpdata;
+       __be32 *udpdata32;
        __u16 encap_type = up->encap_type;
 
        /* if we're overly short, let UDP handle it */
-       if (udpdata > skb->tail)
+       len = skb->len - sizeof(struct udphdr);
+       if (len <= 0)
                return 1;
 
        /* if this is not encapsulated socket, then just return now */
        if (!encap_type)
                return 1;
 
-       len = skb->tail - udpdata;
+       /* If this is a paged skb, make sure we pull up
+        * whatever data we need to look at. */
+       if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
+               return 1;
+
+       /* Now we can get the pointers */
+       uh = skb->h.uh;
+       udpdata = (__u8 *)uh + sizeof(struct udphdr);
+       udpdata32 = (__be32 *)udpdata;
 
        switch (encap_type) {
        default:
@@ -1080,7 +1091,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
  *     so we don't need to lock the hashes.
  */
 static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
-                                u32 saddr, u32 daddr)
+                                __be32 saddr, __be32 daddr)
 {
        struct sock *sk;
        int dif;
@@ -1121,7 +1132,7 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
  * including udp header and folding it to skb->csum.
  */
 static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
-                            unsigned short ulen, u32 saddr, u32 daddr)
+                            unsigned short ulen, __be32 saddr, __be32 daddr)
 {
        if (uh->check == 0) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1146,8 +1157,8 @@ int udp_rcv(struct sk_buff *skb)
        struct udphdr *uh;
        unsigned short ulen;
        struct rtable *rt = (struct rtable*)skb->dst;
-       u32 saddr = skb->nh.iph->saddr;
-       u32 daddr = skb->nh.iph->daddr;
+       __be32 saddr = skb->nh.iph->saddr;
+       __be32 daddr = skb->nh.iph->daddr;
        int len = skb->len;
 
        /*
@@ -1563,8 +1574,8 @@ void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
 static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
 {
        struct inet_sock *inet = inet_sk(sp);
-       unsigned int dest = inet->daddr;
-       unsigned int src  = inet->rcv_saddr;
+       __be32 dest = inet->daddr;
+       __be32 src  = inet->rcv_saddr;
        __u16 destp       = ntohs(inet->dport);
        __u16 srcp        = ntohs(inet->sport);