icmp.PacketConn не видит сообщения превышения TTL под окнами - PullRequest
0 голосов
/ 06 мая 2019

Я пытаюсь реализовать небольшую утилиту 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?

...