github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/daemon/cluster/listen_addr.go (about) 1 package cluster // import "github.com/docker/docker/daemon/cluster" 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 ) 8 9 const ( 10 errNoSuchInterface configError = "no such interface" 11 errNoIP configError = "could not find the system's IP address" 12 errMustSpecifyListenAddr configError = "must specify a listening address because the address to advertise is not recognized as a system address, and a system's IP address to use could not be uniquely identified" 13 errBadNetworkIdentifier configError = "must specify a valid IP address or interface name" 14 errBadListenAddr configError = "listen address must be an IP address or network interface (with optional port number)" 15 errBadAdvertiseAddr configError = "advertise address must be a non-zero IP address or network interface (with optional port number)" 16 errBadDataPathAddr configError = "data path address must be a non-zero IP address or network interface (without a port number)" 17 errBadDefaultAdvertiseAddr configError = "default advertise address must be a non-zero IP address or network interface (without a port number)" 18 ) 19 20 func resolveListenAddr(specifiedAddr string) (string, string, error) { 21 specifiedHost, specifiedPort, err := net.SplitHostPort(specifiedAddr) 22 if err != nil { 23 return "", "", fmt.Errorf("could not parse listen address %s", specifiedAddr) 24 } 25 // Does the host component match any of the interface names on the 26 // system? If so, use the address from that interface. 27 specifiedIP, err := resolveInputIPAddr(specifiedHost, true) 28 if err != nil { 29 if err == errBadNetworkIdentifier { 30 err = errBadListenAddr 31 } 32 return "", "", err 33 } 34 35 return specifiedIP.String(), specifiedPort, nil 36 } 37 38 func (c *Cluster) resolveAdvertiseAddr(advertiseAddr, listenAddrPort string) (string, string, error) { 39 // Approach: 40 // - If an advertise address is specified, use that. Resolve the 41 // interface's address if an interface was specified in 42 // advertiseAddr. Fill in the port from listenAddrPort if necessary. 43 // - If DefaultAdvertiseAddr is not empty, use that with the port from 44 // listenAddrPort. Resolve the interface's address from 45 // if an interface name was specified in DefaultAdvertiseAddr. 46 // - Otherwise, try to autodetect the system's address. Use the port in 47 // listenAddrPort with this address if autodetection succeeds. 48 49 if advertiseAddr != "" { 50 advertiseHost, advertisePort, err := net.SplitHostPort(advertiseAddr) 51 if err != nil { 52 // Not a host:port specification 53 advertiseHost = advertiseAddr 54 advertisePort = listenAddrPort 55 } 56 // Does the host component match any of the interface names on the 57 // system? If so, use the address from that interface. 58 advertiseIP, err := resolveInputIPAddr(advertiseHost, false) 59 if err != nil { 60 if err == errBadNetworkIdentifier { 61 err = errBadAdvertiseAddr 62 } 63 return "", "", err 64 } 65 66 return advertiseIP.String(), advertisePort, nil 67 } 68 69 if c.config.DefaultAdvertiseAddr != "" { 70 // Does the default advertise address component match any of the 71 // interface names on the system? If so, use the address from 72 // that interface. 73 defaultAdvertiseIP, err := resolveInputIPAddr(c.config.DefaultAdvertiseAddr, false) 74 if err != nil { 75 if err == errBadNetworkIdentifier { 76 err = errBadDefaultAdvertiseAddr 77 } 78 return "", "", err 79 } 80 81 return defaultAdvertiseIP.String(), listenAddrPort, nil 82 } 83 84 systemAddr, err := c.resolveSystemAddr() 85 if err != nil { 86 return "", "", err 87 } 88 return systemAddr.String(), listenAddrPort, nil 89 } 90 91 // validateDefaultAddrPool validates default address pool 92 // it also strips white space from the string before validation 93 func validateDefaultAddrPool(defaultAddrPool []string, size uint32) error { 94 if defaultAddrPool == nil { 95 // defaultAddrPool is not defined 96 return nil 97 } 98 //if size is not set, then we use default value 24 99 if size == 0 { 100 size = 24 101 } 102 // We allow max value as 29. We can have 8 IP addresses for max value 29 103 // If we allow 30, then we will get only 4 IP addresses. But with latest 104 // libnetwork LB scale implementation, we use total of 4 IP addresses for internal use. 105 // Hence keeping 29 as max value, we will have 8 IP addresses. This will be 106 // smallest subnet that can be used in overlay network. 107 if size > 29 { 108 return fmt.Errorf("subnet size is out of range: %d", size) 109 } 110 for i := range defaultAddrPool { 111 // trim leading and trailing white spaces 112 defaultAddrPool[i] = strings.TrimSpace(defaultAddrPool[i]) 113 _, b, err := net.ParseCIDR(defaultAddrPool[i]) 114 if err != nil { 115 return fmt.Errorf("invalid base pool %s: %v", defaultAddrPool[i], err) 116 } 117 ones, _ := b.Mask.Size() 118 if size < uint32(ones) { 119 return fmt.Errorf("invalid CIDR: %q. Subnet size is too small for pool: %d", defaultAddrPool[i], size) 120 } 121 } 122 123 return nil 124 } 125 126 func resolveDataPathAddr(dataPathAddr string) (string, error) { 127 if dataPathAddr == "" { 128 // dataPathAddr is not defined 129 return "", nil 130 } 131 // If a data path flag is specified try to resolve the IP address. 132 dataPathIP, err := resolveInputIPAddr(dataPathAddr, false) 133 if err != nil { 134 if err == errBadNetworkIdentifier { 135 err = errBadDataPathAddr 136 } 137 return "", err 138 } 139 return dataPathIP.String(), nil 140 } 141 142 func resolveInterfaceAddr(specifiedInterface string) (net.IP, error) { 143 // Use a specific interface's IP address. 144 intf, err := net.InterfaceByName(specifiedInterface) 145 if err != nil { 146 return nil, errNoSuchInterface 147 } 148 149 addrs, err := intf.Addrs() 150 if err != nil { 151 return nil, err 152 } 153 154 var interfaceAddr4, interfaceAddr6 net.IP 155 156 for _, addr := range addrs { 157 ipAddr, ok := addr.(*net.IPNet) 158 159 if ok { 160 if ipAddr.IP.To4() != nil { 161 // IPv4 162 if interfaceAddr4 != nil { 163 return nil, configError(fmt.Sprintf("interface %s has more than one IPv4 address (%s and %s)", specifiedInterface, interfaceAddr4, ipAddr.IP)) 164 } 165 interfaceAddr4 = ipAddr.IP 166 } else { 167 // IPv6 168 if interfaceAddr6 != nil { 169 return nil, configError(fmt.Sprintf("interface %s has more than one IPv6 address (%s and %s)", specifiedInterface, interfaceAddr6, ipAddr.IP)) 170 } 171 interfaceAddr6 = ipAddr.IP 172 } 173 } 174 } 175 176 if interfaceAddr4 == nil && interfaceAddr6 == nil { 177 return nil, configError(fmt.Sprintf("interface %s has no usable IPv4 or IPv6 address", specifiedInterface)) 178 } 179 180 // In the case that there's exactly one IPv4 address 181 // and exactly one IPv6 address, favor IPv4 over IPv6. 182 if interfaceAddr4 != nil { 183 return interfaceAddr4, nil 184 } 185 return interfaceAddr6, nil 186 } 187 188 // resolveInputIPAddr tries to resolve the IP address from the string passed as input 189 // - tries to match the string as an interface name, if so returns the IP address associated with it 190 // - on failure of previous step tries to parse the string as an IP address itself 191 // if succeeds returns the IP address 192 func resolveInputIPAddr(input string, isUnspecifiedValid bool) (net.IP, error) { 193 // Try to see if it is an interface name 194 interfaceAddr, err := resolveInterfaceAddr(input) 195 if err == nil { 196 return interfaceAddr, nil 197 } 198 // String matched interface but there is a potential ambiguity to be resolved 199 if err != errNoSuchInterface { 200 return nil, err 201 } 202 203 // String is not an interface check if it is a valid IP 204 if ip := net.ParseIP(input); ip != nil && (isUnspecifiedValid || !ip.IsUnspecified()) { 205 return ip, nil 206 } 207 208 // Not valid IP found 209 return nil, errBadNetworkIdentifier 210 } 211 212 func (c *Cluster) resolveSystemAddrViaSubnetCheck() (net.IP, error) { 213 // Use the system's only IP address, or fail if there are 214 // multiple addresses to choose from. Skip interfaces which 215 // are managed by docker via subnet check. 216 interfaces, err := net.Interfaces() 217 if err != nil { 218 return nil, err 219 } 220 221 var systemAddr net.IP 222 var systemInterface string 223 224 // List Docker-managed subnets 225 v4Subnets, v6Subnets := c.config.NetworkSubnetsProvider.Subnets() 226 227 ifaceLoop: 228 for _, intf := range interfaces { 229 // Skip inactive interfaces and loopback interfaces 230 if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 { 231 continue 232 } 233 234 addrs, err := intf.Addrs() 235 if err != nil { 236 continue 237 } 238 239 var interfaceAddr4, interfaceAddr6 net.IP 240 241 for _, addr := range addrs { 242 ipAddr, ok := addr.(*net.IPNet) 243 244 // Skip loopback and link-local addresses 245 if !ok || !ipAddr.IP.IsGlobalUnicast() { 246 continue 247 } 248 249 if ipAddr.IP.To4() != nil { 250 // IPv4 251 252 // Ignore addresses in subnets that are managed by Docker. 253 for _, subnet := range v4Subnets { 254 if subnet.Contains(ipAddr.IP) { 255 continue ifaceLoop 256 } 257 } 258 259 if interfaceAddr4 != nil { 260 return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr4, ipAddr.IP) 261 } 262 263 interfaceAddr4 = ipAddr.IP 264 } else { 265 // IPv6 266 267 // Ignore addresses in subnets that are managed by Docker. 268 for _, subnet := range v6Subnets { 269 if subnet.Contains(ipAddr.IP) { 270 continue ifaceLoop 271 } 272 } 273 274 if interfaceAddr6 != nil { 275 return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr6, ipAddr.IP) 276 } 277 278 interfaceAddr6 = ipAddr.IP 279 } 280 } 281 282 // In the case that this interface has exactly one IPv4 address 283 // and exactly one IPv6 address, favor IPv4 over IPv6. 284 if interfaceAddr4 != nil { 285 if systemAddr != nil { 286 return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr4) 287 } 288 systemAddr = interfaceAddr4 289 systemInterface = intf.Name 290 } else if interfaceAddr6 != nil { 291 if systemAddr != nil { 292 return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr6) 293 } 294 systemAddr = interfaceAddr6 295 systemInterface = intf.Name 296 } 297 } 298 299 if systemAddr == nil { 300 return nil, errNoIP 301 } 302 303 return systemAddr, nil 304 } 305 306 func listSystemIPs() []net.IP { 307 interfaces, err := net.Interfaces() 308 if err != nil { 309 return nil 310 } 311 312 var systemAddrs []net.IP 313 314 for _, intf := range interfaces { 315 addrs, err := intf.Addrs() 316 if err != nil { 317 continue 318 } 319 320 for _, addr := range addrs { 321 ipAddr, ok := addr.(*net.IPNet) 322 323 if ok { 324 systemAddrs = append(systemAddrs, ipAddr.IP) 325 } 326 } 327 } 328 329 return systemAddrs 330 } 331 332 func errMultipleIPs(interfaceA, interfaceB string, addrA, addrB net.IP) error { 333 if interfaceA == interfaceB { 334 return configError(fmt.Sprintf("could not choose an IP address to advertise since this system has multiple addresses on interface %s (%s and %s)", interfaceA, addrA, addrB)) 335 } 336 return configError(fmt.Sprintf("could not choose an IP address to advertise since this system has multiple addresses on different interfaces (%s on %s and %s on %s)", addrA, interfaceA, addrB, interfaceB)) 337 }