inetaf/netaddr

netaddr.IP.IsLinkLocalUnicast() disagrees with net.IP

moreati opened this issue · 2 comments

For the IPv6 address feb0::0

netaddr.IP.IsLinkLocalUnicast() == false
net.IP.IsLinkLocalUnicast() == true

I believe netaddr.IP is in error, and net.IP may be correct. It's possible both are in error, but I don't think so.

RFC4291 section 2.4

The type of an IPv6 address is identified by the high-order bits of the address, as follows:

Address type Binary prefix IPv6 notation Section
...
Link-Local unicast 1111111010 FE80::/10 2.5.6

netaddr

netaddr.IP.IsLinkLocalUnicast() only checks the first 16 bits equal 0xfeb0, it doesn't mask.

return ip.v6u16(0) == 0xfe80

net

net.IP.IsLinkLocalUnicast() (since golang/go@91ba0ab in go 1.5beta2 ) checks the first byte equals 0xfe, and the second byte masked with 0b1100_0000 == 0b1000_0000

    return len(ip) == IPv6len && ip[0] == 0xfe && ip[1]&0xc0 == 0x80

-- https://github.com/golang/go/blob/f22ec51debeddc0903096e66bfaf641568bede3b/src/net/ip.go#L179

Analysis

Going purely from RFC4291 section 2.4 I would expect the correct test to be

    return ip.v6u16(0) & 0xffc0 == 0xfe80

where

  • 0xffc0 == 0b1111_1111_1100_0000 is the netmask
  • 0xfe80 == 0b1111_1110_1000_0000 is the prefix

Whoops. Thanks for the report!

PR incoming, this was found as part of #182