-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathutil_linux.go
More file actions
151 lines (132 loc) · 3.89 KB
/
util_linux.go
File metadata and controls
151 lines (132 loc) · 3.89 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
147
148
149
150
151
//go:build linux
// +build linux
package ocicni
import (
"fmt"
"net"
"os/exec"
"strings"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/vishvananda/netlink"
)
var defaultNamespaceEnterCommandName = "nsenter"
type nsManager struct {
nsenterPath string
}
func (nsm *nsManager) init() error {
var err error
nsm.nsenterPath, err = exec.LookPath(defaultNamespaceEnterCommandName)
return err
}
func getContainerDetails(nsm *nsManager, netnsPath, interfaceName, addrType string) (*net.IPNet, *net.HardwareAddr, error) {
// Try to retrieve ip inside container network namespace
output, err := exec.Command(nsm.nsenterPath, fmt.Sprintf("--net=%s", netnsPath), "-F", "--",
"ip", "-o", addrType, "addr", "show", "dev", interfaceName, "scope", "global").CombinedOutput()
if err != nil {
return nil, nil, fmt.Errorf("Unexpected command output %s with error: %v", output, err)
}
lines := strings.Split(string(output), "\n")
if len(lines) < 1 {
return nil, nil, fmt.Errorf("Unexpected command output %s", output)
}
fields := strings.Fields(lines[0])
if len(fields) < 4 {
return nil, nil, fmt.Errorf("Unexpected address output %s ", lines[0])
}
ip, ipNet, err := net.ParseCIDR(fields[3])
if err != nil {
return nil, nil, fmt.Errorf("CNI failed to parse ip from output %s due to %v", output, err)
}
if ip.To4() == nil {
ipNet.IP = ip
} else {
ipNet.IP = ip.To4()
}
// Try to retrieve MAC inside container network namespace
output, err = exec.Command(nsm.nsenterPath, fmt.Sprintf("--net=%s", netnsPath), "-F", "--",
"ip", "link", "show", "dev", interfaceName).CombinedOutput()
if err != nil {
return nil, nil, fmt.Errorf("unexpected 'ip link' command output %s with error: %v", output, err)
}
lines = strings.Split(string(output), "\n")
if len(lines) < 2 {
return nil, nil, fmt.Errorf("unexpected 'ip link' command output %s", output)
}
fields = strings.Fields(lines[1])
if len(fields) < 4 {
return nil, nil, fmt.Errorf("unexpected link output %s ", lines[0])
}
mac, err := net.ParseMAC(fields[1])
if err != nil {
return nil, nil, fmt.Errorf("failed to parse MAC from output %s due to %v", output, err)
}
return ipNet, &mac, nil
}
func tearDownLoopback(netns string) error {
return ns.WithNetNSPath(netns, func(_ ns.NetNS) error {
link, err := netlink.LinkByName(loIfname)
if err != nil {
return err // not tested
}
err = netlink.LinkSetDown(link)
if err != nil {
return err // not tested
}
return nil
})
}
func bringUpLoopback(netns string) error {
if err := ns.WithNetNSPath(netns, func(_ ns.NetNS) error {
link, err := netlink.LinkByName(loIfname)
if err == nil {
err = netlink.LinkSetUp(link)
}
if err != nil {
return err
}
v4Addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return err
}
if len(v4Addrs) != 0 {
// sanity check that this is a loopback address
for _, addr := range v4Addrs {
if !addr.IP.IsLoopback() {
return fmt.Errorf("loopback interface found with non-loopback address %q", addr.IP)
}
}
}
v6Addrs, err := netlink.AddrList(link, netlink.FAMILY_V6)
if err != nil {
return err
}
if len(v6Addrs) != 0 {
// sanity check that this is a loopback address
for _, addr := range v6Addrs {
if !addr.IP.IsLoopback() {
return fmt.Errorf("loopback interface found with non-loopback address %q", addr.IP)
}
}
}
return nil
}); err != nil {
return fmt.Errorf("error adding loopback interface: %s", err)
}
return nil
}
func checkLoopback(netns string) error {
// Make sure loopback interface is up
if err := ns.WithNetNSPath(netns, func(_ ns.NetNS) error {
link, err := netlink.LinkByName(loIfname)
if err != nil {
return err
}
if link.Attrs().Flags&net.FlagUp != net.FlagUp {
return fmt.Errorf("loopback interface is down")
}
return nil
}); err != nil {
return fmt.Errorf("error checking loopback interface: %v", err)
}
return nil
}