-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexisting.go
More file actions
87 lines (78 loc) · 2.07 KB
/
existing.go
File metadata and controls
87 lines (78 loc) · 2.07 KB
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
package l2
import (
"errors"
"net"
"unsafe"
)
/*
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <string.h>
#include <netinet/in.h>
socklen_t LLSize() {
return sizeof(struct sockaddr_ll);
}
*/
import "C"
// Represents an existing networking interface on the system.
type existingDevice struct {
dev C.int
name string
num C.int
}
func (e *existingDevice) String() string {
return "existingDevice{" + e.name + "}"
}
// Opens a connection to an existing networking interface on the system.
func ConnectExistingDevice(device string) (FrameReadWriter, error) {
sock, err := C.socket(C.AF_PACKET, C.SOCK_RAW, C.int(C.htons(C.ETH_P_ALL)))
if err != nil {
return nil, err
}
ll_addr := C.struct_sockaddr_ll{}
i, err := net.InterfaceByName(device)
if err != nil {
return nil, err
}
ll_addr.sll_family = C.AF_PACKET
ll_addr.sll_ifindex = C.int(i.Index)
ll_addr.sll_protocol = C.__be16(C.htons(C.ETH_P_ALL))
ll_addr.sll_pkttype = C.PACKET_HOST | C.PACKET_BROADCAST
ok, err := C.bind(sock, (*C.struct_sockaddr)(unsafe.Pointer(&ll_addr)), C.LLSize())
if err != nil {
return nil, err
}
if ok != 0 {
return nil, errors.New("bind return !ok")
}
return &existingDevice{sock, device, C.int(i.Index)}, nil
}
func (e *existingDevice) ReadFrame() (EthFrame, error) {
buffer := [1523]byte{}
n, err := C.recvfrom(e.dev, unsafe.Pointer(&buffer[0]), C.size_t(1523), 0, nil, nil)
if err != nil {
return nil, err
}
return buffer[0:n], nil
}
func (e *existingDevice) WriteFrame(data EthFrame) error {
socket_address := C.struct_sockaddr_ll{}
socket_address.sll_ifindex = e.num
socket_address.sll_halen = C.ETH_ALEN
_, err := C.memcpy(unsafe.Pointer(&socket_address.sll_addr[0]),
unsafe.Pointer(&data[0]), C.ETH_ALEN)
if err != nil {
return err
}
n, err := C.sendto(e.dev, unsafe.Pointer(&data[0]), C.size_t(len(data)),
0, (*C.struct_sockaddr)(unsafe.Pointer(&socket_address)), C.LLSize())
if err != nil {
return err
}
if int(n) != len(data) {
return errors.New("sent less data then len(data)")
}
return nil
}