icmp: prevent stripping off ipv4 header twice on darwin

We cannot use net.ReadFrom on darwin because a) net.ReadFrom and
net.ReadFromIP unconditionally try to strip off ipv4 header due to
and c) icmp.ListenPacket calls ipv4.PacketConn internally.

Instead, we use ipv4.PacketConn.ReadFrom that calls net.ReadMsgIP
internally to prevent icmp.ReadFrom from returning corrupted ICMP
message.

Fixes #9395.

Change-Id: I269f3724de72bf37eb26921c251c2acb1c720fa3
diff --git a/icmp/endpoint.go b/icmp/endpoint.go
index 5bf2cfe..3de49e6 100644
--- a/icmp/endpoint.go
+++ b/icmp/endpoint.go
@@ -6,6 +6,7 @@
 
 import (
 	"net"
+	"runtime"
 	"syscall"
 	"time"
 
@@ -51,6 +52,15 @@
 	if !c.ok() {
 		return 0, nil, syscall.EINVAL
 	}
+	// Please be informed that ipv4.NewPacketConn enables
+	// IP_STRIPHDR option by default on Darwin.
+	// See golang.org/issue/9395 for futher information.
+	if runtime.GOOS == "darwin" {
+		if p, _ := c.ipc.(*ipv4.PacketConn); p != nil {
+			n, _, peer, err := p.ReadFrom(b)
+			return n, peer, err
+		}
+	}
 	return c.c.ReadFrom(b)
 }