-
Notifications
You must be signed in to change notification settings - Fork 0
/
icmp.go
88 lines (77 loc) · 1.85 KB
/
icmp.go
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package packemon
import (
"bytes"
"encoding/binary"
"time"
)
// https://www.infraexpert.com/study/tcpip4.html
// https://inc0x0.com/icmp-ip-packets-ping-manually-create-and-send-icmp-ip-packets/
type ICMP struct {
Typ uint8
Code uint8
Checksum uint16
Identifier uint16
Sequence uint16
Data []byte
}
const (
ICMP_TYPE_REQUEST = 0x08
)
func ParsedICMP(payload []byte) *ICMP {
return &ICMP{
Typ: payload[0],
Code: payload[1],
Checksum: binary.BigEndian.Uint16(payload[2:4]),
Identifier: binary.BigEndian.Uint16(payload[4:6]),
Sequence: binary.BigEndian.Uint16(payload[6:8]),
Data: payload[8:],
}
}
// icmp request
func NewICMP() *ICMP {
icmp := &ICMP{
Typ: ICMP_TYPE_REQUEST,
Code: 0,
Identifier: 0x34a1,
Sequence: 0x0001,
}
// pingのecho requestのpacketを観察すると以下で良さそう
timestamp := func() []byte {
now := time.Now().Unix()
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, uint32(now))
return binary.LittleEndian.AppendUint32(b, 0x00000000)
}()
icmp.Data = timestamp
icmp.Checksum = func() uint16 {
b := make([]byte, 2)
binary.LittleEndian.PutUint16(b, icmp.CalculateChecksum())
return binary.BigEndian.Uint16(b)
}()
return icmp
}
// copy from https://cs.opensource.google/go/x/net/+/master:icmp/message.go
func (i *ICMP) CalculateChecksum() uint16 {
b := i.Bytes()
csumcv := len(b) - 1 // checksum coverage
s := uint32(0)
for i := 0; i < csumcv; i += 2 {
s += uint32(b[i+1])<<8 | uint32(b[i])
}
if csumcv&1 == 0 {
s += uint32(b[csumcv])
}
s = s>>16 + s&0xffff
s = s + s>>16
return ^uint16(s)
}
func (i *ICMP) Bytes() []byte {
buf := &bytes.Buffer{}
buf.WriteByte(i.Typ)
buf.WriteByte(i.Code)
WriteUint16(buf, i.Checksum)
WriteUint16(buf, i.Identifier)
WriteUint16(buf, i.Sequence)
buf.Write(i.Data)
return buf.Bytes()
}