aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /net/ipv6/ip6_output.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (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.c29
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);