diff options
author | Thomas Haller <thaller@redhat.com> | 2018-04-04 14:57:42 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-04-04 14:57:42 +0200 |
commit | 3fd109f01534f3408535d29c0ffab0eee8edfaaf (patch) | |
tree | 615a4513ade2f96169e7bd70ffd0dcee8c2a29f4 | |
parent | 33d2d8850bd64c70b18eb1114546277548496e17 (diff) | |
parent | c9f89cafdf588f443821ccff220283859ab26d1f (diff) | |
download | NetworkManager-3fd109f01534f3408535d29c0ffab0eee8edfaaf.tar.gz |
core: merge branch 'th/ipv6-ll-reapply-rh1552069-pt2'
https://github.com/NetworkManager/NetworkManager/pull/80
-rw-r--r-- | src/devices/nm-device.c | 130 | ||||
-rw-r--r-- | src/nm-types.h | 1 | ||||
-rw-r--r-- | src/platform/nm-platform-utils.c | 3 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 72 | ||||
-rw-r--r-- | src/platform/nmp-object.c | 2 | ||||
-rw-r--r-- | src/platform/nmp-object.h | 2 |
6 files changed, 156 insertions, 54 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 7d4b482ef2..9e1592a750 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -373,6 +373,7 @@ typedef struct _NMDevicePrivate { bool master_ready_handled:1; bool ipv6ll_handle:1; /* TRUE if NM handles the device's IPv6LL address */ + bool ipv6ll_has:1; /* Generic DHCP stuff */ char * dhcp_anycast_address; @@ -485,6 +486,7 @@ typedef struct _NMDevicePrivate { AppliedConfig ac_ip6_config; /* config from IPv6 autoconfiguration */ NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */ NMIP6Config * dad6_ip6_config; + struct in6_addr ipv6ll_addr; GHashTable * rt6_temporary_not_available; @@ -6161,6 +6163,28 @@ ip_config_merge_and_apply (NMDevice *self, ensure_con_ip_config (self, addr_family); } + if (!IS_IPv4) { + if ( commit + && priv->ipv6ll_has) { + const NMPlatformIP6Address ll_a = { + .address = priv->ipv6ll_addr, + .plen = 64, + .addr_source = NM_IP_CONFIG_SOURCE_IP6LL, + }; + const NMPlatformIP6Route ll_r = { + .network.s6_addr16[0] = htons (0xfe80u), + .plen = 64, + .metric = nm_device_get_route_metric (self, addr_family), + .rt_source = NM_IP_CONFIG_SOURCE_IP6LL, + }; + + nm_assert (IN6_IS_ADDR_LINKLOCAL (&priv->ipv6ll_addr)); + + nm_ip6_config_add_address (NM_IP6_CONFIG (composite), &ll_a); + nm_ip6_config_add_route (NM_IP6_CONFIG (composite), &ll_r, NULL); + } + } + if (commit) { gboolean v; @@ -7442,11 +7466,11 @@ static void check_and_add_ipv6ll_addr (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - int ip_ifindex = nm_device_get_ip_ifindex (self); struct in6_addr lladdr; NMConnection *connection; NMSettingIP6Config *s_ip6 = NULL; GError *error = NULL; + const char *addr_type; if (!priv->ipv6ll_handle) return; @@ -7460,6 +7484,9 @@ check_and_add_ipv6ll_addr (NMDevice *self) return; } + priv->ipv6ll_has = FALSE; + memset (&priv->ipv6ll_addr, 0, sizeof (priv->ipv6ll_addr)); + memset (&lladdr, 0, sizeof (lladdr)); lladdr.s6_addr16[0] = htons (0xfe80); @@ -7484,7 +7511,7 @@ check_and_add_ipv6ll_addr (NMDevice *self) linklocal6_failed (self); return; } - _LOGD (LOGD_IP6, "linklocal6: using IPv6 stable-privacy addressing"); + addr_type = "stable-privacy"; } else { NMUtilsIPv6IfaceId iid; @@ -7500,23 +7527,14 @@ check_and_add_ipv6ll_addr (NMDevice *self) _LOGW (LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue"); return; } - _LOGD (LOGD_IP6, "linklocal6: using EUI-64 identifier to generate IPv6LL address"); - nm_utils_ipv6_addr_set_interface_identifier (&lladdr, iid); + addr_type = "EUI-64"; } - _LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL)); - if (!nm_platform_ip6_address_add (nm_device_get_platform (self), - ip_ifindex, - lladdr, - 64, - in6addr_any, - NM_PLATFORM_LIFETIME_PERMANENT, - NM_PLATFORM_LIFETIME_PERMANENT, - 0)) { - _LOGW (LOGD_IP6, "failed to add IPv6 link-local address %s", - nm_utils_inet6_ntop (&lladdr, NULL)); - } + _LOGD (LOGD_IP6, "linklocal6: generated %s IPv6LL address %s", addr_type, nm_utils_inet6_ntop (&lladdr, NULL)); + priv->ipv6ll_has = TRUE; + priv->ipv6ll_addr = lladdr; + ip_config_merge_and_apply (self, AF_INET6, TRUE); } static gboolean @@ -7960,10 +7978,8 @@ addrconf6_start_with_link_ready (NMDevice *self) } /* Apply any manual configuration before starting RA */ - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) { + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration"); - g_clear_object (&priv->con_ip_config_6); - } /* FIXME: These sysctls would probably be better set by the lndp ndisc itself. */ switch (nm_ndisc_get_node_type (priv->ndisc)) { @@ -9010,6 +9026,32 @@ nm_device_activate_ip4_state_done (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_DONE; } +static void +dad6_add_pending_address (NMDevice *self, + NMPlatform *platform, + int ifindex, + const struct in6_addr *address, + NMIP6Config **dad6_config) +{ + const NMPlatformIP6Address *pl_addr; + + pl_addr = nm_platform_ip6_address_get (platform, + ifindex, + *address); + if ( pl_addr + && NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_TENTATIVE) + && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_DADFAILED) + && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { + _LOGt (LOGD_DEVICE, "IPv6 DAD: pending address %s", + nm_platform_ip6_address_to_string (pl_addr, NULL, 0)); + + if (!*dad6_config) + *dad6_config = _ip6_config_new (self); + + nm_ip6_config_add_address (*dad6_config, pl_addr); + } +} + /* * Returns a NMIP6Config containing NM-configured addresses which * have the tentative flag, or NULL if none is present. @@ -9022,38 +9064,39 @@ dad6_get_pending_addresses (NMDevice *self) (NMIP6Config *) applied_config_get_current (&priv->dhcp6.ip6_config), priv->con_ip_config_6, (NMIP6Config *) applied_config_get_current (&priv->wwan_ip_config_6) }; - const NMPlatformIP6Address *addr, *pl_addr; + const NMPlatformIP6Address *addr; NMIP6Config *dad6_config = NULL; NMDedupMultiIter ipconf_iter; guint i; int ifindex; + NMPlatform *platform; ifindex = nm_device_get_ip_ifindex (self); g_return_val_if_fail (ifindex > 0, NULL); + platform = nm_device_get_platform (self); + + if (priv->ipv6ll_has) { + dad6_add_pending_address (self, + platform, + ifindex, + &priv->ipv6ll_addr, + &dad6_config); + } + /* We are interested only in addresses that we have explicitly configured, * not in externally added ones. */ for (i = 0; i < G_N_ELEMENTS (confs); i++) { - if (confs[i]) { - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) { - pl_addr = nm_platform_ip6_address_get (nm_device_get_platform (self), - ifindex, - addr->address); - if ( pl_addr - && NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_TENTATIVE) - && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_DADFAILED) - && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { - _LOGt (LOGD_DEVICE, "IPv6 DAD: pending address %s", - nm_platform_ip6_address_to_string (pl_addr, NULL, 0)); - - if (!dad6_config) - dad6_config = _ip6_config_new (self); - - nm_ip6_config_add_address (dad6_config, pl_addr); - } - } + if (!confs[i]) + continue; + + nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) { + dad6_add_pending_address (self, + platform, + ifindex, + &addr->address, + &dad6_config); } } @@ -9501,6 +9544,9 @@ nm_device_reactivate_ip6_config (NMDevice *self, g_clear_object (&priv->ac_ip6_config.current); g_clear_object (&priv->dhcp6.ip6_config.current); g_clear_object (&priv->wwan_ip_config_6.current); + if ( priv->ipv6ll_handle + && !IN6_IS_ADDR_UNSPECIFIED (&priv->ipv6ll_addr)) + priv->ipv6ll_has = TRUE; priv->con_ip_config_6 = _ip6_config_new (self); nm_ip6_config_merge_setting (priv->con_ip_config_6, s_ip6_new, @@ -11280,6 +11326,10 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config for (iter = priv->vpn_configs_6; iter; iter = iter->next) nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, 0); + + if ( priv->ipv6ll_has + && !nm_ip6_config_lookup_address (priv->ext_ip_config_6, &priv->ipv6ll_addr)) + priv->ipv6ll_has = FALSE; } /* Remove parts from ext_ip_config_6 to only contain the information that @@ -12666,6 +12716,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) applied_config_clear (&priv->wwan_ip_config_6); g_clear_object (&priv->ip_config_6); g_clear_object (&priv->dad6_ip6_config); + priv->ipv6ll_has = FALSE; + memset (&priv->ipv6ll_addr, 0, sizeof (priv->ipv6ll_addr)); g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); diff --git a/src/nm-types.h b/src/nm-types.h index 6acc3f10d8..6bcd8f0d8a 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -95,6 +95,7 @@ typedef enum { NM_IP_CONFIG_SOURCE_KERNEL, NM_IP_CONFIG_SOURCE_SHARED, NM_IP_CONFIG_SOURCE_IP4LL, + NM_IP_CONFIG_SOURCE_IP6LL, NM_IP_CONFIG_SOURCE_PPP, NM_IP_CONFIG_SOURCE_WWAN, NM_IP_CONFIG_SOURCE_VPN, diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index b664e8a9f1..114bf4b349 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -589,6 +589,8 @@ nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source) switch (source) { case NM_IP_CONFIG_SOURCE_KERNEL: return RTPROT_KERNEL; + case NM_IP_CONFIG_SOURCE_IP6LL: + return RTPROT_KERNEL; case NM_IP_CONFIG_SOURCE_DHCP: return RTPROT_DHCP; case NM_IP_CONFIG_SOURCE_NDISC: @@ -656,6 +658,7 @@ nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize case NM_IP_CONFIG_SOURCE_KERNEL: s = "kernel"; break; case NM_IP_CONFIG_SOURCE_SHARED: s = "shared"; break; case NM_IP_CONFIG_SOURCE_IP4LL: s = "ipv4ll"; break; + case NM_IP_CONFIG_SOURCE_IP6LL: s = "ipv6ll"; break; case NM_IP_CONFIG_SOURCE_PPP: s = "ppp"; break; case NM_IP_CONFIG_SOURCE_WWAN: s = "wwan"; break; case NM_IP_CONFIG_SOURCE_VPN: s = "vpn"; break; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index dac0a5ff94..a645da2ee6 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -3902,7 +3902,8 @@ nm_platform_ip_route_sync (NMPlatform *self, for (i_type = 0; routes && i_type < 2; i_type++) { for (i = 0; i < routes->len; i++) { - NMPlatformError plerr; + NMPlatformError plerr, plerr2; + gboolean gateway_route_added = FALSE; conf_o = routes->pdata[i]; @@ -3948,6 +3949,7 @@ nm_platform_ip_route_sync (NMPlatform *self, } } +sync_route_add: plerr = nm_platform_ip_route_add (self, NMP_NLM_FLAG_APPEND | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, @@ -3986,22 +3988,66 @@ nm_platform_ip_route_sync (NMPlatform *self, if (!*out_temporary_not_available) *out_temporary_not_available = g_ptr_array_new_full (0, (GDestroyNotify) nmp_object_unref); g_ptr_array_add (*out_temporary_not_available, (gpointer) nmp_object_ref (conf_o)); - } else { - const char *reason = ""; - - if ( ( -((int) plerr) == ENETUNREACH - && vt->is_ip4 - && !!NMP_OBJECT_CAST_IP4_ROUTE (conf_o)->gateway) - || ( -((int) plerr) == EHOSTUNREACH - && !vt->is_ip4 - && !IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (conf_o)->gateway))) - reason = "; is the gateway directly reachable?"; + } else if ( !gateway_route_added + && ( ( -((int) plerr) == ENETUNREACH + && vt->is_ip4 + && !!NMP_OBJECT_CAST_IP4_ROUTE (conf_o)->gateway) + || ( -((int) plerr) == EHOSTUNREACH + && !vt->is_ip4 + && !IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (conf_o)->gateway)))) { + NMPObject oo; + + if (vt->is_ip4) { + const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (conf_o); + + nmp_object_stackinit (&oo, + NMP_OBJECT_TYPE_IP4_ROUTE, + &((NMPlatformIP4Route) { + .network = r->gateway, + .plen = 32, + .metric = r->metric, + .rt_source = r->rt_source, + .table_coerced = r->table_coerced, + })); + } else { + const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (conf_o); + + nmp_object_stackinit (&oo, + NMP_OBJECT_TYPE_IP6_ROUTE, + &((NMPlatformIP6Route) { + .network = r->gateway, + .plen = 128, + .metric = r->metric, + .rt_source = r->rt_source, + .table_coerced = r->table_coerced, + })); + } - _LOGW ("route-sync: failure to add IPv%c route: %s: %s%s", + _LOGD ("route-sync: failure to add IPv%c route: %s: %s; try adding direct route to gateway %s", vt->is_ip4 ? '4' : '6', nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err)), - reason); + nmp_object_to_string (&oo, NMP_OBJECT_TO_STRING_PUBLIC, sbuf2, sizeof (sbuf2))); + + plerr2 = nm_platform_ip_route_add (self, + NMP_NLM_FLAG_APPEND + | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, + &oo); + + if (plerr2 != NM_PLATFORM_ERROR_SUCCESS) { + _LOGD ("route-sync: failure to add gateway IPv%c route: %s: %s", + vt->is_ip4 ? '4' : '6', + nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), + nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err))); + } + + gateway_route_added = TRUE; + goto sync_route_add; + } else { + _LOGW ("route-sync: failure to add IPv%c route: %s: %s", + vt->is_ip4 ? '4' : '6', + nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), + nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err))); success = FALSE; } } diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 666d334c23..8139072fcf 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -532,7 +532,7 @@ _nmp_object_stackinit_from_type (NMPObject *obj, NMPObjectType obj_type) } const NMPObject * -nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, const NMPlatformObject *plobj) +nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj) { const NMPClass *klass = nmp_class_from_type (obj_type); diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 0dd2687a35..b524440392 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -490,7 +490,7 @@ nmp_object_unref (const NMPObject *obj) NMPObject *nmp_object_new (NMPObjectType obj_type, const NMPlatformObject *plob); NMPObject *nmp_object_new_link (int ifindex); -const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, const NMPlatformObject *plobj); +const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj); static inline NMPObject * nmp_object_stackinit_obj (NMPObject *obj, const NMPObject *src) |