...
1 package icmp
2
3 import (
4 "fmt"
5 "net"
6 "time"
7
8 "golang.org/x/net/icmp"
9 "golang.org/x/net/ipv4"
10 )
11
12
13 func NewMessage(message string, id int) icmp.Message {
14 return icmp.Message{
15 Type: ipv4.ICMPTypeEcho,
16 Code: 0,
17 Body: &icmp.Echo{
18 ID: id,
19 Seq: 0,
20 Data: []byte(message),
21 },
22 }
23 }
24
25
26 func NewPacketConnection(timeout time.Duration) (*icmp.PacketConn, error) {
27 packetconn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
28 if err != nil {
29 return nil, fmt.Errorf("error making packet connection: %w", err)
30 }
31
32 deadline := time.Now().Add(timeout)
33 err = packetconn.SetReadDeadline(deadline)
34 if err != nil {
35 return nil, fmt.Errorf("failed to set read deadline on connection: %w", err)
36 }
37 return packetconn, nil
38 }
39
40
41 func SendRequest(packetconn *icmp.PacketConn, im icmp.Message, dst net.Addr) error {
42 ib, err := im.Marshal(nil)
43 if err != nil {
44 return fmt.Errorf("failure to marshall ICMP message: %w", err)
45 }
46
47 _, err = packetconn.WriteTo(ib, dst)
48 if err != nil {
49 return fmt.Errorf("failed to write ICMP bytes to packet connection: %w", err)
50 }
51 return nil
52 }
53
54
55
56
57
58
59
60
61
62
63
64
65 func ReceiveReply(packetconn *icmp.PacketConn, id int) bool {
66 for {
67 rb := make([]byte, 1500)
68 n, _, err := packetconn.ReadFrom(rb)
69 if err != nil {
70 return false
71 }
72
73 rm, err := icmp.ParseMessage(1, rb[:n])
74 if err != nil {
75 continue
76 }
77
78 if rm.Type != ipv4.ICMPTypeEchoReply {
79 continue
80 }
81
82 mes, ok := rm.Body.(*icmp.Echo)
83 if !ok {
84 continue
85 }
86
87 if id == mes.ID {
88 return true
89 }
90 }
91 }
92
View as plain text