Stage 1 gets overridded by most device subclasses and it turns out
they don't every chain back up to NMDevice's stage1 implementation.
It's a bit complicated to make them all do that, so for now just
move the IPv6 address config a bit later.
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.
This reverts commit 3d69429a1e.
Apparently the 'netdev' group rules aren't as widespread anymore
and Debian ships with ConsoleKit by default, and thus can
use at_console.
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.
Not all ethernet devices are immediately usable; newer mobile broadband
devices (Ericsson, Option, Sierra) require setup on the tty before the
ethernet device is usable. 2.6.33 and later kernels set the 'DEVTYPE'
uevent variable which we can use to ignore the interface as a NMDevice
subclass. ModemManager will pick it up though and so we'll handle it
through the mobile broadband stuff.
The error case was as follows. When using 'ifupdown,keyfile' plugins
and 'eth0' present in /etc/network/interfaces on a Debian-based system,
'ifupdown' plugin, in unmanaged mode, load_connections() prematurely
and thus effectively blocked reading connections from 'keyfile' plugin.
Patch by Dan and tested by me.
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 non-blocking connection is really only good for listening for
events. It doesn't work for request/response operations (like
refilling link and address caches) because the message receive loop
in libnl will break out from the EAGAIN before it gets the response
it needs to update the cache with.
This is most evident with link cache refills when requesting the
interface index from the name, or vice-versa; the refill request
exits early with EAGAIN (due to the non-blocking nature of the
connection's socket) and the cache isn't refilled, and the index
lookup fails. We need to use blocking netlink operations in quite
a few places besides index lookups, from address/route operations
to getting the initial device carrier state.
So, split the montior's netlink connection into a non-blocking
event listener connection, and a synchronous connection which gets
used for immediate operations. This also has the effect of
validation the synchronous operations for security, which wasn't
done before in nm-netlink.c (though it wasn't really a problem).
Got the flags wrong in the previous commit; MULTI isn't about
multicast/unicast, but about multi-part packets. Instead we need
to check the netlink sockaddr structure for the group mask.
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.
We need the IFLA_PROTINFO messages, and these are apparently sent
(still by the kernel) but with our own PID. So the current checks
that limit the netlink PID to zero block these messages out. Instead
(like udev) we should be checking the actual sender of the message
usign unix socket credentials.
Second, at least at this point only privileged processes can send
netlink multicast messages, so as long as the:
* the other end of the socket is UID 0 AND
* the netlink PID is 0 OR
* the message is multicast and sent to our netlink PID
the we accept the message and process it as normal. For another
example of this, see 'netlink.c' from the dhcp6s program; do a
Google search for "IFLA_PROTINFO" to find it.