mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #26457 from aboch/auto
Add fallback to resolveSystemAddr() in linux
This commit is contained in:
commit
ebae43efc2
3 changed files with 111 additions and 93 deletions
|
@ -149,6 +149,101 @@ func resolveInterfaceAddr(specifiedInterface string) (net.IP, error) {
|
|||
return interfaceAddr6, nil
|
||||
}
|
||||
|
||||
func (c *Cluster) resolveSystemAddrViaSubnetCheck() (net.IP, error) {
|
||||
// Use the system's only IP address, or fail if there are
|
||||
// multiple addresses to choose from. Skip interfaces which
|
||||
// are managed by docker via subnet check.
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var systemAddr net.IP
|
||||
var systemInterface string
|
||||
|
||||
// List Docker-managed subnets
|
||||
v4Subnets := c.config.NetworkSubnetsProvider.V4Subnets()
|
||||
v6Subnets := c.config.NetworkSubnetsProvider.V6Subnets()
|
||||
|
||||
ifaceLoop:
|
||||
for _, intf := range interfaces {
|
||||
// Skip inactive interfaces and loopback interfaces
|
||||
if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := intf.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var interfaceAddr4, interfaceAddr6 net.IP
|
||||
|
||||
for _, addr := range addrs {
|
||||
ipAddr, ok := addr.(*net.IPNet)
|
||||
|
||||
// Skip loopback and link-local addresses
|
||||
if !ok || !ipAddr.IP.IsGlobalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipAddr.IP.To4() != nil {
|
||||
// IPv4
|
||||
|
||||
// Ignore addresses in subnets that are managed by Docker.
|
||||
for _, subnet := range v4Subnets {
|
||||
if subnet.Contains(ipAddr.IP) {
|
||||
continue ifaceLoop
|
||||
}
|
||||
}
|
||||
|
||||
if interfaceAddr4 != nil {
|
||||
return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr4, ipAddr.IP)
|
||||
}
|
||||
|
||||
interfaceAddr4 = ipAddr.IP
|
||||
} else {
|
||||
// IPv6
|
||||
|
||||
// Ignore addresses in subnets that are managed by Docker.
|
||||
for _, subnet := range v6Subnets {
|
||||
if subnet.Contains(ipAddr.IP) {
|
||||
continue ifaceLoop
|
||||
}
|
||||
}
|
||||
|
||||
if interfaceAddr6 != nil {
|
||||
return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr6, ipAddr.IP)
|
||||
}
|
||||
|
||||
interfaceAddr6 = ipAddr.IP
|
||||
}
|
||||
}
|
||||
|
||||
// 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.Name, systemAddr, interfaceAddr4)
|
||||
}
|
||||
systemAddr = interfaceAddr4
|
||||
systemInterface = intf.Name
|
||||
} else if interfaceAddr6 != nil {
|
||||
if systemAddr != nil {
|
||||
return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr6)
|
||||
}
|
||||
systemAddr = interfaceAddr6
|
||||
systemInterface = intf.Name
|
||||
}
|
||||
}
|
||||
|
||||
if systemAddr == nil {
|
||||
return nil, errNoIP
|
||||
}
|
||||
|
||||
return systemAddr, nil
|
||||
}
|
||||
|
||||
func listSystemIPs() []net.IP {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
|
|
|
@ -16,8 +16,11 @@ func (c *Cluster) resolveSystemAddr() (net.IP, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var systemAddr net.IP
|
||||
var systemInterface string
|
||||
var (
|
||||
systemAddr net.IP
|
||||
systemInterface string
|
||||
deviceFound bool
|
||||
)
|
||||
|
||||
for _, intf := range interfaces {
|
||||
// Skip non device or inactive interfaces
|
||||
|
@ -40,6 +43,9 @@ func (c *Cluster) resolveSystemAddr() (net.IP, error) {
|
|||
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)
|
||||
|
@ -71,6 +77,13 @@ func (c *Cluster) resolveSystemAddr() (net.IP, error) {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -5,95 +5,5 @@ package cluster
|
|||
import "net"
|
||||
|
||||
func (c *Cluster) resolveSystemAddr() (net.IP, error) {
|
||||
// Use the system's only IP address, or fail if there are
|
||||
// multiple addresses to choose from.
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var systemAddr net.IP
|
||||
var systemInterface string
|
||||
|
||||
// List Docker-managed subnets
|
||||
v4Subnets := c.config.NetworkSubnetsProvider.V4Subnets()
|
||||
v6Subnets := c.config.NetworkSubnetsProvider.V6Subnets()
|
||||
|
||||
ifaceLoop:
|
||||
for _, intf := range interfaces {
|
||||
// Skip inactive interfaces and loopback interfaces
|
||||
if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := intf.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var interfaceAddr4, interfaceAddr6 net.IP
|
||||
|
||||
for _, addr := range addrs {
|
||||
ipAddr, ok := addr.(*net.IPNet)
|
||||
|
||||
// Skip loopback and link-local addresses
|
||||
if !ok || !ipAddr.IP.IsGlobalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipAddr.IP.To4() != nil {
|
||||
// IPv4
|
||||
|
||||
// Ignore addresses in subnets that are managed by Docker.
|
||||
for _, subnet := range v4Subnets {
|
||||
if subnet.Contains(ipAddr.IP) {
|
||||
continue ifaceLoop
|
||||
}
|
||||
}
|
||||
|
||||
if interfaceAddr4 != nil {
|
||||
return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr4, ipAddr.IP)
|
||||
}
|
||||
|
||||
interfaceAddr4 = ipAddr.IP
|
||||
} else {
|
||||
// IPv6
|
||||
|
||||
// Ignore addresses in subnets that are managed by Docker.
|
||||
for _, subnet := range v6Subnets {
|
||||
if subnet.Contains(ipAddr.IP) {
|
||||
continue ifaceLoop
|
||||
}
|
||||
}
|
||||
|
||||
if interfaceAddr6 != nil {
|
||||
return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr6, ipAddr.IP)
|
||||
}
|
||||
|
||||
interfaceAddr6 = ipAddr.IP
|
||||
}
|
||||
}
|
||||
|
||||
// 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.Name, systemAddr, interfaceAddr4)
|
||||
}
|
||||
systemAddr = interfaceAddr4
|
||||
systemInterface = intf.Name
|
||||
} else if interfaceAddr6 != nil {
|
||||
if systemAddr != nil {
|
||||
return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr6)
|
||||
}
|
||||
systemAddr = interfaceAddr6
|
||||
systemInterface = intf.Name
|
||||
}
|
||||
}
|
||||
|
||||
if systemAddr == nil {
|
||||
return nil, errNoIP
|
||||
}
|
||||
|
||||
return systemAddr, nil
|
||||
return c.resolveSystemAddrViaSubnetCheck()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue