diff options
author | Thomas Haller <thaller@redhat.com> | 2015-04-16 16:38:00 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-05-14 17:04:07 +0200 |
commit | 5782b678748ef589a22fdd57ab13f27d8cc74180 (patch) | |
tree | f28bfc28d1d51d4badd486b6bf3040ebb7439441 | |
parent | 502f324227ef8f7d67f3a918a1e6bf2ff934d982 (diff) | |
download | NetworkManager-th/default-ip6-privacy-bgo721200-v1.tar.gz |
device: add global configuration default for ip6-privacy (use_tempaddr, RFC4941)th/default-ip6-privacy-bgo721200-v1
Add configuration option default-setting-ipv6.ip6-privacy to
NetworkManager.conf.
https://bugzilla.gnome.org/show_bug.cgi?id=721200
-rw-r--r-- | libnm-core/nm-setting-ip6-config.c | 13 | ||||
-rw-r--r-- | man/NetworkManager.conf.xml.in | 45 | ||||
-rw-r--r-- | src/devices/nm-device.c | 68 | ||||
-rw-r--r-- | src/nm-config-data.c | 108 | ||||
-rw-r--r-- | src/nm-config-data.h | 2 |
5 files changed, 144 insertions, 92 deletions
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index cc3aedf3d4..78d6caa55c 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -508,11 +508,14 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * 1: enabled (prefer public address), 2: enabled (prefer temporary * addresses). * - * This per-connection value is ignored when setting - * "net.ipv6.conf.default.use_tempaddr" in /etc/sysctl.conf or - * /lib/sysctl.d/sysctl.conf. - * If set to -1 (default), the global configuration value main.ip6-privacy - * is used. + * If set to -1 (default), the global configuration value + * "default-setting-ipv6.ip6-privacy" is used. + * + * If the global configuration value "default-setting-ipv6.ip6-privacy" + * is unset but "net.ipv6.conf.default.use_tempaddr" in /etc/sysctl.conf or + * /lib/sysctl.d/sysctl.conf is configured to "0", "1", or "2", that value + * from sysctl takes precedence. In that case a per-connection setting is + * always ignored. **/ /* ---ifcfg-rh--- * property: ip6-privacy diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in index 37fc319a97..2545175bd0 100644 --- a/man/NetworkManager.conf.xml.in +++ b/man/NetworkManager.conf.xml.in @@ -286,21 +286,7 @@ no-auto-default=* </listitem> </varlistentry> - <varlistentry> - <term><varname>ip6-privacy</varname></term> - <listitem><para>Set the global IPv6 privacy address configuration (RFC4941). - If <literal>net.ipv6.conf.default.use_tempaddr</literal> is configured in - <literal>/etc/sysctl.conf</literal> or <literal>/lib/sysctl.d/sysctl.conf</literal>, - that value always takes precedence. Next, the privacy setting can be configured - per-connection via ipv6.ip6-privacy. Only if the per-connection value is -1 (unknown), - this global configuration is considered. - - Supported values are numeric values -1 (unknown, default), 0 (disabled), 1 (enabled, - prefer public address), 2 (enabled, prefer temporary address). - </para> - </listitem> - </varlistentry> - </variablelist> + </variablelist> </refsect1> <refsect1> @@ -493,6 +479,35 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth </refsect1> <refsect1> + <title><literal>default-setting-ipv6</literal> section</title> + <para>Default configuration values for the ipv6 setting of connections.</para> + + <para> + <variablelist> + <varlistentry> + <term><varname>ip6-privacy</varname></term> + <listitem><para>The IPv6 connection setting <literal>ip6-privacy</literal> + determines the IPv6 Privacy Extensions for SLAAC, described in RFC4941 (use_tempaddr). + Valid values are -1 (unknown), 0 (disabled), 1 (enabled, prefer public address), + and 2 (enabled, prefer temporary address). The default value is + -1 which effectively is the same as disabled. + This global configuration value is used for connections that have their + 'ipv6.ip6-privacy' value -1 (unknown). + Note that if this global configuration option is not set, NM will first + check <literal>/etc/sysctl.conf</literal> and <literal>/lib/sysctl.d/sysctl.conf</literal>. + If the sysctl value "net.ipv6.conf.default.use_tempaddr" is configured to + either 0, 1, or 2, that value always takes precedence. In other words, if you + configure "use_tempaddr" in sysctl.conf, that value is used over the + per-connection setting. To ignore a configuration value in sysctl.conf and + instead honor the per-connection setting, you must set this global configuration + option. + </para></listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + + <refsect1> <title>Plugins</title> <variablelist> diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 75ad956a9e..453ebb0963 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -4624,58 +4624,6 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) } } -static NMSettingIP6ConfigPrivacy -use_tempaddr_clamp (NMSettingIP6ConfigPrivacy use_tempaddr) -{ - switch (use_tempaddr) { - case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: - case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: - case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: - return use_tempaddr; - default: - return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; - } -} - -/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or - * /lib/sysctl.d/sysctl.conf - */ -static NMSettingIP6ConfigPrivacy -ip6_use_tempaddr (void) -{ - char *contents = NULL; - const char *group_name = "[forged_group]\n"; - char *sysctl_data = NULL; - GKeyFile *keyfile; - GError *error = NULL; - gint tmp; - NMSettingIP6ConfigPrivacy ret = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; - - /* Read file contents to a string. */ - if (!g_file_get_contents ("/etc/sysctl.conf", &contents, NULL, NULL)) - if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, NULL, NULL)) - return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; - - /* Prepend a group so that we can use GKeyFile parser. */ - sysctl_data = g_strdup_printf ("%s%s", group_name, contents); - - keyfile = g_key_file_new (); - if (!g_key_file_load_from_data (keyfile, sysctl_data, -1, G_KEY_FILE_NONE, NULL)) - goto done; - - tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error); - if (error == NULL) - ret = use_tempaddr_clamp (tmp); - -done: - g_free (contents); - g_free (sysctl_data); - g_clear_error (&error); - g_key_file_free (keyfile); - - return ret; -} - static gboolean ip6_requires_slaves (NMConnection *connection) { @@ -4774,20 +4722,8 @@ act_stage3_ip6_config_start (NMDevice *self, /* Re-enable IPv6 on the interface */ set_disable_ipv6 (self, "0"); - /* Enable/disable IPv6 Privacy Extensions. - * If a global value is configured by sysadmin (e.g. /etc/sysctl.conf), - * use that value instead of per-connection value. - */ - ip6_privacy = ip6_use_tempaddr (); - if (ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) { - NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); - - if (s_ip6) - ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)); - if (ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) - ip6_privacy = nm_config_data_get_ip6_privacy (nm_config_get_data (nm_config_get ())); - } - ip6_privacy = use_tempaddr_clamp (ip6_privacy); + ip6_privacy = nm_config_data_get_ip6_privacy_for_connection (nm_config_get_data (nm_config_get ()), + connection, TRUE); if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) { if (!addrconf6_start (self, ip6_privacy)) { diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 3fe006f0a7..0479cad584 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -50,7 +50,9 @@ typedef struct { char *dns_mode; char *rc_manager; - NMSettingIP6ConfigPrivacy ip6_privacy; + struct { + NMSettingIP6ConfigPrivacy ip6_privacy; + } default_setting_ipv6; } NMConfigDataPrivate; @@ -162,12 +164,105 @@ nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device) return nm_device_spec_match_list (device, NM_CONFIG_DATA_GET_PRIVATE (self)->ignore_carrier); } +/************************************************************************/ + +static NMSettingIP6ConfigPrivacy +_ip6_privacy_clamp (NMSettingIP6ConfigPrivacy use_tempaddr) +{ + switch (use_tempaddr) { + case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: + return use_tempaddr; + default: + return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + } +} + +/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or + * /lib/sysctl.d/sysctl.conf + */ +static NMSettingIP6ConfigPrivacy +_ip6_privacy_sysctl (void) +{ + char *contents = NULL; + const char *group_name = "[forged_group]\n"; + char *sysctl_data = NULL; + GKeyFile *keyfile; + GError *error = NULL; + gint tmp; + NMSettingIP6ConfigPrivacy ret = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + + /* Read file contents to a string. */ + if (!g_file_get_contents ("/etc/sysctl.conf", &contents, NULL, NULL)) + if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, NULL, NULL)) + return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + + /* Prepend a group so that we can use GKeyFile parser. */ + sysctl_data = g_strdup_printf ("%s%s", group_name, contents); + + keyfile = g_key_file_new (); + if (!g_key_file_load_from_data (keyfile, sysctl_data, -1, G_KEY_FILE_NONE, NULL)) + goto done; + + tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error); + if (error == NULL) + ret = _ip6_privacy_clamp (tmp); + +done: + g_free (contents); + g_free (sysctl_data); + g_clear_error (&error); + g_key_file_free (keyfile); + + return ret; +} + +#define NM_SETTING_IP6_CONFIG_PRIVACY_SYSCTL ((NMSettingIP6ConfigPrivacy) -5) + NMSettingIP6ConfigPrivacy -nm_config_data_get_ip6_privacy (const NMConfigData *self) +nm_config_data_get_ip6_privacy_for_connection (const NMConfigData *self, NMConnection *connection, gboolean prefer_sysctl) { + NMConfigDataPrivate *priv; + NMSettingIP6ConfigPrivacy ret; + g_return_val_if_fail (self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - return NM_CONFIG_DATA_GET_PRIVATE (self)->ip6_privacy; + priv = NM_CONFIG_DATA_GET_PRIVATE (self); + + /* - if the global default value is unset, we first consult + * sysctl (if @prefer_sysctl). Hence, if you don't specify + * default_setting_ipv6.ip6_privacy, but sysctl.conf, sysctl.conf + * always wins over any per-connection setting. This is backward + * compatible to previous behavior. + * - if you configure any value for default_setting_ipv6.ip6_privacy, or + * don't configure sysctl.conf, we first always honor the per connection + * setting. IOW, if you configure any value for default_setting_ipv6.ip6_privacy, + * sysctl is ignored. + * - if no per-connection setting is present, fallback to default value + * from global configuration. */ + + ret = priv->default_setting_ipv6.ip6_privacy; + if (ret == NM_SETTING_IP6_CONFIG_PRIVACY_SYSCTL) { + /* the global value is "unknown. That means, consult sysctl first. */ + if (prefer_sysctl) { + ret = _ip6_privacy_sysctl (); + if (ret != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) + return ret; + } else + ret = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + } + if (connection) { + NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); + + if (s_ip6) { + ret = nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)); + ret = _ip6_privacy_clamp (ret); + if (ret != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) + return ret; + } + } + return ret; } /************************************************************************/ @@ -368,8 +463,11 @@ constructed (GObject *object) priv->ignore_carrier = nm_config_get_device_match_spec (priv->keyfile, "main", "ignore-carrier"); - tmp = g_key_file_get_value (priv->keyfile, "main", "ip6-privacy", NULL); - priv->ip6_privacy = _nm_utils_ascii_str_to_int64 (tmp, 10, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + tmp = g_key_file_get_value (priv->keyfile, "default-setting-ipv6", "ip6-privacy", NULL); + priv->default_setting_ipv6.ip6_privacy = _nm_utils_ascii_str_to_int64 (tmp, 10, + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + NM_SETTING_IP6_CONFIG_PRIVACY_SYSCTL); g_free (tmp); G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object); diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 8e6f90475b..36655ea7b1 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -95,7 +95,7 @@ const char *nm_config_data_get_rc_manager (const NMConfigData *self); gboolean nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device); -NMSettingIP6ConfigPrivacy nm_config_data_get_ip6_privacy (const NMConfigData *self); +NMSettingIP6ConfigPrivacy nm_config_data_get_ip6_privacy_for_connection (const NMConfigData *self, NMConnection *connection, gboolean prefer_sysctl); G_END_DECLS |