Repository navigation
Expand file tree
/
Copy pathnetworkinterface_linux.go
More file actions
146 lines (123 loc) · 3.6 KB
/
Copy pathnetworkinterface_linux.go
File metadata and controls
146 lines (123 loc) · 3.6 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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//go:build linux
// +build linux
package packemon
import (
"context"
"errors"
"net"
"strings"
"golang.org/x/sys/unix"
)
func NewInterfaceDevices() (InterfaceDevices, error) {
ids := []*InterfaceDevice{}
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, intf := range interfaces {
ipAddrs, err := intf.Addrs()
if err != nil {
return nil, err
}
addrs := make([]string, len(ipAddrs))
for i, addr := range ipAddrs {
addrs[i] = strings.Split(addr.String(), "/")[0]
}
id := &InterfaceDevice{
InterfaceName: intf.Name,
MacAddr: intf.HardwareAddr.String(),
IPAddrs: addrs,
}
ids = append(ids, id)
}
return ids, nil
}
type NetworkInterface struct {
Intf *net.Interface
Socket int // file discripter
SocketAddr unix.SockaddrLinklayer
IPAdder uint32
PassiveCh chan *Passive
}
func newNetworkInterface(nwInterface string) (*NetworkInterface, error) {
intf, err := getInterface(nwInterface)
if err != nil {
return nil, err
}
ipAddrs, err := intf.Addrs()
if err != nil {
return nil, err
}
if len(ipAddrs) == 0 {
return nil, errors.New("network interface may not have IP address configured")
}
// FIXME: IPv6で、「strconv.ParseUint: parsing "fe80::cc88:acff:fee5:73fd"」のエラーが出ていた
// 現状、ipAddrは使われてないので、パース失敗しても実害はない。なので一旦errを無視する
ipAddr, err := StrIPToBytes(strings.Split(ipAddrs[0].String(), "/")[0])
_, _ = ipAddr, err
// if err != nil {
// return nil, err
// }
// https://ja.manpages.org/af_packet/7 のリンク先に、以下コード1行分の説明あり. ためになる.
// https://github.com/pandax381/seccamp2024 の README にリンクされているスライドもためになる(「KLab Expert Camp 6 - Day3」のとこ).
// また、上記スライドに各OSで直接Ethernetフレームを送受信する手段についてもヒントあり.
sock, err := unix.Socket(unix.AF_PACKET, unix.SOCK_RAW, int(hton(unix.ETH_P_ALL)))
if err != nil {
return nil, err
}
addr := unix.SockaddrLinklayer{
Protocol: hton(unix.ETH_P_ALL),
Ifindex: intf.Index,
}
if err := unix.Bind(sock, &addr); err != nil {
return nil, err
}
return &NetworkInterface{
Intf: intf,
Socket: sock,
SocketAddr: addr,
// IPAdder: binary.BigEndian.Uint32(ipAddr), // FIXME: どこにも使われてなかったからわからなかったけど、IPv6アドレスだとダメ
PassiveCh: make(chan *Passive, 100),
}, nil
}
func getInterface(nwInterface string) (*net.Interface, error) {
// any で全てのインタフェースを取得しない限り、net.InterfaceByName で取得がいいかもしれない
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
var intf *net.Interface
for i := range interfaces {
if interfaces[i].Name == nwInterface {
intf = &interfaces[i]
}
}
if intf == nil {
return nil, errors.New("specified interface did not exist")
}
return intf, nil
}
func (nw *NetworkInterface) send(ethernetFrame *EthernetFrame) error {
return unix.Sendto(nw.Socket, ethernetFrame.Bytes(), 0, &nw.SocketAddr)
}
func (nw *NetworkInterface) recieve(ctx context.Context, shouldParseFull bool) error {
for {
select {
case <-ctx.Done():
return nil
default:
recieved := make([]byte, 1500)
n, _, err := unix.Recvfrom(nw.Socket, recieved, 0)
if err != nil {
if n == -1 {
continue
}
return err
}
nw.PassiveCh <- ParsedPacket(recieved[:n], shouldParseFull)
}
}
}
func (nw *NetworkInterface) close() error {
return unix.Close(nw.Socket)
}