From 30763bbf3f1bb21b0c13612f82323f55b8bc6eb8 Mon Sep 17 00:00:00 2001 From: Konstantin Itskov Date: Sat, 2 Mar 2019 18:56:49 -0500 Subject: [PATCH] Update LocalInterfaces() to comply with spec Resolves #466 --- util.go | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/util.go b/util.go index 886f17f..0d9e91e 100644 --- a/util.go +++ b/util.go @@ -18,21 +18,34 @@ func localInterfaces() (ips []net.IP) { if iface.Flags&net.FlagLoopback != 0 { continue // loopback interface } + addrs, err := iface.Addrs() if err != nil { return ips } + for _, addr := range addrs { var ip net.IP - switch v := addr.(type) { + switch addr := addr.(type) { case *net.IPNet: - ip = v.IP + ip = addr.IP case *net.IPAddr: - ip = v.IP + ip = addr.IP + } + if ip == nil || ip.IsLoopback() { continue } + + // The conditions of invalidation written below are defined in + // https://tools.ietf.org/html/rfc8445#section-5.1.1.1 + if ipv4 := ip.To4(); ipv4 == nil { + if !isSupportedIPv6(ip) { + continue + } + } + ips = append(ips, ip) } } @@ -48,3 +61,23 @@ func (a *atomicError) Load() error { err, _ := a.v.Load().(struct{ error }) return err.error } + +func isSupportedIPv6(ip net.IP) bool { + if len(ip) != net.IPv6len || + !isZeros(ip[0:12]) || // !(IPv4-compatible IPv6) + ip[0] == 0xfe && ip[1]&0xc0 == 0xc0 || // !(IPv6 site-local unicast) + ip.IsLinkLocalUnicast() || + ip.IsLinkLocalMulticast() { + return false + } + return true +} + +func isZeros(ip net.IP) bool { + for i := 0; i < len(ip); i++ { + if ip[i] != 0 { + return false + } + } + return true +}