net: ipv6: Add IPv6 support to the ping socket.
[pandora-kernel.git] / net / ipv6 / icmp.c
index b4ff0a4..1d2902e 100644 (file)
@@ -57,6 +57,7 @@
 
 #include <net/ipv6.h>
 #include <net/ip6_checksum.h>
+#include <net/ping.h>
 #include <net/protocol.h>
 #include <net/raw.h>
 #include <net/rawv6.h>
@@ -84,12 +85,18 @@ static inline struct sock *icmpv6_sk(struct net *net)
 static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                       u8 type, u8 code, int offset, __be32 info)
 {
+       /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */
+       struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset);
        struct net *net = dev_net(skb->dev);
 
        if (type == ICMPV6_PKT_TOOBIG)
                ip6_update_pmtu(skb, net, info, 0, 0);
        else if (type == NDISC_REDIRECT)
                ip6_redirect(skb, net, 0, 0);
+
+       if (!(type & ICMPV6_INFOMSG_MASK))
+               if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
+                       ping_err(skb, offset, info);
 }
 
 static int icmpv6_rcv(struct sk_buff *skb);
@@ -224,7 +231,8 @@ static bool opt_unrec(struct sk_buff *skb, __u32 offset)
        return (*op & 0xC0) == 0x80;
 }
 
-static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len)
+int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
+                              struct icmp6hdr *thdr, int len)
 {
        struct sk_buff *skb;
        struct icmp6hdr *icmp6h;
@@ -307,8 +315,8 @@ static void mip6_addr_swap(struct sk_buff *skb)
 static inline void mip6_addr_swap(struct sk_buff *skb) {}
 #endif
 
-static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
-                                            struct sock *sk, struct flowi6 *fl6)
+struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
+                                     struct sock *sk, struct flowi6 *fl6)
 {
        struct dst_entry *dst, *dst2;
        struct flowi6 fl2;
@@ -697,7 +705,8 @@ static int icmpv6_rcv(struct sk_buff *skb)
                skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
                                             IPPROTO_ICMPV6, 0));
                if (__skb_checksum_complete(skb)) {
-                       LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n",
+                       LIMIT_NETDEBUG(KERN_DEBUG
+                                      "ICMPv6 checksum failed [%pI6c > %pI6c]\n",
                                       saddr, daddr);
                        goto csum_error;
                }
@@ -718,7 +727,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
                break;
 
        case ICMPV6_ECHO_REPLY:
-               /* we couldn't care less */
+               ping_rcv(skb);
                break;
 
        case ICMPV6_PKT_TOOBIG: