diff options
author | David S. Miller <davem@davemloft.net> | 2012-06-15 17:54:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-15 17:54:11 -0400 |
commit | 81aded24675ebda5de8a68843250ad15584ac38a (patch) | |
tree | 84f7bd5cf86cf010394de92efd5e4c5b636b3d20 /net/ipv6/icmp.c | |
parent | 36393395536064e483b73d173f6afc103eadfbc4 (diff) |
ipv6: Handle PMTU in ICMP error handlers.
One tricky issue on the ipv6 side vs. ipv4 is that the ICMP callouts
to handle the error pass the 32-bit info cookie in network byte order
whereas ipv4 passes it around in host byte order.
Like the ipv4 side, we have two helper functions. One for when we
have a socket context and one for when we do not.
ip6ip6 tunnels are not handled here, because they handle PMTU events
by essentially relaying another ICMP packet-too-big message back to
the original sender.
This patch allows us to get rid of rt6_do_pmtu_disc(). It handles all
kinds of situations that simply cannot happen when we do the PMTU
update directly using a fully resolved route.
In fact, the "plen == 128" check in ip6_rt_update_pmtu() can very
likely be removed or changed into a BUG_ON() check. We should never
have a prefixed ipv6 route when we get there.
Another piece of strange history here is that TCP and DCCP, unlike in
ipv4, never invoke the update_pmtu() method from their ICMP error
handlers. This is incredibly astonishing since this is the context
where we have the most accurate context in which to make a PMTU
update, namely we have a fully connected socket and associated cached
socket route.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r-- | net/ipv6/icmp.c | 6 |
1 files changed, 1 insertions, 5 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index ed89bba745a1..5247d5c211f9 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -649,7 +649,6 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
649 | struct net_device *dev = skb->dev; | 649 | struct net_device *dev = skb->dev; |
650 | struct inet6_dev *idev = __in6_dev_get(dev); | 650 | struct inet6_dev *idev = __in6_dev_get(dev); |
651 | const struct in6_addr *saddr, *daddr; | 651 | const struct in6_addr *saddr, *daddr; |
652 | const struct ipv6hdr *orig_hdr; | ||
653 | struct icmp6hdr *hdr; | 652 | struct icmp6hdr *hdr; |
654 | u8 type; | 653 | u8 type; |
655 | 654 | ||
@@ -661,7 +660,7 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
661 | XFRM_STATE_ICMP)) | 660 | XFRM_STATE_ICMP)) |
662 | goto drop_no_count; | 661 | goto drop_no_count; |
663 | 662 | ||
664 | if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(*orig_hdr))) | 663 | if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(struct ipv6hdr))) |
665 | goto drop_no_count; | 664 | goto drop_no_count; |
666 | 665 | ||
667 | nh = skb_network_offset(skb); | 666 | nh = skb_network_offset(skb); |
@@ -722,9 +721,6 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
722 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 721 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
723 | goto discard_it; | 722 | goto discard_it; |
724 | hdr = icmp6_hdr(skb); | 723 | hdr = icmp6_hdr(skb); |
725 | orig_hdr = (struct ipv6hdr *) (hdr + 1); | ||
726 | rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, | ||
727 | ntohl(hdr->icmp6_mtu)); | ||
728 | 724 | ||
729 | /* | 725 | /* |
730 | * Drop through to notify | 726 | * Drop through to notify |