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

Reply via email to