This patch fixes NM's incorrect assumption that SLAAC and Stateful
DHCPv6 are mutually exclusive configuration methods. It does this by
lowering the initial target state of the device to "got-ra" rather than
the previous "got-address" (which implies SLAAC has been performed, not
DHCPv6). If an RA is seen containing a prefix with the Autonomous flag
set, the target state is increased to "got-address" so that NM will
expect the kernel to perform SLAAC.
A side-effect of lowering the initial target state to "got-ra" is that
will be possible for a connection to succeed even if NM has not
configured any (non-link-local) addresses. This will happen if the RA
received has the Managed flag unset, and also contains no Prefix
Information Options (or that all PIOs have the Autonomous flag unset).
While such a connection may be of questionable usability to an end user,
calling it a success it not really unreasonable; after all, NM will have
successfully configured the host according to the network admin's
specifications (which could include addition of a default routes,
on-link prefix routes, recursive DNS servers, and so forth).
It also improves some debugging output that incorrectly implied that
Stateful DHCPv6 supersede RA/SLAAC and that Information-Only DHCPv6 is
the only form of DHCPv6 that should be done in parallel with SLAAC.
The patch will not apply cleanly without "[PATCH] ip6-manager: Accept
RAs when forwarding". The two patches are functionally independent of
each other, though.
(rh #720188)
---
src/ip6-manager/nm-ip6-manager.c | 33 ++++++++++++++++++++-------------
1 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c
index 03f5cc4..8ccdc11 100644
--- a/src/ip6-manager/nm-ip6-manager.c
+++ b/src/ip6-manager/nm-ip6-manager.c
@@ -41,6 +41,8 @@
#define IF_RA_MANAGED 0x40
#define IF_RA_RCVD 0x20
#define IF_RS_SENT 0x10
+#define IF_PREFIX_ONLINK 0x01
+#define IF_PREFIX_AUTOCONF 0x02
typedef struct {
NMNetlinkMonitor *monitor;
@@ -68,7 +70,7 @@ typedef enum {
NM_IP6_DEVICE_UNCONFIGURED,
NM_IP6_DEVICE_GOT_LINK_LOCAL,
NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT,
- NM_IP6_DEVICE_GOT_ADDRESS,
+ NM_IP6_DEVICE_GOT_ADDRESS, /* Note: Used for SLAAC only, not DHCPv6 */
NM_IP6_DEVICE_TIMED_OUT
} NMIP6DeviceState;
@@ -459,8 +461,7 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device,
gboolean config_changed)
nm_log_dbg (LOGD_IP6, "(%s): addresses synced (state %s)",
device->iface, state_to_string (device->state));
- /* We only care about router advertisements if we want a real IPv6
address */
- if ( (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS)
+ if ( (device->target_state >= NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT)
&& (device->ra_flags & IF_RA_RCVD)) {
if (device->state < NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT)
@@ -468,27 +469,22 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device,
gboolean config_changed)
if (device->ra_flags & IF_RA_MANAGED) {
dhcp_opts = IP6_DHCP_OPT_MANAGED;
- nm_log_dbg (LOGD_IP6, "router advertisement deferred to
DHCPv6");
+ nm_log_dbg (LOGD_IP6, "router advertisement requests
Stateful DHCPv6");
} else if (device->ra_flags & IF_RA_OTHERCONF) {
dhcp_opts = IP6_DHCP_OPT_OTHERCONF;
- nm_log_dbg (LOGD_IP6, "router advertisement requests
parallel DHCPv6");
+ nm_log_dbg (LOGD_IP6, "router advertisement requests
Information-Only DHCPv6");
}
}
if (!device->addrconf_complete) {
- /* Managed mode (ie DHCP only) short-circuits automatic
addrconf, so
- * we don't bother waiting for the device's target state to be
reached
- * when the RA requests managed mode.
- */
- if ( (device->state >= device->target_state)
- || (dhcp_opts == IP6_DHCP_OPT_MANAGED)) {
+ if (device->state >= device->target_state) {
/* device->finish_addrconf_id may currently be a timeout
* rather than an idle, so we remove the existing
source.
*/
if (device->finish_addrconf_id)
g_source_remove (device->finish_addrconf_id);
- nm_log_dbg (LOGD_IP6, "(%s): reached target state or
Managed-mode requested (state '%s') (dhcp opts 0x%X)",
+ nm_log_dbg (LOGD_IP6, "(%s): reached target state
(state '%s') (dhcp opts 0x%X)",
device->iface, state_to_string
(device->state),
dhcp_opts);
@@ -631,6 +627,12 @@ process_prefix (NMIP6Manager *manager, struct nl_msg *msg)
return NULL;
}
+ if(pmsg->prefix_flags & IF_PREFIX_AUTOCONF) {
+ nm_log_dbg (LOGD_IP6, "(%s): prefix requests stateless
autoconf",
+ device->iface);
+ device->target_state = NM_IP6_DEVICE_GOT_ADDRESS;
+ }
+
return device;
}
@@ -1088,7 +1090,12 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
device->target_state = NM_IP6_DEVICE_GOT_LINK_LOCAL;
nm_utils_do_sysctl (accept_ra_path, "0\n");
} else {
- device->target_state = NM_IP6_DEVICE_GOT_ADDRESS;
+ /* To begin with, the target state is only got-ra. We will
+ * increase it to got-address later, if we see a prefix
+ * being advertised with the Autonomous flag set, cf.
+ * process_prefix() above.
+ */
+ device->target_state = NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT;
nm_utils_do_sysctl (accept_ra_path, "2\n");
}
--
1.7.6
_______________________________________________
networkmanager-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/networkmanager-list