forked from j-keck/arping
-
Notifications
You must be signed in to change notification settings - Fork 0
/
arp_datagram.go
98 lines (84 loc) · 2.6 KB
/
arp_datagram.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
89
90
91
92
93
94
95
96
97
98
package arping
import (
"bytes"
"encoding/binary"
"net"
)
const (
requestOper = 1
responseOper = 2
)
type arpDatagram struct {
htype uint16 // Hardware Type
ptype uint16 // Protocol Type
hlen uint8 // Hardware address Length
plen uint8 // Protocol address length
oper uint16 // Operation 1->request, 2->response
sha []byte // Sender hardware address, length from Hlen
spa []byte // Sender protocol address, length from Plen
tha []byte // Target hardware address, length from Hlen
tpa []byte // Target protocol address, length from Plen
}
func newArpRequest(
srcMac net.HardwareAddr,
srcIP net.IP,
dstMac net.HardwareAddr,
dstIP net.IP) arpDatagram {
return arpDatagram{
htype: uint16(1),
ptype: uint16(0x0800),
hlen: uint8(6),
plen: uint8(4),
oper: uint16(requestOper),
sha: srcMac,
spa: srcIP.To4(),
tha: dstMac,
tpa: dstIP.To4()}
}
func (datagram arpDatagram) Marshal() []byte {
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, datagram.htype)
binary.Write(buf, binary.BigEndian, datagram.ptype)
binary.Write(buf, binary.BigEndian, datagram.hlen)
binary.Write(buf, binary.BigEndian, datagram.plen)
binary.Write(buf, binary.BigEndian, datagram.oper)
buf.Write(datagram.sha)
buf.Write(datagram.spa)
buf.Write(datagram.tha)
buf.Write(datagram.tpa)
return buf.Bytes()
}
func (datagram arpDatagram) MarshalWithEthernetHeader() []byte {
// ethernet frame header
var ethernetHeader []byte
ethernetHeader = append(ethernetHeader, datagram.tha...)
ethernetHeader = append(ethernetHeader, datagram.sha...)
ethernetHeader = append(ethernetHeader, []byte{0x08, 0x06}...) // arp
return append(ethernetHeader, datagram.Marshal()...)
}
func (datagram arpDatagram) SenderIP() net.IP {
return net.IP(datagram.spa)
}
func (datagram arpDatagram) SenderMac() net.HardwareAddr {
return net.HardwareAddr(datagram.sha)
}
func (datagram arpDatagram) IsResponseOf(request arpDatagram) bool {
return datagram.oper == responseOper && bytes.Equal(request.spa, datagram.tpa) &&
bytes.Equal(request.tpa, datagram.spa)
}
func parseArpDatagram(buffer []byte) arpDatagram {
var datagram arpDatagram
b := bytes.NewBuffer(buffer)
binary.Read(b, binary.BigEndian, &datagram.htype)
binary.Read(b, binary.BigEndian, &datagram.ptype)
binary.Read(b, binary.BigEndian, &datagram.hlen)
binary.Read(b, binary.BigEndian, &datagram.plen)
binary.Read(b, binary.BigEndian, &datagram.oper)
haLen := int(datagram.hlen)
paLen := int(datagram.plen)
datagram.sha = b.Next(haLen)
datagram.spa = b.Next(paLen)
datagram.tha = b.Next(haLen)
datagram.tpa = b.Next(paLen)
return datagram
}