aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r--net/ipv6/icmp.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index b4ff0a42b8c7..1d2902e61786 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -57,6 +57,7 @@
57 57
58#include <net/ipv6.h> 58#include <net/ipv6.h>
59#include <net/ip6_checksum.h> 59#include <net/ip6_checksum.h>
60#include <net/ping.h>
60#include <net/protocol.h> 61#include <net/protocol.h>
61#include <net/raw.h> 62#include <net/raw.h>
62#include <net/rawv6.h> 63#include <net/rawv6.h>
@@ -84,12 +85,18 @@ static inline struct sock *icmpv6_sk(struct net *net)
84static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 85static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
85 u8 type, u8 code, int offset, __be32 info) 86 u8 type, u8 code, int offset, __be32 info)
86{ 87{
88 /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */
89 struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset);
87 struct net *net = dev_net(skb->dev); 90 struct net *net = dev_net(skb->dev);
88 91
89 if (type == ICMPV6_PKT_TOOBIG) 92 if (type == ICMPV6_PKT_TOOBIG)
90 ip6_update_pmtu(skb, net, info, 0, 0); 93 ip6_update_pmtu(skb, net, info, 0, 0);
91 else if (type == NDISC_REDIRECT) 94 else if (type == NDISC_REDIRECT)
92 ip6_redirect(skb, net, 0, 0); 95 ip6_redirect(skb, net, 0, 0);
96
97 if (!(type & ICMPV6_INFOMSG_MASK))
98 if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
99 ping_err(skb, offset, info);
93} 100}
94 101
95static int icmpv6_rcv(struct sk_buff *skb); 102static int icmpv6_rcv(struct sk_buff *skb);
@@ -224,7 +231,8 @@ static bool opt_unrec(struct sk_buff *skb, __u32 offset)
224 return (*op & 0xC0) == 0x80; 231 return (*op & 0xC0) == 0x80;
225} 232}
226 233
227static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) 234int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
235 struct icmp6hdr *thdr, int len)
228{ 236{
229 struct sk_buff *skb; 237 struct sk_buff *skb;
230 struct icmp6hdr *icmp6h; 238 struct icmp6hdr *icmp6h;
@@ -307,8 +315,8 @@ static void mip6_addr_swap(struct sk_buff *skb)
307static inline void mip6_addr_swap(struct sk_buff *skb) {} 315static inline void mip6_addr_swap(struct sk_buff *skb) {}
308#endif 316#endif
309 317
310static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, 318struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
311 struct sock *sk, struct flowi6 *fl6) 319 struct sock *sk, struct flowi6 *fl6)
312{ 320{
313 struct dst_entry *dst, *dst2; 321 struct dst_entry *dst, *dst2;
314 struct flowi6 fl2; 322 struct flowi6 fl2;
@@ -697,7 +705,8 @@ static int icmpv6_rcv(struct sk_buff *skb)
697 skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, 705 skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
698 IPPROTO_ICMPV6, 0)); 706 IPPROTO_ICMPV6, 0));
699 if (__skb_checksum_complete(skb)) { 707 if (__skb_checksum_complete(skb)) {
700 LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", 708 LIMIT_NETDEBUG(KERN_DEBUG
709 "ICMPv6 checksum failed [%pI6c > %pI6c]\n",
701 saddr, daddr); 710 saddr, daddr);
702 goto csum_error; 711 goto csum_error;
703 } 712 }
@@ -718,7 +727,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
718 break; 727 break;
719 728
720 case ICMPV6_ECHO_REPLY: 729 case ICMPV6_ECHO_REPLY:
721 /* we couldn't care less */ 730 ping_rcv(skb);
722 break; 731 break;
723 732
724 case ICMPV6_PKT_TOOBIG: 733 case ICMPV6_PKT_TOOBIG: