-
Notifications
You must be signed in to change notification settings - Fork 18.6k
/
listen_addr_linux.go
91 lines (76 loc) · 2.24 KB
/
listen_addr_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
// +build linux
package cluster
import (
"net"
"github.com/vishvananda/netlink"
)
func (c *Cluster) resolveSystemAddr() (net.IP, error) {
// Use the system's only device IP address, or fail if there are
// multiple addresses to choose from.
interfaces, err := netlink.LinkList()
if err != nil {
return nil, err
}
var (
systemAddr net.IP
systemInterface string
deviceFound bool
)
for _, intf := range interfaces {
// Skip non device or inactive interfaces
if intf.Type() != "device" || intf.Attrs().Flags&net.FlagUp == 0 {
continue
}
addrs, err := netlink.AddrList(intf, netlink.FAMILY_ALL)
if err != nil {
continue
}
var interfaceAddr4, interfaceAddr6 net.IP
for _, addr := range addrs {
ipAddr := addr.IPNet.IP
// Skip loopback and link-local addresses
if !ipAddr.IsGlobalUnicast() {
continue
}
// At least one non-loopback device is found and it is administratively up
deviceFound = true
if ipAddr.To4() != nil {
if interfaceAddr4 != nil {
return nil, errMultipleIPs(intf.Attrs().Name, intf.Attrs().Name, interfaceAddr4, ipAddr)
}
interfaceAddr4 = ipAddr
} else {
if interfaceAddr6 != nil {
return nil, errMultipleIPs(intf.Attrs().Name, intf.Attrs().Name, interfaceAddr6, ipAddr)
}
interfaceAddr6 = ipAddr
}
}
// In the case that this interface has exactly one IPv4 address
// and exactly one IPv6 address, favor IPv4 over IPv6.
if interfaceAddr4 != nil {
if systemAddr != nil {
return nil, errMultipleIPs(systemInterface, intf.Attrs().Name, systemAddr, interfaceAddr4)
}
systemAddr = interfaceAddr4
systemInterface = intf.Attrs().Name
} else if interfaceAddr6 != nil {
if systemAddr != nil {
return nil, errMultipleIPs(systemInterface, intf.Attrs().Name, systemAddr, interfaceAddr6)
}
systemAddr = interfaceAddr6
systemInterface = intf.Attrs().Name
}
}
if systemAddr == nil {
if !deviceFound {
// If no non-loopback device type interface is found,
// fall back to the regular auto-detection mechanism.
// This is to cover the case where docker is running
// inside a container (eths are in fact veths).
return c.resolveSystemAddrViaSubnetCheck()
}
return nil, errNoIP
}
return systemAddr, nil
}