summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-04-16 16:38:00 +0200
committerThomas Haller <thaller@redhat.com>2015-05-29 12:57:32 +0200
commit18835fb008fcd083a07a2e7702e17583e5405550 (patch)
tree809b18ce190e004d6aa859c2cd0df4894f989208
parent340ebaecfa338f25cd9f57a4a3f3f8f7be65d298 (diff)
downloadNetworkManager-th/default-ip6-privacy-bgo721200.tar.gz
device: add global configuration default for ip6-privacy (use_tempaddr, RFC4941)th/default-ip6-privacy-bgo721200
Support default value for setting 'ipv6.ip6-privacy' in NetworkManager.conf. If the global value is unset, preserve old behavior of looking into /etc/sycctl.conf first. If the global value is set to "unknown", add a new fallback that instead reads the runtime value from "/proc/sys/net/ipv6/conf/default/use_tempaddr" This seems more sensible behavior because we fallback to sysctl, but instead of looking at static files in /etc, read /proc. But to preserve the old behavior, we only do that when a global value is configured at all. https://bugzilla.gnome.org/show_bug.cgi?id=721200
-rw-r--r--libnm-core/nm-setting-ip6-config.c17
-rw-r--r--man/NetworkManager.conf.xml.in10
-rw-r--r--src/devices/nm-device.c89
3 files changed, 97 insertions, 19 deletions
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
index fa9eb1500e..4b7612fc62 100644
--- a/libnm-core/nm-setting-ip6-config.c
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -508,9 +508,20 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
* 0: disabled, 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 to either "0", "1", or "2".
+ * This property can be configured with a default value in global configuration
+ * NetworkManager.conf.
+ *
+ * If the global configuration value "connection.ipv6.ip6-privacy"
+ * is not specified, the sysctl value "net.ipv6.conf.default.use_tempaddr" in /etc/sysctl.conf or
+ * /lib/sysctl.d/sysctl.conf is always checked first. If set to "0", "1", or "2", that
+ * value is always used and any per-connection setting is ignored. This behavior is kept for
+ * backward compatiblity.
+ *
+ * Otherwise this per-connection setting is honored next. Having a per-connection setting set
+ * to "-1" (unknown) means fallback to global configuration "connection.ipv6.ip6-privacy".
+ *
+ * If the global configuration is explicitly set to "-1", fallback to reading
+ * "/proc/sys/net/ipv6/conf/default/use_tempaddr".
**/
/* ---ifcfg-rh---
* property: ip6-privacy
diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in
index 2815f25b44..6ae8f43303 100644
--- a/man/NetworkManager.conf.xml.in
+++ b/man/NetworkManager.conf.xml.in
@@ -476,7 +476,6 @@ ipv6.ip6-privacy=1
Note that also "wlan0" gets "ipv6.ip6-privacy=1", because although the section
"[connection-wifi-wlan0]" matches the device, it does not contain that property
and the search continues.
- This is just an example, ipv6.ip6-privacy property is currently not overwritable.
</para>
<para>
@@ -510,6 +509,15 @@ ipv6.ip6-privacy=1
<term><varname>ipv4.route-metric</varname></term>
</varlistentry>
<varlistentry>
+ <term><varname>ipv6.ip6-privacy</varname></term>
+ <listitem><para>If this value is unset, NetworkManager will always first check "/etc/sysctl.conf" and "/etc/sysctl.d/sysctl.conf" whether
+ they contain "net.ipv6.conf.default.use_tempaddr". This value is then preferred over any per-connection
+ setting. That step is omitted when setting the global configuration value <literal>ipv6.ip6-privacy</literal>
+ to any value. If <literal>ipv6.ip6-privacy</literal> is set but neither "0", "1", or "2", use the content of
+ "/proc/sys/net/ipv6/conf/default/use_tempaddr" as last fallback.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>ipv6.route-metric</varname></term>
</varlistentry>
</variablelist>
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index e8ec00c13c..afc26168d6 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -4697,8 +4697,10 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
}
}
+/************************************************************************/
+
static NMSettingIP6ConfigPrivacy
-use_tempaddr_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
+_ip6_privacy_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
{
switch (use_tempaddr) {
case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
@@ -4714,7 +4716,7 @@ use_tempaddr_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
* /lib/sysctl.d/sysctl.conf
*/
static NMSettingIP6ConfigPrivacy
-ip6_use_tempaddr (void)
+_ip6_privacy_sysctl (void)
{
char *contents = NULL;
const char *group_name = "[forged_group]\n";
@@ -4738,7 +4740,7 @@ ip6_use_tempaddr (void)
tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error);
if (error == NULL)
- ret = use_tempaddr_clamp (tmp);
+ ret = _ip6_privacy_clamp (tmp);
done:
g_free (contents);
@@ -4749,6 +4751,74 @@ done:
return ret;
}
+static NMSettingIP6ConfigPrivacy
+_ip6_privacy_get (NMDevice *self)
+{
+ NMSettingIP6ConfigPrivacy ip6_privacy;
+ gs_free char *value = NULL;
+ NMConnection *connection;
+
+ g_return_val_if_fail (self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+
+ value = nm_config_data_get_connection_default (nm_config_get_data (nm_config_get ()),
+ "ipv6.ip6-privacy", self);
+
+ /* 1.) If (and only if) the default value is not configured, check _ip6_privacy_sysctl()
+ * first. This is to preserve backward compatibility. In this case -- having no
+ * default value in global configuration, but use_tempaddr configured in /etc/sysctl --
+ * the per-connection setting is always ignored. */
+ if (!value) {
+ ip6_privacy = _ip6_privacy_sysctl ();
+ if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
+ return ip6_privacy;
+ }
+
+ /* 2.) Next we always look at the per-connection setting. If it is not -1 (unknown),
+ * use it. */
+ connection = nm_device_get_connection (self);
+ if (connection) {
+ 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));
+ ip6_privacy = _ip6_privacy_clamp (ip6_privacy);
+ if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
+ return ip6_privacy;
+ }
+ }
+
+ /* 3.) All options (per-connection, global, sysctl) are unset/default.
+ * Return UNKNOWN. Skip step 5.) because that would be a change in behavior
+ * compared to older versions. */
+ if (!value)
+ return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
+
+ /* 4.) use the default value from the configuration. */
+ ip6_privacy = _nm_utils_ascii_str_to_int64 (value, 10,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
+ return ip6_privacy;
+
+ /* 5.) A default-value is configured, but it is invalid/unknown. Fallback to sysctl reading.
+ *
+ * _ip6_privacy_sysctl() only reads two files from /etc and does not support the complexity
+ * of parsing all files. Also, it only considers "net.ipv6.conf.default.use_tempaddr",
+ * not the per-interface values. This is kinda unexpected, but we do it in 1.) to preserve
+ * old behavior.
+ *
+ * Now, the user actively configured a default value to "unknown" and we can introduce new
+ * behavior without changing old behavior (step 1.).
+ * Instead of reading static config files in /etc, just read the current sysctl value.
+ * This works as NM only writes to "/proc/sys/net/ipv6/conf/IFNAME/use_tempaddr", but leaves
+ * the "default" entry untouched. */
+ ip6_privacy = nm_platform_sysctl_get_int32 (NM_PLATFORM_GET, "/proc/sys/net/ipv6/conf/default/use_tempaddr", NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ return _ip6_privacy_clamp (ip6_privacy);
+}
+
+/****************************************************************/
+
static gboolean
ip6_requires_slaves (NMConnection *connection)
{
@@ -4847,18 +4917,7 @@ 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));
- }
- ip6_privacy = use_tempaddr_clamp (ip6_privacy);
+ ip6_privacy = _ip6_privacy_get (self);
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
if (!addrconf6_start (self, ip6_privacy)) {