-
Notifications
You must be signed in to change notification settings - Fork 1
/
interface_tun_linux.go
110 lines (93 loc) · 2.17 KB
/
interface_tun_linux.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
// +build tun
package l2
import (
"fmt"
"net"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/songgao/water"
"github.com/vishvananda/netlink"
)
func (n *Network) SetupInterface() {
interfaceType := water.DeviceType(water.TUN)
iface, err := water.New(water.Config{
DeviceType: interfaceType,
PlatformSpecificParams: water.PlatformSpecificParams{
Name: fmt.Sprintf("L2-%s-%d", n.LocalNode.LanIP.String(), n.LocalNode.ID),
MultiQueue: true,
},
})
ce(err, "new interface")
link, err := netlink.LinkByName(iface.Name())
ce(err)
err = netlink.LinkSetUp(link)
ce(err)
err = netlink.AddrAdd(link, &netlink.Addr{
IPNet: &net.IPNet{
IP: n.LocalNode.LanIP,
Mask: n.Network.Mask,
},
})
ce(err)
err = netlink.LinkSetMTU(link, n.MTU)
ce(err)
err = netlink.SetPromiscOn(link)
ce(err)
n.iface = &fakeTAP{
iface: iface,
}
}
type fakeTAP struct {
iface *water.Interface
}
func (f *fakeTAP) Close() error {
return f.iface.Close()
}
func (f *fakeTAP) Name() string {
return f.iface.Name()
}
func (f *fakeTAP) Read(buf []byte) (n int, err error) {
n, err = f.iface.Read(buf[14:])
if err != nil {
return
}
n += 14
// decode ipv4 and fill MAC header
parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4)
var ipv4 layers.IPv4
parser.AddDecodingLayer(&ipv4)
decoded := make([]gopacket.LayerType, 0, 1)
parser.DecodeLayers(buf[14:n], &decoded)
dstMac := ip2Mac(ipv4.DstIP)
copy(buf[:6], dstMac)
srcMac := ip2Mac(ipv4.SrcIP)
copy(buf[6:12], srcMac)
buf[12] = 8
buf[13] = 0
return
}
func (f *fakeTAP) Write(buf []byte) (n int, err error) {
parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet)
var eth layers.Ethernet
var ipv4 layers.IPv4
var arp layers.ARP
parser.AddDecodingLayer(ð)
parser.AddDecodingLayer(&ipv4)
parser.AddDecodingLayer(&arp)
decoded := make([]gopacket.LayerType, 0, 5)
parser.DecodeLayers(buf, &decoded)
for _, t := range decoded {
switch t {
case layers.LayerTypeEthernet:
case layers.LayerTypeIPv4:
n, err = f.iface.Write(buf[14:])
if err != nil {
return
}
n += 14
return n, nil
case layers.LayerTypeARP:
}
}
return len(buf), nil
}