icmp/status.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
package icmp import ( "net" "os" "time" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" ) func CheckICMPReachability(ipAddress string) (bool, error) { icmpConn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { return false, err } defer icmpConn.Close() icmpMessage := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1, Data: []byte("ping"), }, } messageBytes, err := icmpMessage.Marshal(nil) if err != nil { return false, err } destinationIP := &net.IPAddr{IP: net.ParseIP(ipAddress)} if destinationIP.IP == nil { return false, net.InvalidAddrError("invalid IP address") } _, err = icmpConn.WriteTo(messageBytes, destinationIP) if err != nil { return false, err } responseBuffer := make([]byte, 1500) err = icmpConn.SetReadDeadline(time.Now().Add(2 * time.Second)) if err != nil { return false, err } bytesRead, _, err := icmpConn.ReadFrom(responseBuffer) if err != nil { return false, nil // this means device is offline this isn't an error condition } responseMessage, err := icmp.ParseMessage(1, responseBuffer[:bytesRead]) if err != nil { return false, err } return responseMessage.Type == ipv4.ICMPTypeEchoReply, nil } |