-
Notifications
You must be signed in to change notification settings - Fork 5
/
arp.go
113 lines (101 loc) · 3.26 KB
/
arp.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package tcpip
import (
"fmt"
"log"
"syscall"
)
// htons converts a short (uint16) from host-to-network byte order.
func htons(i uint16) uint16 {
return (i<<8)&0xff00 | i>>8
}
// https://www.n-study.com/tcp-ip/arp-format/
type Arp struct {
HardwareType []byte
ProtocolType []byte
HardwareSize []byte
ProtocolSize []byte
Opcode []byte
SenderMacAddr []byte
SenderIpAddr []byte
TargetMacAddr []byte
TargetIpAddr []byte
}
func NewArpRequest(localif LocalIpMacAddr, targetip string) Arp {
return Arp{
// イーサネットの場合、0x0001で固定
HardwareType: []byte{0x00, 0x01},
// IPv4の場合、0x0800で固定
ProtocolType: []byte{0x08, 0x00},
// MACアドレスのサイズ(バイト)。0x06
HardwareSize: []byte{0x06},
// IPアドレスのサイズ(バイト)。0x04
ProtocolSize: []byte{0x04},
// ARPリクエスト:0x0001
Opcode: []byte{0x00, 0x01},
// 送信元MACアドレス
SenderMacAddr: localif.LocalMacAddr,
// 送信元IPアドレス
SenderIpAddr: localif.LocalIpAddr,
// ターゲットMACアドレス broadcastなのでAll zero
TargetMacAddr: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// ターゲットIPアドレス
TargetIpAddr: Iptobyte(targetip),
}
}
func (*Arp) Send(ifindex int, packet []byte) Arp {
addr := syscall.SockaddrLinklayer{
Protocol: syscall.ETH_P_ARP,
Ifindex: ifindex,
Hatype: syscall.ARPHRD_ETHER,
}
sendfd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_ALL)))
if err != nil {
log.Fatalf("create sendfd err : %v\n", err)
}
defer syscall.Close(sendfd)
err = syscall.Sendto(sendfd, packet, 0, &addr)
if err != nil {
log.Fatalf("Send to err : %v\n", err)
}
for {
recvBuf := make([]byte, 80)
_, _, err := syscall.Recvfrom(sendfd, recvBuf, 0)
if err != nil {
log.Fatalf("read err : %v", err)
}
// EthernetのTypeがArpがチェック
if recvBuf[12] == 0x08 && recvBuf[13] == 0x06 {
// ArpのOpcodeがReplyかチェック
if recvBuf[20] == 0x00 && recvBuf[21] == 0x02 {
return parseArpPacket(recvBuf[14:])
}
}
}
}
func parseArpPacket(packet []byte) Arp {
return Arp{
HardwareType: []byte{packet[0], packet[1]},
ProtocolType: []byte{packet[2], packet[3]},
HardwareSize: []byte{packet[4]},
ProtocolSize: []byte{packet[5]},
Opcode: []byte{packet[6], packet[7]},
SenderMacAddr: []byte{packet[8], packet[9], packet[10], packet[11], packet[12], packet[13]},
SenderIpAddr: []byte{packet[14], packet[15], packet[16], packet[17]},
TargetMacAddr: []byte{packet[18], packet[19], packet[20], packet[21], packet[22], packet[23]},
TargetIpAddr: []byte{packet[24], packet[25], packet[26], packet[27]},
}
}
func arp() {
localif, err := getLocalIpAddr("wlp4s0")
if err != nil {
log.Fatalf("getLocalIpAddr err : %v", err)
}
ethernet := NewEthernet([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, localif.LocalMacAddr, "ARP")
//ethernet := NewEthernet([]byte{0x1c, 0x3b, 0xf3, 0x95, 0x6a, 0x2c}, localif.LocalMacAddr, "ARP")
arpReq := NewArpRequest(localif, "192.168.0.17")
var sendArp []byte
sendArp = append(sendArp, toByteArr(ethernet)...)
sendArp = append(sendArp, toByteArr(arpReq)...)
arpreply := arpReq.Send(localif.Index, sendArp)
fmt.Printf("ARP Reply : %s\n", printByteArr(arpreply.SenderMacAddr))
}