diff options
Diffstat (limited to 'net/ipv4/icmp.c')
-rw-r--r-- | net/ipv4/icmp.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 5c0e8bc6e5ba..0134663fdbce 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -668,6 +668,16 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) | |||
668 | rcu_read_unlock(); | 668 | rcu_read_unlock(); |
669 | } | 669 | } |
670 | 670 | ||
671 | static bool icmp_tag_validation(int proto) | ||
672 | { | ||
673 | bool ok; | ||
674 | |||
675 | rcu_read_lock(); | ||
676 | ok = rcu_dereference(inet_protos[proto])->icmp_strict_tag_validation; | ||
677 | rcu_read_unlock(); | ||
678 | return ok; | ||
679 | } | ||
680 | |||
671 | /* | 681 | /* |
672 | * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and | 682 | * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and |
673 | * ICMP_PARAMETERPROB. | 683 | * ICMP_PARAMETERPROB. |
@@ -705,10 +715,22 @@ static void icmp_unreach(struct sk_buff *skb) | |||
705 | case ICMP_PORT_UNREACH: | 715 | case ICMP_PORT_UNREACH: |
706 | break; | 716 | break; |
707 | case ICMP_FRAG_NEEDED: | 717 | case ICMP_FRAG_NEEDED: |
708 | if (ipv4_config.no_pmtu_disc) { | 718 | /* for documentation of the ip_no_pmtu_disc |
719 | * values please see | ||
720 | * Documentation/networking/ip-sysctl.txt | ||
721 | */ | ||
722 | switch (net->ipv4.sysctl_ip_no_pmtu_disc) { | ||
723 | default: | ||
709 | LIMIT_NETDEBUG(KERN_INFO pr_fmt("%pI4: fragmentation needed and DF set\n"), | 724 | LIMIT_NETDEBUG(KERN_INFO pr_fmt("%pI4: fragmentation needed and DF set\n"), |
710 | &iph->daddr); | 725 | &iph->daddr); |
711 | } else { | 726 | break; |
727 | case 2: | ||
728 | goto out; | ||
729 | case 3: | ||
730 | if (!icmp_tag_validation(iph->protocol)) | ||
731 | goto out; | ||
732 | /* fall through */ | ||
733 | case 0: | ||
712 | info = ntohs(icmph->un.frag.mtu); | 734 | info = ntohs(icmph->un.frag.mtu); |
713 | if (!info) | 735 | if (!info) |
714 | goto out; | 736 | goto out; |