-
Notifications
You must be signed in to change notification settings - Fork 5
/
udp.go
127 lines (103 loc) · 3.15 KB
/
udp.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package tcpip
import (
"bytes"
"fmt"
"log"
"syscall"
)
// https://www.infraexpert.com/study/tcpip12.html
type UDPHeader struct {
SourcePort []byte
DestPort []byte
PacketLenth []byte
Checksum []byte
}
type UDPDummyHeader struct {
SourceIPAddr []byte
DstIPAddr []byte
Protocol []byte
Length []byte
}
func NewUDPHeader(sourceport, destport []byte) UDPHeader {
return UDPHeader{
SourcePort: sourceport,
DestPort: destport,
PacketLenth: []byte{0x00, 0x00},
Checksum: []byte{0x00, 0x00},
}
}
func NewUDPDummyHeader(header IPHeader) UDPDummyHeader {
return UDPDummyHeader{
SourceIPAddr: header.SourceIPAddr,
DstIPAddr: header.DstIPAddr,
Protocol: []byte{0x00, 0x11},
Length: []byte{0x00, 0x00},
}
}
func (*UDPHeader) Send(packet []byte) {
addr := syscall.SockaddrLinklayer{
Protocol: syscall.ETH_P_IP,
Ifindex: 5,
}
sendfd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_ALL)))
if err != nil {
log.Fatalf("create udp sendfd err : %v\n", err)
}
err = syscall.Sendto(sendfd, packet, 0, &addr)
if err != nil {
log.Fatalf("Send to err : %v\n", err)
}
fmt.Println("UDP packet send")
syscall.Close(sendfd)
}
func (*UDPHeader) recv(localip []byte) {
recvfd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
if err != nil {
log.Fatalf("create udp sendfd err : %v\n", err)
}
syscall.Bind(recvfd, &syscall.SockaddrInet4{
Addr: [4]byte{localip[0], localip[1], localip[2], localip[3]},
Port: 42279,
})
for {
recvBuf := make([]byte, 300)
_, _, err := syscall.Recvfrom(recvfd, recvBuf, 0)
if err != nil {
log.Fatalf("read err : %v", err)
}
ip := parseIP(recvBuf[0:20])
if recvBuf[9] == 0x11 && bytes.Equal(ip.DstIPAddr, localip) {
// Ethernetが14byte, IPヘッダが20byteなので34byte目からがICMPパケット
fmt.Printf("dns packet : %s\n", printByteArr(recvBuf[28:]))
}
}
}
func udpSend() {
localmac := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
localif, err := getLocalIpAddr("lo")
if err != nil {
log.Fatalf("getLocalIpAddr err : %v", err)
}
ipheader := NewIPHeader(localif.LocalIpAddr, localif.LocalIpAddr, "UDP")
//var udp UDPHeader
udpheader := NewUDPHeader(UintTo2byte(42279), UintTo2byte(12345))
udpdata := []byte(`hogehoge`)
ipheader.TotalPacketLength = UintTo2byte(uint16(20) + toByteLen(udpheader) + uint16(len(udpdata)))
udpheader.PacketLenth = UintTo2byte(toByteLen(udpheader) + uint16(len(udpdata)))
// IPヘッダのチェックサムを計算する
ipsum := sumByteArr(toByteArr(ipheader))
ipheader.HeaderCheckSum = checksum(ipsum)
dummyHeader := NewUDPDummyHeader(ipheader)
dummyHeader.Length = udpheader.PacketLenth
sum := sumByteArr(toByteArr(dummyHeader))
sum += sumByteArr(toByteArr(udpheader))
sum += sumByteArr(udpdata)
// UDPヘッダ+データのチェックサムを計算する
udpheader.Checksum = checksum(sum)
var packet []byte
packet = append(packet, toByteArr(NewEthernet(localmac, localmac, "IPv4"))...)
packet = append(packet, toByteArr(ipheader)...)
packet = append(packet, toByteArr(udpheader)...)
packet = append(packet, udpdata...)
udpheader.Send(packet)
}