Pkg.go.dev is a new destination for Go discovery & docs. Check it out at pkg.go.dev/github.com/surge/net and share your feedback.

package netx

import "github.com/surge/net"

ip.go ping.go

❖ const ( ProtocolICMP = 1 ProtocolIPv6ICMP = 58 )

ParseIP takes a string that represents an IP address, IP range, or CIDR block and return a list of individual IPs. Currently only IPv4 is supported.

For example:

10.1.1.1 -> 10.1.1.1 10.1.1.1,2 -> 10.1.1.1, 10.1.1.2 10.1.1,2.1 -> 10.1.1.1, 10.1.2.1 10.1.1,2.1,2 -> 10.1.1.1, 10.1.1.2 10.1.2.1, 10.1.2.2 10.1.1.1-2 -> 10.1.1.1, 10.1.1.2 10.1.1.-2 -> 10.1.1.0, 10.1.1.1, 10.1.1.2 10.1.1.1-10 -> 10.1.1.1, 10.1.1.2 ... 10.1.1.10 10.1.1.1- -> 10.1.1.1 ... 10.1.1.254, 10.1.1.255 10.1.1-3.1 -> 10.1.1.1, 10.1.2.1, 10.1.3.1 10.1-3.1-3.1 -> 10.1.1.1, 10.1.2.1, 10.1.3.1, 10.2.1.1, 10.2.2.1, 10.2.3.1, 10.3.1.1, 10.3.2.1, 10.3.3.1 10.1.1 -> 10.1.1.0, 10.1.1.1 ... 10.1.1.254, 10.1.1.255 10.1.1-2 -> 10.1.1.0, 10.1.1.1 ... 10.1.1.255, 10.1.2.0, 10.1.2.1 ... 10.1.2.255 10.1-2 -> 10.1.0.0, 10.1.0,1 ... 10.2.255.254, 10..2.255.255 10 -> 10.0.0.0 ... 10.255.255.255 10.1.1.2,3,4 -> 10.1.1.1, 10.1.1.2, 10.1.1.3, 10.1.1.4 10.1.1,2 -> 10.1.1.0, 10.1.1.1 ... 10.1.1.255, 10.1.2.0, 10.1.2.1 ... 10.1.2.255 10.1.1/28 -> 10.1.1.0 ... 10.1.1.255 10.1.1.0/28 -> 10.1.1.0 ... 10.1.1.15 10.1.1.0/30 -> 10.1.1.0, 10.1.1.1, 10.1.1.2, 10.1.1.3 10.1.1.128/25 -> 10.1.1.128 ... 10.1.1.255

Example Code: ips, _ := ParseIP("10.1.1,2.1,2") fmt.Println(len(ips)) Output: 4 err should be nil, and ips should contain 10.1.1.1, 10.1.1.2, 10.1.2.1 and 10.1.2.2

ParseIPv4 is called by ParseIP for IPv4 addresses. See ParseIP for more detials.

❖ type PingResult struct { // Source IP = remote host Src net.IP // Destination IP = localhost IP Dst net.IP // Type of Service TOS int // Time to live (# of hops, really) TTL int // ICMP Type: Type of Message // http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Control_messages Type icmp.Type // ICMP Subtype // http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Control_messages Code int // Message ID ID int // Message sequence number Seq int // Payload size Size int // Round trip time RTT time.Duration // Any errors encountered Err error }

PingResult is the result from sending an ICMP ECHO_REQUEST to a specific host. When successful, all the fields are filled in and Err is nil. When failed, only the fields Src, ID, Seq and Err are available.

Ping sends ICMP ECHO_REQUEST to a single IP address, wait for the ECHO_REPLY, and returns the result.

Example Code: pr, _ := Ping("127.0.0.1") fmt.Printf("%v", pr) Output: 8 bytes from 127.0.0.1: seq=1 ttl=64 tos=0 time=346.372us

❖ type Pinger struct { // Interval is the amount of time to wait between sending each ICMP packet. // Realistically this shouldn't be less than 25 or 50ms as the process of the // ECHO_REPLY packets will take some time. So if the ECHO_REQUEST packets are // sent too fast, then the round trip time will be skewed. // // Default 100ms. Interval time.Duration // MaxRTT is the maximum round trip time a response is to be expected. // Default 100ms. MaxRTT time.Duration // ICMP payload size, in bytes. Minimum 8 bytes. Size int // Copied from `man ping` on CentOS // Set Quality of Service -related bits in ICMP datagrams. Traditionally (RFC1349), // these have been interpreted as: 0 for reserved (currently being redefined as // congestion control), 1-4 for Type of Service and 5-7 for Precedence. // Possible settings for Type of Service are: minimal cost: 0x02, reliability: 0x04, // throughput: 0x08, low delay: 0x10. Multiple TOS bits should not be set // simultaneously. Possible settings for special Precedence range from priority // (0x20) to net control (0xe0). You must be root (CAP_NET_ADMIN capability) to // use Critical or higher precedence value. You cannot set bit 0x01 (reserved) // unless ECN has been enabled in the kernel. In RFC2474, these fields has been // redefined as 8-bit Differentiated Services (DS), consisting of: bits 0-1 of // separate data (ECN will be used, here), and bits 2-7 of Differentiated // Services Codepoint (DSCP). // // Default 0 TOS int // Time to live for outgoing ECHO_REQUEST packets. // // Default 32. TTL int // Don't Fragment. // // Default false. DF bool // contains filtered or unexported fields }

Pinger sends ICMP ECHO_REQQUEST to a list of IPv4 addresses and waits for the ICMP ECHO_REPLY from each of them.

The process using Pinger must be run as root.

Example Code: pinger := &Pinger{Size: 64} pinger.AddIPs([]string{"127.0.0.1", "127.0.0.2"}) res, _ := pinger.Start() for pr := range res { fmt.Printf("%v", pr) } Output: 64 bytes from 127.0.0.1: seq=1 ttl=64 tos=0 time=346.372us 127.0.0.2: Request timed out for seq 1 Example (DF) Code: pinger := &Pinger{ DF: true, Size: 1800, } pinger.AddIPs([]string{"8.8.8.8"}) res, _ := pinger.Start() for pr := range res { fmt.Printf("%v", pr) } Output: Should output error: ping/sender: Error sending echo requests: write ip4: message too long

AddIPs adds a list of IP addresses. Each of the IPs in the list are parsed and expanded using ParseIP.

IPs returns the list of parsed IP addresses in the form of net.IP

Start kicks off the pinging process. It takes the list of IP addresses added by AddIPs() and sends ICMP ECHO_REQUEST to all of them at the specified Interval. Results are sent via the returned channel. The caller is expected to read the channel so it won't get blocked.

Only a single Start can be called at a time. If the second call to Start is made, and error will be returned.

Stop stops the pinging processes.