func icmpEchoSender(c *icmp.PacketConn) { timer := time.NewTicker(5 * time.Second) for { <-timer.C // Collect IPs. ips := make(map[string]bool) for k, _ := range outSockets { ipAndPort := strings.Split(k, ":") ips[ipAndPort[0]] = true } // Send to all IPs. for ip, _ := range ips { wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1, Data: []byte("STRATUX"), }, } wb, err := wm.Marshal(nil) if err != nil { log.Printf("couldn't send ICMP Echo: %s\n", err.Error()) continue } if _, err := c.WriteTo(wb, &net.IPAddr{IP: net.ParseIP(ip)}); err != nil { log.Printf("couldn't send ICMP Echo: %s\n", err.Error()) continue } totalNetworkMessagesSent++ } } }
func (e *EchoRequest) Send() { for i := 0; i < e.Count; i++ { pkt := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: e.Id, Seq: i, Data: []byte("raintank/go-pinger"), }, } wb, err := pkt.Marshal(nil) if err != nil { if e.pinger.Debug { log.Printf("failed to marshal ICMP Echo packet. %s", err) } continue } sentTime, err := e.pinger.WritePkt(wb, e.Peer) if err == nil { e.Stats.Sent++ e.Stats.SentTime[i] = sentTime if e.pinger.Debug { log.Printf("go-pinger: sent pkt. Peer %s, Id: %d, Seq: %d, Sent: %s", e.Peer, e.Id, i, sentTime) } } } e.Listen() }
func main() { timeout := 5 t1 := time.Now() c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { checkError(err, "listen err, ") } c.SetDeadline(t1.Add(time.Second * time.Duration(timeout))) defer c.Close() wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, 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) } // Send ICMP echo and start timer starttime := time.Now() if _, err := c.WriteTo(wb, &net.IPAddr{IP: net.ParseIP(targetIP)}); err != nil { log.Fatalf("WriteTo err, %s", err) } rb := make([]byte, 1500) // Look for ICMP response and stop time n, peer, err := c.ReadFrom(rb) stoptime := time.Now() if err != nil { log.Fatal(err) } //rm, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) rm, err := icmp.ParseMessage(1, rb[:n]) if err != nil { log.Fatal(err) } switch rm.Type { case ipv4.ICMPTypeEchoReply: log.Printf("got reflection from %v", peer) log.Printf("ICMP echo request sent on ", starttime) log.Printf("ICMP echo response received on ", stoptime) default: log.Printf("got %+v; want echo reply", rm) } }
func ping(listener *icmp.PacketConn, message icmp.Message, raddr net.Addr, timeout time.Duration) (Pong, error) { data, err := message.Marshal(nil) if err != nil { return Pong{}, err } _, err = listener.WriteTo(data, raddr) if err != nil { return Pong{}, err } now := time.Now() done := make(chan Pong) go func() { for { buf := make([]byte, 10000) // bufio n, peer, err := listener.ReadFrom(buf) if err != nil { return } since := time.Since(now) input, err := icmp.ParseMessage(protocolICMP, buf[:n]) if err != nil { return } if input.Type != ipv4.ICMPTypeEchoReply { continue } echo := input.Body.(*icmp.Echo) pong := Pong{ Peer: peer, ID: echo.ID, Seq: echo.Seq, Data: echo.Data, Size: n, RTT: since, } done <- pong return } }() select { case pong := <-done: return pong, nil case <-time.After(timeout): return Pong{}, errors.New("Timeout") } }
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 (i *ICMP) Write(b []byte) error { message := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ Data: b, }, } outgoing, err := message.Marshal(nil) if err != nil { return err } _, err = i.listener.WriteTo(outgoing, i.raddr) if err != nil { return err } return nil }
func Send_UDP_Ping(c *icmp.PacketConn, targetIP string, concurrent int, timeout int, ch_lock chan struct{}, rCache *ResultCache) { ch_lock <- struct{}{} wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, 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 { return } timeForSend := time.Now() c.SetReadDeadline(timeForSend.Add(time.Duration(timeout) * time.Second)) rCache.New(targetIP) if _, err := c.WriteTo(wb, &net.UDPAddr{IP: net.ParseIP(targetIP)}); err != nil { return } time.Sleep(time.Second) <-ch_lock }
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) } }
// pingIcmp performs a ping to a destination. It select between ipv4 or ipv6 ping based // on the format of the destination ip. func (r Runner) pingIcmp() (err error) { var ( icmpType icmp.Type network string ) if strings.Contains(r.Parameters.Destination, ":") { network = "ip6:ipv6-icmp" icmpType = ipv6.ICMPTypeEchoRequest } else { network = "ip4:icmp" icmpType = ipv4.ICMPTypeEcho } c, err := net.Dial(network, r.Parameters.Destination) if err != nil { return fmt.Errorf("Dial failed: %v", err) } c.SetDeadline(time.Now().Add(time.Duration(r.Parameters.Timeout) * time.Second)) defer c.Close() // xid is the process ID. // Get process ID and make sure it fits in 16bits. xid := os.Getpid() & 0xffff // Sequence number of the packet. xseq := 0 packet := icmp.Message{ Type: icmpType, // Type of icmp message Code: 0, // icmp query messages use code 0 Body: &icmp.Echo{ ID: xid, // Packet id Seq: xseq, // Sequence number of the packet Data: bytes.Repeat([]byte("Ping!Ping!Ping!"), 3), }, } wb, err := packet.Marshal(nil) if err != nil { return fmt.Errorf("Connection failed: %v", err) } if _, err := c.Write(wb); err != nil { return fmt.Errorf("Conn.Write Error: %v", err) } rb := make([]byte, 1500) if _, err := c.Read(rb); err != nil { // If connection timed out, we return E_Timeout if e := err.(*net.OpError).Timeout(); e { return fmt.Errorf(E_Timeout) } if strings.Contains(err.Error(), "connection refused") { return fmt.Errorf(E_ConnRefused) } return fmt.Errorf("Conn.Read failed: %v", err) } _, err = icmp.ParseMessage(icmpType.Protocol(), rb) if err != nil { return fmt.Errorf("ParseICMPMessage failed: %v", err) } return }
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 probeICMP(target string, w http.ResponseWriter, module Module) (success bool) { deadline := time.Now().Add(module.Timeout) socket, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { log.Errorf("Error listening to socket: %s", err) return } defer socket.Close() ip, err := net.ResolveIPAddr("ip4", target) if err != nil { log.Errorf("Error resolving address %s: %s", target, err) return } seq := getICMPSequence() pid := os.Getpid() & 0xffff wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: pid, Seq: int(seq), Data: []byte("Prometheus Blackbox Exporter"), }, } wb, err := wm.Marshal(nil) if err != nil { log.Errorf("Error marshalling packet for %s: %s", target, err) return } if _, err := socket.WriteTo(wb, ip); err != nil { log.Errorf("Error writing to socker for %s: %s", target, err) return } rb := make([]byte, 1500) if err := socket.SetReadDeadline(deadline); err != nil { log.Errorf("Error setting socket deadline for %s: %s", target, err) return } for { n, peer, err := socket.ReadFrom(rb) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { log.Infof("Timeout reading from socket for %s: %s", target, err) return } log.Errorf("Error reading from socket for %s: %s", target, err) continue } if peer.String() != ip.String() { continue } rm, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) if err != nil { log.Warnf("Error parsing ICMP message for %s: %s", target, err) continue } if rm.Type == ipv4.ICMPTypeEchoReply { // The ICMP package does not support unmarshalling // messages, so assume this is the right sequence number. success = true return } } return }
func probeICMP(target string, w http.ResponseWriter, module Module) (success bool) { var ( socket *icmp.PacketConn requestType icmp.Type replyType icmp.Type fallbackProtocol string ) deadline := time.Now().Add(module.Timeout) // Defaults to IPv4 to be compatible with older versions if module.ICMP.Protocol == "" { module.ICMP.Protocol = "icmp" } // In case of ICMP prefer IPv6 by default if module.ICMP.Protocol == "icmp" && module.ICMP.PreferredIpProtocol == "" { module.ICMP.PreferredIpProtocol = "ip6" } if module.ICMP.Protocol == "icmp4" { module.ICMP.PreferredIpProtocol = "ip4" fallbackProtocol = "" } else if module.ICMP.Protocol == "icmp6" { module.ICMP.PreferredIpProtocol = "ip6" fallbackProtocol = "" } else if module.ICMP.PreferredIpProtocol == "ip6" { fallbackProtocol = "ip4" } else { fallbackProtocol = "ip6" } ip, err := net.ResolveIPAddr(module.ICMP.PreferredIpProtocol, target) if err != nil && fallbackProtocol != "" { ip, err = net.ResolveIPAddr(fallbackProtocol, target) } if err != nil { log.Errorf("Error resolving address %s: %s", target, err) } if ip.IP.To4() == nil { requestType = ipv6.ICMPTypeEchoRequest replyType = ipv6.ICMPTypeEchoReply socket, err = icmp.ListenPacket("ip6:ipv6-icmp", "::") fmt.Fprintf(w, "probe_ip_protocol 6\n") } else { requestType = ipv4.ICMPTypeEcho replyType = ipv4.ICMPTypeEchoReply socket, err = icmp.ListenPacket("ip4:icmp", "0.0.0.0") fmt.Fprintf(w, "probe_ip_protocol 4\n") } if err != nil { log.Errorf("Error listening to socket: %s", err) return } defer socket.Close() if err != nil { log.Errorf("Error resolving address %s: %s", target, err) return } seq := getICMPSequence() pid := os.Getpid() & 0xffff wm := icmp.Message{ Type: requestType, Code: 0, Body: &icmp.Echo{ ID: pid, Seq: int(seq), Data: []byte("Prometheus Blackbox Exporter"), }, } wb, err := wm.Marshal(nil) if err != nil { log.Errorf("Error marshalling packet for %s: %s", target, err) return } if _, err := socket.WriteTo(wb, ip); err != nil { log.Errorf("Error writing to socker for %s: %s", target, err) return } // Reply should be the same except for the message type. wm.Type = replyType wb, err = wm.Marshal(nil) if err != nil { log.Errorf("Error marshalling packet for %s: %s", target, err) return } rb := make([]byte, 1500) if err := socket.SetReadDeadline(deadline); err != nil { log.Errorf("Error setting socket deadline for %s: %s", target, err) return } for { n, peer, err := socket.ReadFrom(rb) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { log.Infof("Timeout reading from socket for %s: %s", target, err) return } log.Errorf("Error reading from socket for %s: %s", target, err) continue } if peer.String() != ip.String() { continue } if replyType == ipv6.ICMPTypeEchoReply { // Clear checksum to make comparison succeed. rb[2] = 0 rb[3] = 0 } if bytes.Compare(rb[:n], wb) == 0 { success = true return } } }
// Sends a single ICMP echo to an IP and returns success and latency information. // Borrowed from BrianBrazil's blackbox exporter func Ping(ip net.IP, maxRTT time.Duration) (success bool, latency time.Duration) { deadline := time.Now().Add(maxRTT) var socket *icmp.PacketConn var err error if isIPv4(ip) { socket, err = icmp.ListenPacket("ip4:icmp", "0.0.0.0") } else if isIPv6(ip) { socket, err = icmp.ListenPacket("ip6:ipv6-icmp", "::") } else { log.Errorln("IP did not match any known types?") return } if err != nil { log.Errorf("Error listening to socket: %s", err) return } defer socket.Close() seq := getICMPSequence() pid := os.Getpid() & 0xffff // Build the packet var wm icmp.Message if isIPv4(ip) { wm = icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: pid, Seq: int(seq), Data: []byte("poller_exporter"), }, } } else if isIPv6(ip) { wm = icmp.Message{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmp.Echo{ ID: pid, Seq: int(seq), Data: []byte("poller_exporter"), }, } } else { log.Errorln("IP did not match any known types?") return } wb, err := wm.Marshal(nil) if err != nil { log.Errorf("Error marshalling packet for %s: %s", ip.String(), err) return } sendTime := time.Now() var dst *net.IPAddr dst = &net.IPAddr{IP: ip} if _, err := socket.WriteTo(wb, dst); err != nil { log.Errorf("Error writing to socket for %s: %s", ip.String(), err) return } // Reply should be the same except for the message type. if isIPv4(ip) { wm.Type = ipv4.ICMPTypeEchoReply } else if isIPv6(ip) { wm.Type = ipv6.ICMPTypeEchoReply } else { log.Errorln("IP did not match any known types?") return } wb, err = wm.Marshal(nil) if err != nil { log.Errorf("Error marshalling packet for %s: %s", ip.String(), err) return } rb := make([]byte, 1500) if err := socket.SetReadDeadline(deadline); err != nil { log.Errorf("Error setting socket deadline for %s: %s", ip.String(), err) return } for { n, peer, err := socket.ReadFrom(rb) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { log.Infof("Timeout reading from socket for %s: %s", ip.String(), err) return } log.Errorf("Error reading from socket for %s: %s", ip.String(), err) continue } if peer.String() != ip.String() { continue } if bytes.Compare(rb[:n], wb) == 0 { success = true latency = time.Now().Sub(sendTime) return } } return }
func doPing(host string, tt *Ping, seq int) error { c, err := icmp.ListenPacket(tt.network, tt.address) if err != nil { return err } defer c.Close() dst, err := getAddr(host, c, tt.protocol) if err != nil { return err } now := time.Now() today := now.Truncate(24*time.Hour).UnixNano() / 1000000 transmitTime := uint32(now.UnixNano()/1000000 - today) wm := icmp.Message{ Type: tt.mtype, Code: 0, Body: &Timestamp{ ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq), OriginTimestamp: transmitTime, }, } 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 } receivedTime := time.Now().UnixNano()/1000000 - today rm, err := icmp.ParseMessage(tt.protocol, rb[:n]) if err != nil { return err } switch rm.Type { case ipv4.ICMPTypeTimestampReply: b, _ := rm.Body.Marshal(iana.ProtocolICMP) ts, err := ParseTimestamp(b) if err != nil { fmt.Errorf("ParseTimestamp error: %s", err) } remoteReceiveTime := int64(ts.ReceiveTimestamp) rtt := int64(math.Abs(float64(remoteReceiveTime - int64(transmitTime) + receivedTime - int64(ts.TransmitTimestamp)))) delta := rtt/2 + int64(transmitTime) - remoteReceiveTime w := new(tabwriter.Writer) w.Init(os.Stdout, 0, 4, 0, '\t', 0) fmt.Fprintf(w, "ICMP timestamp:\tOriginate=%d Receive=%d Transmit=%d\n", ts.OriginTimestamp, ts.ReceiveTimestamp, ts.TransmitTimestamp) fmt.Fprintf(w, "ICMP timestamp RTT:\ttsrtt=%d\n", rtt) fmt.Fprintf(w, "Time difference:\tdelta=%d\n", delta) w.Flush() return nil default: return fmt.Errorf("got %+v from %v; want echo reply", rm, peer) } }
// Pinger pings requested address. // It returns nil when IcmpEchoReplay is recived, error otherwishe. func Pinger(address string, timeout time.Duration) (err error) { addr, err := net.ResolveIPAddr("ip", address) if err != nil { return err } network := "ip4:icmp" if addr.IP.To4() == nil { network = "ip6:ipv6-icmp" } c, err := icmp.ListenPacket(network, address) if err != nil { return err } defer func() { if cerr := c.Close(); cerr != nil && err == nil { err = cerr } }() wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1, Data: []byte("ping"), }, } if addr.IP.To4() == nil { wm.Type = ipv6.ICMPTypeEchoRequest } wb, err := wm.Marshal(nil) if err != nil { return err } if err := c.SetDeadline(time.Now().Add(timeout)); err != nil { return err } if _, err = c.WriteTo(wb, addr); err != nil { return err } rb := make([]byte, 1500) n, _, err := c.ReadFrom(rb) if err != nil { return err } rm, err := icmp.ParseMessage(ProtocolICMP, rb[:n]) if err != nil { return err } if addr.IP.To4() == nil { if rm.Type == ipv6.ICMPTypeEchoReply { return ErrNoImcpReplay } return nil } if rm.Type == ipv4.ICMPTypeEchoReply { return ErrNoImcpReplay } return nil }
func probeICMP(target string, w http.ResponseWriter, module Module) (success bool) { deadline := time.Now().Add(module.Timeout) socket, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { log.Errorf("Error listening to socket: %s", err) return } defer socket.Close() ip, err := net.ResolveIPAddr("ip4", target) if err != nil { log.Errorf("Error resolving address %s: %s", target, err) return } seq := getICMPSequence() pid := os.Getpid() & 0xffff wm := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: pid, Seq: int(seq), Data: []byte("Prometheus Blackbox Exporter"), }, } wb, err := wm.Marshal(nil) if err != nil { log.Errorf("Error marshalling packet for %s: %s", target, err) return } if _, err := socket.WriteTo(wb, ip); err != nil { log.Errorf("Error writing to socker for %s: %s", target, err) return } // Reply should be the same except for the message type. wm.Type = ipv4.ICMPTypeEchoReply wb, err = wm.Marshal(nil) if err != nil { log.Errorf("Error marshalling packet for %s: %s", target, err) return } rb := make([]byte, 1500) if err := socket.SetReadDeadline(deadline); err != nil { log.Errorf("Error setting socket deadline for %s: %s", target, err) return } for { n, peer, err := socket.ReadFrom(rb) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { log.Infof("Timeout reading from socket for %s: %s", target, err) return } log.Errorf("Error reading from socket for %s: %s", target, err) continue } if peer.String() != ip.String() { continue } if bytes.Compare(rb[:n], wb) == 0 { success = true return } } return }
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 %q", runtime.GOOS) } for i, tt := range pingGoogleTests { if tt.network[:2] == "ip" && os.Getuid() != 0 { 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 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.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) } }