Like if the IP interface doesn't have an ifindex yet. Previously
the connection would just go merrily along and wait for IPv6 to
complete even though it had already failed. Happens if you try
to do IPv6 on mobile broadband connections, which we'll add support
for later.
RFC6101 adds the DNS Search List option to router advertisements. This
allows stateless configuration of suffixes to try when doing DNS lookups.
Make sure we catch these when provided by the kernel and reconfigure
things appropriately.
NOTE: this commit depends on a kernel patch:
http://marc.info/?l=linux-netdev&m=129216173321352&w=2
RFC5006/RFC6106 specifies fairly clearly how to handle multiple RDDNS options.
Unfortunately the previous code didn't deal with this and hence would
misbehave in all but the simplest setups. The new code should be fully
compliant with the following exceptions:
- Router lifetime not respected
- No "sufficient number" management.
- DHCPv6 servers might not be prioritised over RDDNS ones.
Pad the DNS server expiry somewhat to give a bit of slack in cases
where one RA gets lost or something (which can happen on unreliable
links like wifi where certain types of frames are not retransmitted).
The kernel apparently caches the value and will send Managed/Other flags
in the newlink message even if the router is no longer reachable and
and RA hasn't been received for a while. So we need to make sure we
check for IF_RA_RCVD before paying attention to Managed/Other.
The RA interval is configurable on the router and we don't want
to miss one. 20s is still a lot less than we allow for DHCP so
the latency isn't that big of an issue.
Two things:
1) we need to bounce IPv6 on the interface because otherwise the
kernel won't start listening for new RAs. So code gets added
to handle the 'disable_ipv6' /proc/sys/net/ipv6 parameter for
each interface.
2) Second, we need to grab a default route (if we find one) before
reading addresses, so that we can add it to each address that we
get out of the kernel. Most of the time we'll get an -EEXIST error
when adding address, but that's OK since we're just trying to add
the same route back that the kernel already added from the RA. We
also need to make sure the route and address caches are up-to-date
otherwise we won't get a complete picture of the routing table.
Poll the device's IPv6 flags so we're notified when the RA has
been parsed and what the flags are. Only when that's complete
and the device's target state has been reached (or Managed mode
was indicated by the RA) should we continue with IP configuration.
Where we can do so, let's use ifindex since that's actually unique
and doesn't change when the interface name changes. We already use
ifindex in a bunch of places, and netlink *only* uses ifindex, so
this will make it easier later when we move over to ifindexes fully.
The RA flags aren't in the link flags, they are in the special
PROTINFO flags that the IPv6 stack sends. To get these, because
libnl doesn't have native support for them, we get to parse the
netlink messages directly. Furthermore, the PROTINFO message
isn't sent unless it's explicitly requested with a
RTM_GETLINK/AF_INET6 message, meaning we get to poll for it
periodically.
So switch over to the netlink monitor object (killing a lot of
duplicate code) and start requesting the PROTINFO bits from
netlink.
device->want_signal was never set to TRUE when addrconf was started,
causing random netlink events (say for link-local address addition
or removal) to trigger the config-changed signal from
nm_ip6_device_sync_from_netlink() at the wrong time. This would
cause IPv6 address configuration to look like it succeeded, when
in fact the config timeout was still in-force. Thus device
activation would proceed if IPv4 was enabled, but a few seconds later
the device would be deactivated due to the still active IPv6
timeout.
So fix that and clarify when the events from the IPv6 manager happen,
and what the want_signal variable is really for.
Automatic IPv6 configuration is handled by the kernel, but to
integrate it properly with NetworkManager, we need to watch what the
kernel does to see whether or not it was successful (so that we can
let the user know if there is no IPv6 router present, for example).
NMIP6Manager takes care of this.