networkd: ndisc - handle router advertisement in userspace

Router Discovery is a core part of IPv6, which by default is handled by the kernel.
However, the kernel implementation is meant as a fall-back, and to fully support
the protocol a userspace implementation is desired.

The protocol essentially listens for Router Advertisement packets from routers
on the local link and use these to configure the client automatically. The four
main pieces of information are: what kind (if any) of DHCPv6 configuration should
be performed; a default gateway; the prefixes that should be considered to be on
the local link; and the prefixes with which we can preform SLAAC in order to pick
a global IPv6 address.

A lot of additional information is also available, which we do not yet fully
support, but which will eventually allow us to avoid the need for DHCPv6 in the
common case.

Short-term, the reason for wanting this is in userspace was the desire to fully
track all the addresses on links we manage, and that is not possible for addresses
managed by the kernel (as the kernel does not expose to us the fact that it
manages these addresses). Moreover, we would like to support stable privacy
addresses, which will soon be mandated and the legacy MAC-based global addresses
deprecated, to do this well we need to handle the generation in userspace. Lastly,
more long-term we wish to support more RA options than what the kernel exposes.
This commit is contained in:
Tom Gundersen
2015-11-11 15:42:38 +01:00
parent f5a8c43f39
commit 3b015d40c1
6 changed files with 172 additions and 27 deletions
+5 -6
View File
@@ -519,15 +519,14 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
stateful = ra->nd_ra_flags_reserved & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER);
switch (ra->nd_ra_flags_reserved & ND_RA_FLAG_PREF >> 3) {
pref = ra->nd_ra_flags_reserved & ND_RA_FLAG_PREF >> 3;
switch (pref) {
case ND_RA_FLAG_PREF_LOW:
pref = -1;
break;
case ND_RA_FLAG_PREF_HIGH:
pref = 1;
break;
default:
pref = 0;
pref = ND_RA_FLAG_PREF_MEDIUM;
break;
}
@@ -535,7 +534,7 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %u sec",
stateful & ND_RA_FLAG_MANAGED ? "MANAGED" : stateful & ND_RA_FLAG_OTHER ? "OTHER" : "none",
pref == 1 ? "high" : pref == -1 ? "low" : "medium",
pref == ND_RA_FLAG_PREF_HIGH ? "high" : pref == ND_RA_FLAG_PREF_LOW ? "low" : "medium",
lifetime);
r = ndisc_ra_parse(nd, ra, len);