/
nic_linux.go
122 lines (102 loc) · 2.59 KB
/
nic_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
111
112
113
114
115
116
117
118
119
120
121
122
package tun
import (
"fmt"
"net/netip"
"github.com/vishvananda/netlink"
"go4.org/netipx"
)
func (d *Device) netLink() (netlink.Link, error) {
// Get link by index and check if the name matches.
nl, err := netlink.LinkByIndex(d.linkIndex)
if err == nil && nl.Attrs().Name == d.linkName {
return nl, nil
}
// Otherwise, get link by name and save the index.
nl, err = netlink.LinkByName(d.linkName)
if err != nil {
return nil, fmt.Errorf("get link %q by name: %w", d.linkName, err)
}
d.linkIndex = nl.Attrs().Index
return nl, nil
}
// PrepTUN prepares the creation of the TUN device.
func (d *Device) PrepTUN() {}
// InitInterface initializes the interface.
func (d *Device) InitInterface(prefix netip.Prefix) error {
nl, err := d.netLink()
if err != nil {
return err
}
// Set primary address.
err = netlink.AddrReplace(nl, &netlink.Addr{
IPNet: netipx.PrefixIPNet(prefix),
})
if err != nil {
return fmt.Errorf("set primary address: %w", err)
}
// Set interface flags.
err = netlink.LinkSetARPOff(nl)
if err != nil {
return fmt.Errorf("disable ARP: %w", err)
}
err = netlink.LinkSetAllmulticastOff(nl)
if err != nil {
return fmt.Errorf("disable multicast: %w", err)
}
return nil
}
// StartInterface starts the interface and brings it online.
func (d *Device) StartInterface() error {
nl, err := d.netLink()
if err != nil {
return err
}
// Take the interface online.
err = netlink.LinkSetUp(nl)
if err != nil {
return fmt.Errorf("set link to up: %w", err)
}
return nil
}
// AddAddress adds an address to the interface.
func (d *Device) AddAddress(prefix netip.Prefix) error {
nl, err := d.netLink()
if err != nil {
return err
}
return netlink.AddrReplace(nl, &netlink.Addr{
IPNet: netipx.PrefixIPNet(prefix),
})
}
// RemoveAddress removes an address from the interface.
func (d *Device) RemoveAddress(prefix netip.Prefix) error {
nl, err := d.netLink()
if err != nil {
return err
}
return netlink.AddrDel(nl, &netlink.Addr{
IPNet: netipx.PrefixIPNet(prefix),
})
}
// AddRoute adds a route to the interface.
func (d *Device) AddRoute(prefix netip.Prefix, highPrio bool) error {
metric := 0x7FFF_FFFF
if highPrio {
metric = 1
}
return netlink.RouteAdd(&netlink.Route{
LinkIndex: d.linkIndex,
Dst: netipx.PrefixIPNet(prefix),
Priority: metric,
Family: netlink.FAMILY_V6,
})
}
// RemoveRoute removes a route to the interface.
func (d *Device) RemoveRoute(prefix netip.Prefix) error {
return netlink.RouteDel(&netlink.Route{
LinkIndex: d.linkIndex,
Dst: netipx.PrefixIPNet(prefix),
Priority: 0,
Family: netlink.FAMILY_V6,
})
}