Brijesh's Git Server — network-scan @ 5f24c81efef6551c7737d1bc4c8d73f94f12dc03

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
}