func ExamplePacketConn_nonPrivilegedPing() { switch runtime.GOOS { case "darwin": case "linux": log.Println("you may need to adjust the net.ipv4.ping_group_range kernel state") default: log.Println("not supported on", runtime.GOOS) return } c, err := icmp.ListenPacket("udp6", "fe80::1%en0") if err != nil { log.Fatal(err) } defer c.Close() wm := icmp.Message{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1, Data: []byte("HELLO-R-U-THERE"), }, } wb, err := wm.Marshal(nil) if err != nil { log.Fatal(err) } if _, err := c.WriteTo(wb, &net.UDPAddr{IP: net.ParseIP("ff02::1"), Zone: "en0"}); err != nil { log.Fatal(err) } rb := make([]byte, 1500) n, peer, err := c.ReadFrom(rb) if err != nil { log.Fatal(err) } rm, err := icmp.ParseMessage(58, rb[:n]) if err != nil { log.Fatal(err) } switch rm.Type { case ipv6.ICMPTypeEchoReply: log.Printf("got reflection from %v", peer) default: log.Printf("got %+v; want echo reply", rm) } }
func ExamplePacketConn_nonPrivilegedPing() { c, err := icmp.ListenPacket("udp6", "fe80::1%en0") if err != nil { log.Fatal(err) } defer c.Close() wm := icmp.Message{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1, Data: []byte("HELLO-R-U-THERE"), }, } wb, err := wm.Marshal(nil) if err != nil { log.Fatal(err) } if _, err := c.WriteTo(wb, &net.UDPAddr{IP: net.ParseIP("ff02::1"), Zone: "en0"}); err != nil { log.Fatal(err) } rb := make([]byte, 1500) n, peer, err := c.ReadFrom(rb) if err != nil { log.Fatal(err) } rm, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]) if err != nil { log.Fatal(err) } switch rm.Type { case ipv6.ICMPTypeEchoReply: log.Printf("got reflection from %v", peer) default: log.Printf("got %+v; want echo reply", rm) } }
func TestPingGoogle(t *testing.T) { if testing.Short() { t.Skip("to avoid external network") } switch runtime.GOOS { case "darwin": case "linux": t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state") default: t.Skipf("not supported on %s", runtime.GOOS) } m, ok := nettest.SupportsRawIPSocket() for i, tt := range pingGoogleTests { if tt.network[:2] == "ip" && !ok { t.Log(m) continue } c, err := icmp.ListenPacket(tt.network, tt.address) if err != nil { t.Error(err) continue } defer c.Close() dst, err := googleAddr(c, tt.protocol) if err != nil { t.Error(err) continue } wm := icmp.Message{ Type: tt.mtype, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1 << uint(i), Data: []byte("HELLO-R-U-THERE"), }, } wb, err := wm.Marshal(nil) if err != nil { t.Error(err) continue } if n, err := c.WriteTo(wb, dst); err != nil { t.Error(err, dst) continue } else if n != len(wb) { t.Errorf("got %v; want %v", n, len(wb)) continue } rb := make([]byte, 1500) n, peer, err := c.ReadFrom(rb) if err != nil { t.Error(err) continue } rm, err := icmp.ParseMessage(tt.protocol, rb[:n]) if err != nil { t.Error(err) continue } switch rm.Type { case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply: t.Logf("got reflection from %v", peer) default: t.Errorf("got %+v; want echo reply", rm) } } }
func ExamplePacketConn_tracingIPPacketRoute() { // Tracing an IP packet route to www.google.com. const host = "www.google.com" ips, err := net.LookupIP(host) if err != nil { log.Fatal(err) } var dst net.IPAddr for _, ip := range ips { if ip.To4() != nil { dst.IP = ip fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host) break } } if dst.IP == nil { log.Fatal("no A record found") } c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolICMP), "0.0.0.0") // ICMP for IPv4 if err != nil { log.Fatal(err) } defer c.Close() p := ipv4.NewPacketConn(c) if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil { log.Fatal(err) } wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Data: []byte("HELLO-R-U-THERE"), }, } rb := make([]byte, 1500) for i := 1; i <= 64; i++ { // up to 64 hops wm.Body.(*icmp.Echo).Seq = i wb, err := wm.Marshal(nil) if err != nil { log.Fatal(err) } if err := p.SetTTL(i); err != nil { log.Fatal(err) } // In the real world usually there are several // multiple traffic-engineered paths for each hop. // You may need to probe a few times to each hop. begin := time.Now() if _, err := p.WriteTo(wb, nil, &dst); err != nil { log.Fatal(err) } if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { log.Fatal(err) } n, cm, peer, err := p.ReadFrom(rb) if err != nil { if err, ok := err.(net.Error); ok && err.Timeout() { fmt.Printf("%v\t*\n", i) continue } log.Fatal(err) } rm, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) if err != nil { log.Fatal(err) } rtt := time.Since(begin) // In the real world you need to determine whether the // received message is yours using ControlMessage.Src, // ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq. switch rm.Type { case ipv4.ICMPTypeTimeExceeded: names, _ := net.LookupAddr(peer.String()) fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm) case ipv4.ICMPTypeEchoReply: names, _ := net.LookupAddr(peer.String()) fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm) return default: log.Printf("unknown ICMP message: %+v\n", rm) } } }
func doPing(tt pingTest, seq int) error { c, err := icmp.ListenPacket(tt.network, tt.address) if err != nil { return err } defer c.Close() dst, err := googleAddr(c, tt.protocol) if err != nil { return err } if tt.network != "udp6" && tt.protocol == iana.ProtocolIPv6ICMP { var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeDestinationUnreachable) f.Accept(ipv6.ICMPTypePacketTooBig) f.Accept(ipv6.ICMPTypeTimeExceeded) f.Accept(ipv6.ICMPTypeParameterProblem) f.Accept(ipv6.ICMPTypeEchoReply) if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil { return err } } wm := icmp.Message{ Type: tt.mtype, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq), Data: []byte("HELLO-R-U-THERE"), }, } wb, err := wm.Marshal(nil) if err != nil { return err } if n, err := c.WriteTo(wb, dst); err != nil { return err } else if n != len(wb) { return fmt.Errorf("got %v; want %v", n, len(wb)) } rb := make([]byte, 1500) if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { return err } n, peer, err := c.ReadFrom(rb) if err != nil { return err } rm, err := icmp.ParseMessage(tt.protocol, rb[:n]) if err != nil { return err } switch rm.Type { case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply: return nil default: return fmt.Errorf("got %+v from %v; want echo reply", rm, peer) } }