diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/ipv6/ip6_output.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index cd48801a8d6f..75d5ef830097 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/tcp.h> | 37 | #include <linux/tcp.h> |
38 | #include <linux/route.h> | 38 | #include <linux/route.h> |
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/slab.h> | ||
40 | 41 | ||
41 | #include <linux/netfilter.h> | 42 | #include <linux/netfilter.h> |
42 | #include <linux/netfilter_ipv6.h> | 43 | #include <linux/netfilter_ipv6.h> |
@@ -107,7 +108,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | |||
107 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 108 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
108 | WARN_ON(!skb_dst(newskb)); | 109 | WARN_ON(!skb_dst(newskb)); |
109 | 110 | ||
110 | netif_rx(newskb); | 111 | netif_rx_ni(newskb); |
111 | return 0; | 112 | return 0; |
112 | } | 113 | } |
113 | 114 | ||
@@ -121,10 +122,9 @@ static int ip6_output2(struct sk_buff *skb) | |||
121 | skb->dev = dev; | 122 | skb->dev = dev; |
122 | 123 | ||
123 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { | 124 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { |
124 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; | ||
125 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 125 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
126 | 126 | ||
127 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && | 127 | if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && |
128 | ((mroute6_socket(dev_net(dev)) && | 128 | ((mroute6_socket(dev_net(dev)) && |
129 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || | 129 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || |
130 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, | 130 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
@@ -268,7 +268,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
268 | if (net_ratelimit()) | 268 | if (net_ratelimit()) |
269 | printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); | 269 | printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); |
270 | skb->dev = dst->dev; | 270 | skb->dev = dst->dev; |
271 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); | 271 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
272 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); | 272 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); |
273 | kfree_skb(skb); | 273 | kfree_skb(skb); |
274 | return -EMSGSIZE; | 274 | return -EMSGSIZE; |
@@ -403,6 +403,7 @@ int ip6_forward(struct sk_buff *skb) | |||
403 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 403 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
404 | struct inet6_skb_parm *opt = IP6CB(skb); | 404 | struct inet6_skb_parm *opt = IP6CB(skb); |
405 | struct net *net = dev_net(dst->dev); | 405 | struct net *net = dev_net(dst->dev); |
406 | u32 mtu; | ||
406 | 407 | ||
407 | if (net->ipv6.devconf_all->forwarding == 0) | 408 | if (net->ipv6.devconf_all->forwarding == 0) |
408 | goto error; | 409 | goto error; |
@@ -442,8 +443,7 @@ int ip6_forward(struct sk_buff *skb) | |||
442 | if (hdr->hop_limit <= 1) { | 443 | if (hdr->hop_limit <= 1) { |
443 | /* Force OUTPUT device used as source address */ | 444 | /* Force OUTPUT device used as source address */ |
444 | skb->dev = dst->dev; | 445 | skb->dev = dst->dev; |
445 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, | 446 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0); |
446 | 0, skb->dev); | ||
447 | IP6_INC_STATS_BH(net, | 447 | IP6_INC_STATS_BH(net, |
448 | ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); | 448 | ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); |
449 | 449 | ||
@@ -505,15 +505,19 @@ int ip6_forward(struct sk_buff *skb) | |||
505 | goto error; | 505 | goto error; |
506 | if (addrtype & IPV6_ADDR_LINKLOCAL) { | 506 | if (addrtype & IPV6_ADDR_LINKLOCAL) { |
507 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, | 507 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, |
508 | ICMPV6_NOT_NEIGHBOUR, 0, skb->dev); | 508 | ICMPV6_NOT_NEIGHBOUR, 0); |
509 | goto error; | 509 | goto error; |
510 | } | 510 | } |
511 | } | 511 | } |
512 | 512 | ||
513 | if (skb->len > dst_mtu(dst)) { | 513 | mtu = dst_mtu(dst); |
514 | if (mtu < IPV6_MIN_MTU) | ||
515 | mtu = IPV6_MIN_MTU; | ||
516 | |||
517 | if (skb->len > mtu) { | ||
514 | /* Again, force OUTPUT device used as source address */ | 518 | /* Again, force OUTPUT device used as source address */ |
515 | skb->dev = dst->dev; | 519 | skb->dev = dst->dev; |
516 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); | 520 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
517 | IP6_INC_STATS_BH(net, | 521 | IP6_INC_STATS_BH(net, |
518 | ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); | 522 | ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); |
519 | IP6_INC_STATS_BH(net, | 523 | IP6_INC_STATS_BH(net, |
@@ -623,12 +627,11 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
623 | mtu = ip6_skb_dst_mtu(skb); | 627 | mtu = ip6_skb_dst_mtu(skb); |
624 | 628 | ||
625 | /* We must not fragment if the socket is set to force MTU discovery | 629 | /* We must not fragment if the socket is set to force MTU discovery |
626 | * or if the skb it not generated by a local socket. (This last | 630 | * or if the skb it not generated by a local socket. |
627 | * check should be redundant, but it's free.) | ||
628 | */ | 631 | */ |
629 | if (!skb->local_df) { | 632 | if (!skb->local_df && skb->len > mtu) { |
630 | skb->dev = skb_dst(skb)->dev; | 633 | skb->dev = skb_dst(skb)->dev; |
631 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); | 634 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
632 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 635 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
633 | IPSTATS_MIB_FRAGFAILS); | 636 | IPSTATS_MIB_FRAGFAILS); |
634 | kfree_skb(skb); | 637 | kfree_skb(skb); |