]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/ip6_output.c
Merge branch 'master' of /repos/git/net-next-2.6
[net-next-2.6.git] / net / ipv6 / ip6_output.c
index 7f12e30cfa73272256b80a412f69b72747915152..5173acaeb5015e2bc0722e43c8a09d5d96d55190 100644 (file)
@@ -92,7 +92,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
        newskb->ip_summed = CHECKSUM_UNNECESSARY;
        WARN_ON(!skb_dst(newskb));
 
-       netif_rx(newskb);
+       netif_rx_ni(newskb);
        return 0;
 }
 
@@ -216,8 +216,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
                        }
                        kfree_skb(skb);
                        skb = skb2;
-                       if (sk)
-                               skb_set_owner_w(skb, sk);
+                       skb_set_owner_w(skb, sk);
                }
                if (opt->opt_flen)
                        ipv6_push_frag_opts(skb, opt, &proto);
@@ -623,7 +622,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
        /* We must not fragment if the socket is set to force MTU discovery
         * or if the skb it not generated by a local socket.
         */
-       if (!skb->local_df) {
+       if (!skb->local_df && skb->len > mtu) {
                skb->dev = skb_dst(skb)->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
@@ -1103,7 +1102,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
        int offset, int len, int odd, struct sk_buff *skb),
        void *from, int length, int transhdrlen,
        int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
-       struct rt6_info *rt, unsigned int flags)
+       struct rt6_info *rt, unsigned int flags, int dontfrag)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
@@ -1217,15 +1216,23 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
         */
 
        inet->cork.length += length;
-       if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
-           (rt->u.dst.dev->features & NETIF_F_UFO)) {
+       if (length > mtu) {
+               int proto = sk->sk_protocol;
+               if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
+                       ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen);
+                       return -EMSGSIZE;
+               }
 
-               err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len,
-                                         fragheaderlen, transhdrlen, mtu,
-                                         flags);
-               if (err)
-                       goto error;
-               return 0;
+               if (proto == IPPROTO_UDP &&
+                   (rt->u.dst.dev->features & NETIF_F_UFO)) {
+
+                       err = ip6_ufo_append_data(sk, getfrag, from, length,
+                                                 hh_len, fragheaderlen,
+                                                 transhdrlen, mtu, flags);
+                       if (err)
+                               goto error;
+                       return 0;
+               }
        }
 
        if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)