always select non link-local interface, fixes #11961
The API server will refuse to start if a link-local IP address is selected, however, ChooseNetworkInterface can still select link-local network routes. This causes a startup failure on platforms like DigitalOcean that use a link-local route to fetch metadata. Signed-off-by: Christian Stewart <christian@paral.in>
This commit is contained in:
		| @@ -321,7 +321,7 @@ func isInterfaceUp(intf *net.Interface) bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| //getFinalIP method receives all the IP addrs of a Interface | //getFinalIP method receives all the IP addrs of a Interface | ||||||
| //and returns a nil if the address is Loopback , Ipv6  or nil. | //and returns a nil if the address is Loopback, Ipv6, link-local or nil. | ||||||
| //It returns a valid IPv4 if an Ipv4 address is found in the array. | //It returns a valid IPv4 if an Ipv4 address is found in the array. | ||||||
| func getFinalIP(addrs []net.Addr) (net.IP, error) { | func getFinalIP(addrs []net.Addr) (net.IP, error) { | ||||||
| 	if len(addrs) > 0 { | 	if len(addrs) > 0 { | ||||||
| @@ -334,11 +334,11 @@ func getFinalIP(addrs []net.Addr) (net.IP, error) { | |||||||
| 			//Only IPv4 | 			//Only IPv4 | ||||||
| 			//TODO : add IPv6 support | 			//TODO : add IPv6 support | ||||||
| 			if ip.To4() != nil { | 			if ip.To4() != nil { | ||||||
| 				if !ip.IsLoopback() { | 				if !ip.IsLoopback() && !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() { | ||||||
| 					glog.V(4).Infof("IP found %v", ip) | 					glog.V(4).Infof("IP found %v", ip) | ||||||
| 					return ip, nil | 					return ip, nil | ||||||
| 				} else { | 				} else { | ||||||
| 					glog.V(4).Infof("Loopback found %v", ip) | 					glog.V(4).Infof("Loopback/link-local found %v", ip) | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				glog.V(4).Infof("%v is not a valid IPv4 address", ip) | 				glog.V(4).Infof("%v is not a valid IPv4 address", ip) | ||||||
| @@ -399,7 +399,9 @@ func chooseHostInterfaceNativeGo() (net.IP, error) { | |||||||
| 					if addrIP, _, err := net.ParseCIDR(addr.String()); err == nil { | 					if addrIP, _, err := net.ParseCIDR(addr.String()); err == nil { | ||||||
| 						if addrIP.To4() != nil { | 						if addrIP.To4() != nil { | ||||||
| 							ip = addrIP.To4() | 							ip = addrIP.To4() | ||||||
| 							break | 							if !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() { | ||||||
|  | 								break | ||||||
|  | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -379,6 +379,12 @@ docker0	000011AC	00000000	0001	0	0	0	0000FFFF	0	0	0 | |||||||
| virbr0	007AA8C0	00000000	0001	0	0	0	00FFFFFF	0	0	0 | virbr0	007AA8C0	00000000	0001	0	0	0	00FFFFFF	0	0	0 | ||||||
| ` | ` | ||||||
|  |  | ||||||
|  | // Based on DigitalOcean COREOS | ||||||
|  | const gatewayfirstLinkLocal = `Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask            MTU     Window  IRTT                                                        | ||||||
|  | eth0    00000000        0120372D        0001    0       0       0       00000000        0       0       0                                                                                | ||||||
|  | eth0    00000000        00000000        0001    0       0       2048    00000000        0       0       0                                                                             | ||||||
|  | ` | ||||||
|  |  | ||||||
| func TestGetRoutes(t *testing.T) { | func TestGetRoutes(t *testing.T) { | ||||||
| 	testCases := []struct { | 	testCases := []struct { | ||||||
| 		tcase    string | 		tcase    string | ||||||
| @@ -499,6 +505,19 @@ func (_ validNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { | |||||||
| 	return ifat, nil | 	return ifat, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type validNetworkInterfaceWithLinkLocal struct { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (_ validNetworkInterfaceWithLinkLocal) InterfaceByName(intfName string) (*net.Interface, error) { | ||||||
|  | 	c := net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: net.FlagUp} | ||||||
|  | 	return &c, nil | ||||||
|  | } | ||||||
|  | func (_ validNetworkInterfaceWithLinkLocal) Addrs(intf *net.Interface) ([]net.Addr, error) { | ||||||
|  | 	var ifat []net.Addr | ||||||
|  | 	ifat = []net.Addr{addrStruct{val: "169.254.162.166/16"}, addrStruct{val: "45.55.47.146/19"}} | ||||||
|  | 	return ifat, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| type validNetworkInterfacewithIpv6Only struct { | type validNetworkInterfacewithIpv6Only struct { | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -577,6 +596,7 @@ func TestChooseHostInterfaceFromRoute(t *testing.T) { | |||||||
| 		{"valid_routemiddle", strings.NewReader(gatewaymiddle), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, | 		{"valid_routemiddle", strings.NewReader(gatewaymiddle), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, | ||||||
| 		{"valid_routemiddle_ipv6", strings.NewReader(gatewaymiddle), validNetworkInterfacewithIpv6Only{}, nil}, | 		{"valid_routemiddle_ipv6", strings.NewReader(gatewaymiddle), validNetworkInterfacewithIpv6Only{}, nil}, | ||||||
| 		{"no internet connection", strings.NewReader(noInternetConnection), validNetworkInterface{}, nil}, | 		{"no internet connection", strings.NewReader(noInternetConnection), validNetworkInterface{}, nil}, | ||||||
|  | 		{"no non-link-local ip", strings.NewReader(gatewayfirstLinkLocal), validNetworkInterfaceWithLinkLocal{}, net.ParseIP("45.55.47.146")}, | ||||||
| 		{"no route", strings.NewReader(nothing), validNetworkInterface{}, nil}, | 		{"no route", strings.NewReader(nothing), validNetworkInterface{}, nil}, | ||||||
| 		{"no route file", nil, validNetworkInterface{}, nil}, | 		{"no route file", nil, validNetworkInterface{}, nil}, | ||||||
| 		{"no interfaces", nil, noNetworkInterface{}, nil}, | 		{"no interfaces", nil, noNetworkInterface{}, nil}, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Christian Stewart
					Christian Stewart