diff --git a/src/net/ip.go b/src/net/ip.go index 9a6fda00e84b6..f3595715bcc5b 100644 --- a/src/net/ip.go +++ b/src/net/ip.go @@ -130,6 +130,19 @@ func (ip IP) IsMulticast() bool { return len(ip) == IPv6len && ip[0] == 0xff } +// IsLocal reports whether `ip' is a local address, according to +// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses). +func (ip IP) IsLocal() bool { + if ip4 := ip.To4(); ip4 != nil { + // Local IPv4 addresses are defined in https://tools.ietf.org/html/rfc1918 + return ip4[0] == 10 || + (ip4[0] == 172 && ip4[1]&0xf0 == 16) || + (ip4[0] == 192 && ip4[1] == 168) + } + // Local IPv6 addresses are defined in https://tools.ietf.org/html/rfc4193 + return len(ip) == IPv6len && ip[0]&0xfe == 0xfc +} + // IsInterfaceLocalMulticast reports whether ip is // an interface-local multicast address. func (ip IP) IsInterfaceLocalMulticast() bool { diff --git a/src/net/ip_test.go b/src/net/ip_test.go index a5fc5e644a2b2..8febbdd206c3b 100644 --- a/src/net/ip_test.go +++ b/src/net/ip_test.go @@ -666,6 +666,15 @@ var ipAddrScopeTests = []struct { {IP.IsMulticast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true}, {IP.IsMulticast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false}, {IP.IsMulticast, nil, false}, + {IP.IsLocal, nil, false}, + {IP.IsLocal, IPv4(10, 0, 0, 0), true}, + {IP.IsLocal, IPv4(11, 0, 0, 0), false}, + {IP.IsLocal, IPv4(172, 16, 0, 0), true}, + {IP.IsLocal, IPv4(172, 32, 0, 0), false}, + {IP.IsLocal, IPv4(192, 168, 0, 0), true}, + {IP.IsLocal, IPv4(192, 169, 0, 0), false}, + {IP.IsLocal, IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true}, + {IP.IsLocal, IP{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false}, {IP.IsInterfaceLocalMulticast, IPv4(224, 0, 0, 0), false}, {IP.IsInterfaceLocalMulticast, IPv4(0xff, 0x01, 0, 0), false}, {IP.IsInterfaceLocalMulticast, IPv6interfacelocalallnodes, true},