-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuland.go
130 lines (114 loc) · 2.88 KB
/
uland.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
128
129
130
package ulan
import (
"encoding/binary"
"errors"
"fmt"
"net"
"os"
"golang.org/x/net/ipv4"
)
type EthernetType uint16
const (
EthernetHdrSize = 14
IPHdrSize = 20
MTU = 1456
)
const (
// EthernetTypeLLC is not an actual ethernet type. It is instead a
// placeholder we use in Ethernet frames that use the 802.3 standard of
// srcmac|dstmac|length|LLC instead of srcmac|dstmac|ethertype.
EthernetTypeLLC EthernetType = 0
EthernetTypeIPv4 EthernetType = 0x0800
)
type Ethernet struct {
SrcMAC net.HardwareAddr
DstMAC net.HardwareAddr
EthernetType EthernetType
Length uint16
}
func (eth *Ethernet) decodeFromBytes(data []byte) error {
if len(data) < 14 {
return errors.New("Ethernet packet too small")
}
eth.DstMAC = net.HardwareAddr(data[0:6])
eth.SrcMAC = net.HardwareAddr(data[6:12])
eth.EthernetType = EthernetType(binary.BigEndian.Uint16(data[12:14]))
eth.Length = 0
if eth.EthernetType < 0x0600 {
eth.Length = uint16(eth.EthernetType)
eth.EthernetType = EthernetTypeLLC
}
return nil
}
func (eth *Ethernet) bytes() []byte {
data := make([]byte, EthernetHdrSize)
copy(data[0:], eth.DstMAC)
copy(data[6:], eth.SrcMAC)
copy(data[12:], []byte{0x0000})
return data
}
type IODevice struct {
fd *os.File
localMacAddress net.HardwareAddr
}
type EthernetFrame struct {
buffer [MTU]byte
len int
}
func (e *EthernetFrame) GetEthernet() (*Ethernet, error) {
var eth Ethernet
if len(e.buffer) < EthernetHdrSize {
return nil, errors.New("Ethernet packet too small")
}
eth.DstMAC = net.HardwareAddr(e.buffer[0:6])
eth.SrcMAC = net.HardwareAddr(e.buffer[6:12])
eth.EthernetType = EthernetType(binary.BigEndian.Uint16(e.buffer[12:14]))
eth.Length = 0
if eth.EthernetType < 0x0600 {
eth.Length = uint16(eth.EthernetType)
eth.EthernetType = EthernetTypeLLC
}
return ð, nil
}
func (e *EthernetFrame) GetIP() (*ipv4.Header, error) {
var ip ipv4.Header
if len(e.buffer) < EthernetHdrSize+IPHdrSize {
return nil, errors.New("Ethernet packet too smal")
}
ip.Parse(e.buffer[EthernetHdrSize:])
return &ip, nil
}
func (e *EthernetFrame) Len() int {
return e.len
}
func (e *EthernetFrame) RawIP() []byte {
return e.buffer[EthernetHdrSize:e.len]
}
func (io *IODevice) ReadEthFrame() (*EthernetFrame, error) {
var frame EthernetFrame
n, e := io.fd.Read(frame.buffer[:])
fmt.Println("Leido: ", n)
if e != nil {
return nil, e
}
frame.len = n
return &frame, nil
}
func (io *IODevice) WriteRawIP(pkt []byte) (int, error) {
var ip ipv4.Header
ip.Parse(pkt)
fmt.Println("Original len: ", len(pkt), ip.String())
// buf := make([]byte, EthernetHdrSize+len(pkt))
// copy(buf, io.localMacAddress)
// copy(buf[EthernetHdrSize:], pkt)
return io.fd.Write(pkt)
}
func UlanDriver() (*IODevice, error) {
file, err := os.OpenFile("/dev/ulan_io", os.O_RDWR, 0644)
if err != nil {
return nil, err
}
return &IODevice{
fd: file,
}, nil
}