diff --git a/machine/coreos.go b/machine/coreos.go index e4243a440..9ffceed00 100644 --- a/machine/coreos.go +++ b/machine/coreos.go @@ -119,27 +119,38 @@ func readLocalMachineID(root string) (string, error) { return mID, nil } -func getLocalIP() string { +func getLocalIP() (got string) { iface := getDefaultGatewayIface() if iface == nil { - return "" + return } addrs, err := iface.Addrs() if err != nil || len(addrs) == 0 { - return "" + return } for _, addr := range addrs { // Attempt to parse the address in CIDR notation - // and assert it is IPv4 + // and assert that it is IPv4 and global unicast ip, _, err := net.ParseCIDR(addr.String()) - if err == nil && ip.To4() != nil { - return ip.String() + if err != nil { + continue } + + if !usableAddress(ip) { + continue + } + + got = ip.String() + break } - return "" + return +} + +func usableAddress(ip net.IP) bool { + return ip.To4() != nil && ip.IsGlobalUnicast() } func getDefaultGatewayIface() *net.Interface { diff --git a/machine/coreos_test.go b/machine/coreos_test.go index 04cc8e493..88f58ad4b 100644 --- a/machine/coreos_test.go +++ b/machine/coreos_test.go @@ -2,6 +2,7 @@ package machine import ( "io/ioutil" + "net" "os" "path/filepath" "testing" @@ -49,3 +50,39 @@ func TestReadLocalMachineIDFound(t *testing.T) { t.Fatalf("Received incorrect machID %q, expected 'pingpong'", machID) } } + +func TestUsableAddress(t *testing.T) { + tests := []struct { + ip net.IP + ok bool + }{ + // unicast IPv4 usable + {net.ParseIP("192.168.1.12"), true}, + + // unicast IPv6 unusable + {net.ParseIP("2001:DB8::3"), false}, + + // loopback IPv4/6 unusable + {net.ParseIP("127.0.0.12"), false}, + {net.ParseIP("::1"), false}, + + // link-local IPv4/6 unusable + {net.ParseIP("169.254.4.87"), false}, + {net.ParseIP("fe80::12"), false}, + + // unspecified (all zeros) IPv4/6 unusable + {net.ParseIP("0.0.0.0"), false}, + {net.ParseIP("::"), false}, + + // multicast IPv4/6 unusable + {net.ParseIP("239.255.255.250"), false}, + {net.ParseIP("ffx2::4"), false}, + } + + for i, tt := range tests { + ok := usableAddress(tt.ip) + if tt.ok != ok { + t.Errorf("case %d: expected %v usable %t, got %t", i, tt.ip, tt.ok, ok) + } + } +}