diff options
author | Shan Wei <shanwei@cn.fujitsu.com> | 2010-04-18 12:58:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-22 01:48:26 -0400 |
commit | f2228f785a9d97307aa8ba709088cfda6c3df73f (patch) | |
tree | 3440546af96613f8204221128609bf8054a8e733 | |
parent | a19259c3d589a014e5f47f148f74dfc44422c82b (diff) |
ipv6: allow to send packet after receiving ICMPv6 Too Big message with MTU field less than IPV6_MIN_MTU
According to RFC2460, PMTU is set to the IPv6 Minimum Link
MTU (1280) and a fragment header should always be included
after a node receiving Too Big message reporting PMTU is
less than the IPv6 Minimum Link MTU.
After receiving a ICMPv6 Too Big message reporting PMTU is
less than the IPv6 Minimum Link MTU, sctp *can't* send any
data/control chunk that total length including IPv6 head
and IPv6 extend head is less than IPV6_MIN_MTU(1280 bytes).
The failure occured in p6_fragment(), about reason
see following(take SHUTDOWN chunk for example):
sctp_packet_transmit (SHUTDOWN chunk, len=16 byte)
|------sctp_v6_xmit (local_df=0)
|------ip6_xmit
|------ip6_output (dst_allfrag is ture)
|------ip6_fragment
In ip6_fragment(), for local_df=0, drops the the packet
and returns EMSGSIZE.
The patch fixes it with adding check length of skb->len.
In this case, Ipv6 not to fragment upper protocol data,
just only add a fragment header before it.
Signed-off-by: Shan Wei <shanwei@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/ip6_output.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 65f9c379df38..75d5ef830097 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -629,7 +629,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
629 | /* 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 |
630 | * or if the skb it not generated by a local socket. | 630 | * or if the skb it not generated by a local socket. |
631 | */ | 631 | */ |
632 | if (!skb->local_df) { | 632 | if (!skb->local_df && skb->len > mtu) { |
633 | skb->dev = skb_dst(skb)->dev; | 633 | skb->dev = skb_dst(skb)->dev; |
634 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 634 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
635 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 635 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |