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 }