github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/daemon/cluster/listen_addr_linux.go (about)

     1  package cluster // import "github.com/demonoid81/moby/daemon/cluster"
     2  
     3  import (
     4  	"net"
     5  
     6  	"github.com/vishvananda/netlink"
     7  )
     8  
     9  func (c *Cluster) resolveSystemAddr() (net.IP, error) {
    10  	// Use the system's only device IP address, or fail if there are
    11  	// multiple addresses to choose from.
    12  	interfaces, err := netlink.LinkList()
    13  	if err != nil {
    14  		return nil, err
    15  	}
    16  
    17  	var (
    18  		systemAddr      net.IP
    19  		systemInterface string
    20  		deviceFound     bool
    21  	)
    22  
    23  	for _, intf := range interfaces {
    24  		// Skip non device or inactive interfaces
    25  		if intf.Type() != "device" || intf.Attrs().Flags&net.FlagUp == 0 {
    26  			continue
    27  		}
    28  
    29  		addrs, err := netlink.AddrList(intf, netlink.FAMILY_ALL)
    30  		if err != nil {
    31  			continue
    32  		}
    33  
    34  		var interfaceAddr4, interfaceAddr6 net.IP
    35  
    36  		for _, addr := range addrs {
    37  			ipAddr := addr.IPNet.IP
    38  
    39  			// Skip loopback and link-local addresses
    40  			if !ipAddr.IsGlobalUnicast() {
    41  				continue
    42  			}
    43  
    44  			// At least one non-loopback device is found and it is administratively up
    45  			deviceFound = true
    46  
    47  			if ipAddr.To4() != nil {
    48  				if interfaceAddr4 != nil {
    49  					return nil, errMultipleIPs(intf.Attrs().Name, intf.Attrs().Name, interfaceAddr4, ipAddr)
    50  				}
    51  				interfaceAddr4 = ipAddr
    52  			} else {
    53  				if interfaceAddr6 != nil {
    54  					return nil, errMultipleIPs(intf.Attrs().Name, intf.Attrs().Name, interfaceAddr6, ipAddr)
    55  				}
    56  				interfaceAddr6 = ipAddr
    57  			}
    58  		}
    59  
    60  		// In the case that this interface has exactly one IPv4 address
    61  		// and exactly one IPv6 address, favor IPv4 over IPv6.
    62  		if interfaceAddr4 != nil {
    63  			if systemAddr != nil {
    64  				return nil, errMultipleIPs(systemInterface, intf.Attrs().Name, systemAddr, interfaceAddr4)
    65  			}
    66  			systemAddr = interfaceAddr4
    67  			systemInterface = intf.Attrs().Name
    68  		} else if interfaceAddr6 != nil {
    69  			if systemAddr != nil {
    70  				return nil, errMultipleIPs(systemInterface, intf.Attrs().Name, systemAddr, interfaceAddr6)
    71  			}
    72  			systemAddr = interfaceAddr6
    73  			systemInterface = intf.Attrs().Name
    74  		}
    75  	}
    76  
    77  	if systemAddr == nil {
    78  		if !deviceFound {
    79  			// If no non-loopback device type interface is found,
    80  			// fall back to the regular auto-detection mechanism.
    81  			// This is to cover the case where docker is running
    82  			// inside a container (eths are in fact veths).
    83  			return c.resolveSystemAddrViaSubnetCheck()
    84  		}
    85  		return nil, errNoIP
    86  	}
    87  
    88  	return systemAddr, nil
    89  }