summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2016-11-03 12:15:32 +0100
committerLubomir Rintel <lkundrak@v3.sk>2016-11-09 17:23:32 +0100
commit46e63e03af587d405324205997aee3b9a49b4052 (patch)
tree92037f968106cb2b131dec163c42ae9f7e9032b4
parent0e6d1940601250e72a85fbcbdce43920f6f052ef (diff)
downloadNetworkManager-46e63e03af587d405324205997aee3b9a49b4052.tar.gz
device: announce the managed IPv6 configuration with ipv6.method=shared
This esentially causes us to announce the prefixes of the addresses we own and the DNS configuration. Currently the only way to get the IPv6 configuration on such device is manual setting in the connection. This will change with IPv6 prefix delegation.
-rw-r--r--src/devices/nm-device.c120
1 files changed, 111 insertions, 9 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 543a3241bb..35d81cdf5f 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1811,6 +1811,73 @@ device_recheck_slave_status (NMDevice *self, const NMPlatformLink *plink)
}
}
+static void
+ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ guint32 now = nm_utils_get_monotonic_timestamp_s ();
+ GArray *addresses, *dns_servers, *dns_domains;
+ guint len, i;
+
+ if (nm_ndisc_get_node_type (ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
+ return;
+
+ /* Addresses whose prefixes we announce. */
+ len = nm_ip6_config_get_num_addresses (priv->ip6_config);
+ addresses = g_array_sized_new (FALSE, FALSE, sizeof (NMNDiscAddress), len);
+ for (i = 0; i < len; i++) {
+ const NMPlatformIP6Address *addr = nm_ip6_config_get_address (priv->ip6_config, i);
+ NMNDiscAddress *ndisc_addr;
+
+ if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
+ continue;
+
+ if ( addr->n_ifa_flags & IFA_F_TENTATIVE
+ || addr->n_ifa_flags & IFA_F_DADFAILED)
+ continue;
+
+ if (addr->plen != 64)
+ continue;
+
+ ndisc_addr = &g_array_index (addresses, NMNDiscAddress, addresses->len-1);
+ ndisc_addr->address = addr->address;
+ ndisc_addr->timestamp = addr->timestamp;
+ ndisc_addr->lifetime = addr->lifetime;
+ ndisc_addr->preferred = addr->preferred;
+ }
+
+ /* DNS servers. */
+ len = nm_ip6_config_get_num_nameservers (priv->ip6_config);
+ dns_servers = g_array_sized_new (FALSE, FALSE, sizeof (NMNDiscDNSServer), len);
+ for (i = 0; i < len; i++) {
+ const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (priv->ip6_config, i);
+ NMNDiscDNSServer *ndisc_nameserver;
+
+ ndisc_nameserver = &g_array_index (dns_servers, NMNDiscDNSServer, dns_servers->len-1);
+ ndisc_nameserver->address = *nameserver;
+ ndisc_nameserver->timestamp = now;
+ ndisc_nameserver->lifetime = NM_NDISC_ROUTER_LIFETIME;
+ }
+
+ /* DNS domains. */
+ len = nm_ip6_config_get_num_searches (priv->ip6_config);
+ dns_domains = g_array_sized_new (FALSE, FALSE, sizeof (NMNDiscDNSDomain), len);
+ for (i = 0; i < len; i++) {
+ const char *search = nm_ip6_config_get_search (priv->ip6_config, i);
+ NMNDiscDNSDomain *ndisc_search;
+
+ ndisc_search = &g_array_index (dns_domains, NMNDiscDNSDomain, dns_domains->len-1);
+ ndisc_search->domain = g_strdup (search);
+ ndisc_search->timestamp = now;
+ ndisc_search->lifetime = NM_NDISC_ROUTER_LIFETIME;
+ }
+
+ nm_ndisc_set_config (ndisc, addresses, dns_servers, dns_domains);
+ g_array_free (addresses, TRUE);
+ g_array_free (dns_servers, TRUE);
+ g_array_free (dns_domains, TRUE);
+}
+
static gboolean
device_link_changed (NMDevice *self)
{
@@ -5266,6 +5333,7 @@ connection_ip6_method_requires_carrier (NMConnection *connection,
static const char *ip6_carrier_methods[] = {
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NM_SETTING_IP6_CONFIG_METHOD_DHCP,
+ NM_SETTING_IP6_CONFIG_METHOD_SHARED,
NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL,
NULL
};
@@ -6043,7 +6111,8 @@ linklocal6_complete (NMDevice *self)
_LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses successful, continue with method %s", method);
- if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
+ if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
+ || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
if (!addrconf6_start_with_link_ready (self)) {
/* Time out IPv6 instead of failing the entire activation */
nm_device_activate_schedule_ip6_config_timeout (self);
@@ -6406,10 +6475,23 @@ addrconf6_start_with_link_ready (NMDevice *self)
if (!ip6_config_merge_and_apply (self, TRUE, NULL))
_LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration");
- nm_device_ipv6_sysctl_set (self, "accept_ra", "1");
- nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0");
- nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
- nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
+ /* XXX: These sysctls would probably be better set by the lndp ndisc itself. */
+ switch (nm_ndisc_get_node_type (priv->ndisc)) {
+ case NM_NDISC_NODE_TYPE_HOST:
+ /* Accepting prefixes from discovered routers. */
+ nm_device_ipv6_sysctl_set (self, "accept_ra", "1");
+ nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0");
+ nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
+ nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
+ break;
+ case NM_NDISC_NODE_TYPE_ROUTER:
+ /* We're the router. */
+ nm_device_ipv6_sysctl_set (self, "forwarding", "1");
+ nm_device_activate_schedule_ip6_config_result (self);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
priv->ndisc_changed_id = g_signal_connect (priv->ndisc,
NM_NDISC_CONFIG_RECEIVED,
@@ -6420,10 +6502,26 @@ addrconf6_start_with_link_ready (NMDevice *self)
G_CALLBACK (ndisc_ra_timeout),
self);
+ ndisc_set_router_config (priv->ndisc, self);
nm_ndisc_start (priv->ndisc);
return TRUE;
}
+static NMNDiscNodeType
+ndisc_node_type (NMDevice *self)
+{
+ NMConnection *connection;
+
+ connection = nm_device_get_applied_connection (self);
+ g_assert (connection);
+
+ if (strcmp (nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG),
+ NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
+ return NM_NDISC_NODE_TYPE_ROUTER;
+ else
+ return NM_NDISC_NODE_TYPE_HOST;
+}
+
static gboolean
addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
{
@@ -6455,7 +6553,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
stable_type,
stable_id,
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),
- NM_NDISC_NODE_TYPE_HOST,
+ ndisc_node_type (self),
&error);
}
if (!priv->ndisc) {
@@ -6508,6 +6606,7 @@ static const char *ip6_properties_to_save[] = {
"accept_ra_defrtr",
"accept_ra_pinfo",
"accept_ra_rtr_pref",
+ "forwarding",
"disable_ipv6",
"hop_limit",
"use_tempaddr",
@@ -6753,7 +6852,8 @@ act_stage3_ip6_config_start (NMDevice *self,
ip6_privacy = _ip6_privacy_get (self);
- if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
+ if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
+ || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
if (!addrconf6_start (self, ip6_privacy)) {
/* IPv6 might be disabled; allow IPv4 to proceed */
ret = NM_ACT_STAGE_RETURN_IP_FAIL;
@@ -6773,8 +6873,6 @@ act_stage3_ip6_config_start (NMDevice *self,
} else
_LOGW (LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method);
- /* Other methods (shared) aren't implemented yet */
-
if ( ret != NM_ACT_STAGE_RETURN_FAILURE
&& !nm_device_uses_assumed_connection (self)) {
switch (ip6_privacy) {
@@ -8800,6 +8898,9 @@ nm_device_set_ip6_config (NMDevice *self,
}
nm_device_queue_recheck_assume (self);
+
+ if (priv->ndisc)
+ ndisc_set_router_config (priv->ndisc, self);
}
if (reason)
@@ -11116,6 +11217,7 @@ ip6_managed_setup (NMDevice *self)
nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0");
+ nm_device_ipv6_sysctl_set (self, "forwarding", "0");
}
static void