github.com/olljanat/moby@v1.13.1/daemon/cluster/listen_addr_linux.go (about)

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