ipv6: stop sending PTB packets for MTU < 1280
[pandora-kernel.git] / net / ipv6 / udp.c
index 8c25419..d131a95 100644 (file)
@@ -347,14 +347,11 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        int is_udp4;
        bool slow;
 
-       if (addr_len)
-               *addr_len=sizeof(struct sockaddr_in6);
-
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-               return ipv6_recv_rxpmtu(sk, msg, len);
+               return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -423,7 +420,7 @@ try_again:
                        if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
                                sin6->sin6_scope_id = IP6CB(skb)->iif;
                }
-
+               *addr_len = sizeof(*sin6);
        }
        if (is_udp4) {
                if (inet->cmsg_flags)
@@ -893,11 +890,16 @@ static int udp_v6_push_pending_frames(struct sock *sk)
        struct udphdr *uh;
        struct udp_sock  *up = udp_sk(sk);
        struct inet_sock *inet = inet_sk(sk);
-       struct flowi6 *fl6 = &inet->cork.fl.u.ip6;
+       struct flowi6 *fl6;
        int err = 0;
        int is_udplite = IS_UDPLITE(sk);
        __wsum csum = 0;
 
+       if (up->pending == AF_INET)
+               return udp_push_pending_frames(sk);
+
+       fl6 = &inet->cork.fl.u.ip6;
+
        /* Grab the skbuff where UDP header space exists. */
        if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
                goto out;
@@ -1360,7 +1362,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features)
        fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
        fptr->nexthdr = nexthdr;
        fptr->reserved = 0;
-       ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
+       fptr->identification = skb_shinfo(skb)->ip6_frag_id;
 
        /* Fragment the skb. ipv6 header and the remaining fields of the
         * fragment header are updated in ipv6_gso_segment()
@@ -1453,6 +1455,17 @@ void udp6_proc_exit(struct net *net) {
 }
 #endif /* CONFIG_PROC_FS */
 
+void udp_v6_clear_sk(struct sock *sk, int size)
+{
+       struct inet_sock *inet = inet_sk(sk);
+
+       /* we do not want to clear pinet6 field, because of RCU lookups */
+       sk_prot_clear_portaddr_nulls(sk, offsetof(struct inet_sock, pinet6));
+
+       size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6);
+       memset(&inet->pinet6 + 1, 0, size);
+}
+
 /* ------------------------------------------------------------------------ */
 
 struct proto udpv6_prot = {
@@ -1483,7 +1496,7 @@ struct proto udpv6_prot = {
        .compat_setsockopt = compat_udpv6_setsockopt,
        .compat_getsockopt = compat_udpv6_getsockopt,
 #endif
-       .clear_sk          = sk_prot_clear_portaddr_nulls,
+       .clear_sk          = udp_v6_clear_sk,
 };
 
 static struct inet_protosw udpv6_protosw = {