github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/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 }