In IPv4 the address assignment is coupled with the assignment of a subnet-mask — which means the insertion of a route to the given subnet.
In IPv6 address assignment is separate from on-link determination, for this an interface maintains a list of prefixes. All addresses matched by these prefixes are directly reachable. In addition routers may issue ICMPv6 redirects and the target of such a redirect is also on-link even if not contained in a known prefix of the interface.
dhclient from ISC doesn’t get this right, so I spent some time to learn why a prefix I wanted for an interface, which is different from /64, didn’t work. It turns out,
dhclient always configures an interface with a /64 subnet mask and associated route.
RFC4861 on IPv6 Neighbor Discovery later updated by RFC5942 “IPv6 Subnet Model: The Relationship between Links and Subnet Prefixes” makes clear that such prefixes may only be set by the following means (RFC5942, p.4)
The Prefix List is populated via the following means:
- Receipt of a valid Router Advertisement (RA) that specifies a prefix with the L-bit set. Such a prefix is considered on-link for a period specified in the Valid Lifetime and is added to the Prefix List. (The link-local prefix is effectively considered a permanent entry on the Prefix List.)
- Indication of an on-link prefix (which may be a /128) via manual configuration, or some other yet-to-be-specified configuration mechanism.
And makes clear this also holds for DHCPv6 (RFC5942, p.7):
The assignment of an IPv6 address — whether through IPv6 stateless address autoconfiguration [RFC4862], DHCPv6 [RFC3315], or manual configuration — MUST NOT implicitly cause a prefix derived from that address to be treated as on-link and added to the Prefix List. …
It even lists the bug if dhclient under the heading “Observed Incorrect Implementation Behavior” (RFC5942, p.8):
… An address could be acquired through the DHCPv6 identity association for non-temporary addresses (IA_NA) option from [RFC3315] (which does not include a prefix length), or through manual configuration (if no prefix length is specified). The host incorrectly assumes an invented prefix is on-link. This invented prefix typically is a /64 that was written by the developer of the operating system network module API to any IPv6 application as a “default” prefix length when a length isn’t specified…
And code inspection (client/dhc6.c, line 3844 dhcp-4.3.0a1) shows the value is really hard-coded in
/* Current practice is that all subnets are /64's, but * some suspect this may not be permanent. */ client_envadd(client, prefix, "ip6_prefixlen", "%d", 64); client_envadd(client, prefix, "ip6_address", "%s", piaddr(addr->address));
I’ve filed a bug-report (#35178, not the first one I discovered later as the bug-tracker doesn’t seem to be public, the reporter of the Debian bug also has submitted a report) and hope this will be fixed. The bug is present also in older versions, for example isc-dhcp-4.2.2 in Debian stable (wheezy). Debian also has a bug-report that references RFC 5942 which exists since 2012 (RFC 5942 is from 2010).
The fix would probably be to hard-code the netmask /128 for the newly-assigned address and leave the configuration to ICMPv6 router advertisements (see RFC4861).
I hope this will finally be fixed as dhcp is the only autoconfiguration mechanism in IPv6 that can handle netmasks different from /64 (on Ethernet, there may be other layer-2 protocols with a different interface identifier length for stateless autoconfiguration).