Я пытаюсь реализовать небольшую утилиту traceroute как часть кроссплатформенного проекта.Но я обнаружил, что в Windows Go не видит сообщений превышения TTL в необработанном сокете icmp, несмотря на то, что я вижу эти пакеты в wireshark.
Вот полный тест, который проходит под * nixи не работает под Windows:
package probes
import (
"fmt"
"net"
"testing"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"time"
)
func TestTtlExceed(t *testing.T) {
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
t.Fatalf("Cannot listen: %s", err.Error())
}
defer conn.Close()
go listen(conn, t)
msg := icmp.Message{
Code: 0,
Body: &icmp.Echo{
Seq: 1,
ID: 1,
Data: []byte{'t','e','s','t'},
},
Type:ipv4.ICMPTypeEcho,
}
wbuf, err := msg.Marshal(nil)
if err != nil {
t.Fatalf("Failed to marshal: %s", err.Error())
}
conn.IPv4PacketConn().SetTTL(1)
err = conn.SetWriteDeadline(time.Now().Add(time.Second))
if err != nil {
t.Fatalf("Failed to set dl: %s", err.Error())
}
_, err = conn.WriteTo(wbuf, &net.IPAddr{IP:net.ParseIP("8.8.8.8")})
if err != nil {
t.Fatalf("Failed to write: %s", err.Error())
}
time.Sleep(time.Second * 3)
}
func listen(conn *icmp.PacketConn, t *testing.T) {
got := false
conn.SetReadDeadline(time.Now().Add(time.Second * 2))
for {
buf := make([]byte, 256)
n, cm, peer, err := conn.IPv4PacketConn().ReadFrom(buf)
if err != nil {
// t.Fatalf("Error reading: %s", err.Error())
t.Logf("Error reading: %s", err.Error())
break
}
fmt.Printf("Got some: n: %v\tpeer:%s\tcm:%+#v\n", n, peer.String(),cm)
got = true
/*buf := make([]byte, 256)
n, peer, err := conn.ReadFrom(buf)
if err != nil {
t.Fatalf("Listen failed: %s\n", err.Error())
return
}
fmt.Printf("icmp: got\n")
parsed, err := icmp.ParseMessage(1, buf[:n])
if err != nil {
t.Fatalf("Failed to parse icmp message: %s", err.Error())
return
}
fmt.Printf("Got message from %s: %+#v\n", peer.String(), parsed)*/
}
if !got {
t.Fatalf("Got nothing from conn")
}
}
Есть идеи о том, что не так с Windows icmp raw socket?