1740 lines
59 KiB
Diff
1740 lines
59 KiB
Diff
From 9989350adbe25dccb716f8df41ac915c1e262304 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Sat, 15 Feb 2014 13:20:40 +0100
|
|
Subject: [PATCH 01/14] fix several compile errors
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/devices/nm-device.c | 2 +-
|
|
src/settings/nm-system-config-interface.c | 2 +-
|
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index c3b3f21..92de1db 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -6925,7 +6925,7 @@ nm_device_add_pending_action (NMDevice *device, const char *action)
|
|
nm_device_get_iface (device),
|
|
g_slist_length (priv->pending_actions),
|
|
action);
|
|
- g_return_val_if_reached (FALSE);
|
|
+ g_return_if_reached ();
|
|
}
|
|
}
|
|
|
|
diff --git a/src/settings/nm-system-config-interface.c b/src/settings/nm-system-config-interface.c
|
|
index 18457ea..fd36fc4 100644
|
|
--- a/src/settings/nm-system-config-interface.c
|
|
+++ b/src/settings/nm-system-config-interface.c
|
|
@@ -141,7 +141,7 @@ gboolean
|
|
nm_system_config_interface_load_connection (NMSystemConfigInterface *config,
|
|
const char *filename)
|
|
{
|
|
- g_return_val_if_fail (config != NULL, NULL);
|
|
+ g_return_val_if_fail (config != NULL, FALSE);
|
|
|
|
if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->load_connection)
|
|
return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->load_connection (config, filename);
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 7ffd758bf4e0d57a240ec4031bf987b397950463 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Tue, 21 Jan 2014 13:07:06 +0100
|
|
Subject: [PATCH 02/14] core: add nm_utils_ascii_str_to_int64() function
|
|
|
|
(cherry picked from commit 63075d98a59270ffcb89bb556b6ee5efc14eef0f)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/NetworkManagerUtils.c | 60 +++++++++++++++++++++++++++++++++++++
|
|
src/NetworkManagerUtils.h | 2 ++
|
|
src/tests/Makefile.am | 10 +++++++
|
|
src/tests/test-general.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
4 files changed, 148 insertions(+)
|
|
create mode 100644 src/tests/test-general.c
|
|
|
|
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
|
|
index bc3d1b2..d0937fb 100644
|
|
--- a/src/NetworkManagerUtils.c
|
|
+++ b/src/NetworkManagerUtils.c
|
|
@@ -644,3 +644,63 @@ nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id)
|
|
return g_strdup_printf ("%s.%d", parent_iface, vlan_id);
|
|
}
|
|
|
|
+/* nm_utils_ascii_str_to_int64:
|
|
+ *
|
|
+ * A wrapper for g_ascii_strtoll, that checks whether the whole string
|
|
+ * can be successfully converted to a number and is within a given
|
|
+ * range. On any error, @fallback will be returned and @errno will be set
|
|
+ * to a non-zero value. Check @errno for errors. Any trailing or leading
|
|
+ * (ascii) white space is ignored and the functions is locale independent.
|
|
+ *
|
|
+ * The function is guaranteed to return a value between @min and @max
|
|
+ * (included) or @fallback. Also, the parsing is rather strict, it does
|
|
+ * not allow for any unrecognized characters, except leading and trailing
|
|
+ * white space.
|
|
+ **/
|
|
+gint64
|
|
+nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
|
|
+{
|
|
+ gint64 v;
|
|
+ char *end;
|
|
+ char *str_free = NULL;
|
|
+
|
|
+ if (str) {
|
|
+ while (str[0] && g_ascii_isspace (str[0]))
|
|
+ str++;
|
|
+ }
|
|
+ if (!str || !str[0]) {
|
|
+ errno = EINVAL;
|
|
+ return fallback;
|
|
+ }
|
|
+
|
|
+ if (g_ascii_isspace (str[strlen (str) - 1])) {
|
|
+ str_free = g_strdup (str);
|
|
+ g_strstrip (str_free);
|
|
+ str = str_free;
|
|
+ }
|
|
+
|
|
+ errno = 0;
|
|
+ v = g_ascii_strtoll (str, &end, base);
|
|
+
|
|
+ if (errno != 0) {
|
|
+ g_free (str_free);
|
|
+ return fallback;
|
|
+ }
|
|
+
|
|
+ if (end[0] != 0) {
|
|
+ g_free (str_free);
|
|
+ errno = EINVAL;
|
|
+ return fallback;
|
|
+ }
|
|
+
|
|
+ g_free (str_free);
|
|
+ if (v > max || v < min) {
|
|
+ errno = ERANGE;
|
|
+ return fallback;
|
|
+ }
|
|
+
|
|
+ return v;
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
|
|
index 819cb07..0904c51 100644
|
|
--- a/src/NetworkManagerUtils.h
|
|
+++ b/src/NetworkManagerUtils.h
|
|
@@ -91,4 +91,6 @@ void nm_utils_complete_generic (NMConnection *connection,
|
|
|
|
char *nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id);
|
|
|
|
+gint64 nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
|
|
+
|
|
#endif /* NETWORK_MANAGER_UTILS_H */
|
|
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
|
|
index 3e485fd..2b42d2c 100644
|
|
--- a/src/tests/Makefile.am
|
|
+++ b/src/tests/Makefile.am
|
|
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
|
|
|
|
noinst_PROGRAMS = \
|
|
test-dhcp-options \
|
|
+ test-general \
|
|
test-policy-hosts \
|
|
test-wifi-ap-utils \
|
|
test-ip4-config \
|
|
@@ -62,6 +63,14 @@ test_ip6_config_SOURCES = \
|
|
test_ip6_config_LDADD = \
|
|
$(top_builddir)/src/libNetworkManager.la
|
|
|
|
+####### general test #######
|
|
+
|
|
+test_general_SOURCES = \
|
|
+ test-general.c
|
|
+
|
|
+test_general_LDADD = \
|
|
+ $(top_builddir)/src/libNetworkManager.la
|
|
+
|
|
####### secret agent interface test #######
|
|
|
|
EXTRA_DIST = test-secret-agent.py
|
|
@@ -74,4 +83,5 @@ check-local: test-dhcp-options test-policy-hosts test-wifi-ap-utils test-ip4-con
|
|
$(abs_builddir)/test-wifi-ap-utils
|
|
$(abs_builddir)/test-ip4-config
|
|
$(abs_builddir)/test-ip6-config
|
|
+ $(abs_builddir)/test-general
|
|
|
|
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
|
|
new file mode 100644
|
|
index 0000000..649653c
|
|
--- /dev/null
|
|
+++ b/src/tests/test-general.c
|
|
@@ -0,0 +1,76 @@
|
|
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
+/*
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2, or (at your option)
|
|
+ * any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License along
|
|
+ * with this program; if not, write to the Free Software Foundation, Inc.,
|
|
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Copyright (C) 2014 Red Hat, Inc.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <glib.h>
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include "NetworkManagerUtils.h"
|
|
+
|
|
+
|
|
+static void
|
|
+test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min,
|
|
+ gint64 max, gint64 fallback, int exp_errno,
|
|
+ gint64 exp_val)
|
|
+{
|
|
+ gint64 v;
|
|
+
|
|
+ errno = 0;
|
|
+ v = nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
|
|
+ g_assert_cmpint (errno, ==, exp_errno);
|
|
+ g_assert_cmpint (v, ==, exp_val);
|
|
+}
|
|
+
|
|
+static void
|
|
+test_nm_utils_ascii_str_to_int64 (void)
|
|
+{
|
|
+ test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711);
|
|
+ test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1);
|
|
+ test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 1x ", 10, 0, 10000, -1, EINVAL, -1);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 10000 ", 10, 0, 10000, -1, 0, 10000);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 10001 ", 10, 0, 10000, -1, ERANGE, -1);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 0xFF ", 16, 0, 10000, -1, 0, 255);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" FF ", 16, 0, 10000, -1, 0, 255);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" FF ", 10, 0, 10000, -2, EINVAL, -2);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 9223372036854775807 ", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 0x7FFFFFFFFFFFFFFF ", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 7FFFFFFFFFFFFFFF ", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" 9223372036854775808 ", 10, 0, G_MAXINT64, -2, ERANGE, -2);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" -9223372036854775808 ", 10, G_MININT64, 0, -2, 0, G_MININT64);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" -9223372036854775808 ", 10, G_MININT64+1, 0, -2, ERANGE, -2);
|
|
+ test_nm_utils_ascii_str_to_int64_do (" -9223372036854775809 ", 10, G_MININT64, 0, -2, ERANGE, -2);
|
|
+ test_nm_utils_ascii_str_to_int64_do ("\r\n\t10000\t\n\t\n", 10, 0, 10000, -1, 0, 10000);
|
|
+}
|
|
+
|
|
+/*******************************************/
|
|
+
|
|
+int
|
|
+main (int argc, char **argv)
|
|
+{
|
|
+ g_test_init (&argc, &argv, NULL);
|
|
+
|
|
+ g_type_init ();
|
|
+
|
|
+ g_test_add_func ("/general/nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
|
+
|
|
+ return g_test_run ();
|
|
+}
|
|
+
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 04320290b6c1dfb7f6ac0b8c7f9b71cffbc5730b Mon Sep 17 00:00:00 2001
|
|
From: Dan Winship <danw@gnome.org>
|
|
Date: Mon, 14 Oct 2013 10:38:56 -0400
|
|
Subject: [PATCH 03/14] core: add function nm_utils_get_ip_config_method()
|
|
|
|
Add nm_utils_get_ip_config_method(), which returns the correct
|
|
IP config method for a connection, whether the connection has IP4 and
|
|
IP6 settings objects or not, and use that to keep some more of the
|
|
simplifications from the earlier patch.
|
|
|
|
This is a partial backport of an upstream commit.
|
|
|
|
(cherry picked from commit f03635e5ac829d4fc896573f2f3c6969b9d5a2e2)
|
|
---
|
|
src/NetworkManagerUtils.c | 43 +++++++++++++++++++++++++++++++++++++++++++
|
|
src/NetworkManagerUtils.h | 3 +++
|
|
2 files changed, 46 insertions(+)
|
|
|
|
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
|
|
index d0937fb..bac5322 100644
|
|
--- a/src/NetworkManagerUtils.c
|
|
+++ b/src/NetworkManagerUtils.c
|
|
@@ -576,6 +576,49 @@ get_new_connection_name (const GSList *existing,
|
|
return cname;
|
|
}
|
|
|
|
+const char *
|
|
+nm_utils_get_ip_config_method (NMConnection *connection,
|
|
+ GType ip_setting_type)
|
|
+{
|
|
+ NMSettingConnection *s_con;
|
|
+ NMSettingIP4Config *s_ip4;
|
|
+ NMSettingIP6Config *s_ip6;
|
|
+ const char *method;
|
|
+
|
|
+ s_con = nm_connection_get_setting_connection (connection);
|
|
+
|
|
+ if (ip_setting_type == NM_TYPE_SETTING_IP4_CONFIG) {
|
|
+ g_return_val_if_fail (s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
|
+
|
|
+ if (nm_setting_connection_get_master (s_con))
|
|
+ return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
+ else {
|
|
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
+ g_return_val_if_fail (s_ip4 != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
|
+ method = nm_setting_ip4_config_get_method (s_ip4);
|
|
+ g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
|
+
|
|
+ return method;
|
|
+ }
|
|
+
|
|
+ } else if (ip_setting_type == NM_TYPE_SETTING_IP6_CONFIG) {
|
|
+ g_return_val_if_fail (s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
|
+
|
|
+ if (nm_setting_connection_get_master (s_con))
|
|
+ return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
|
+ else {
|
|
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
+ g_return_val_if_fail (s_ip6 != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
|
+ method = nm_setting_ip6_config_get_method (s_ip6);
|
|
+ g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
|
+
|
|
+ return method;
|
|
+ }
|
|
+
|
|
+ } else
|
|
+ g_assert_not_reached ();
|
|
+}
|
|
+
|
|
void
|
|
nm_utils_complete_generic (NMConnection *connection,
|
|
const char *ctype,
|
|
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
|
|
index 0904c51..a15f74f 100644
|
|
--- a/src/NetworkManagerUtils.h
|
|
+++ b/src/NetworkManagerUtils.h
|
|
@@ -82,6 +82,9 @@ gboolean nm_utils_get_proc_sys_net_value_with_bounds (const char *path,
|
|
gint32 valid_min,
|
|
gint32 valid_max);
|
|
|
|
+const char *nm_utils_get_ip_config_method (NMConnection *connection,
|
|
+ GType ip_setting_type);
|
|
+
|
|
void nm_utils_complete_generic (NMConnection *connection,
|
|
const char *ctype,
|
|
const GSList *existing,
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 32602714f0e06301d68be71daf38c42215b46944 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Mon, 6 Jan 2014 19:59:17 +0100
|
|
Subject: [PATCH 04/14] core: add function nm_platform_sysctl_get_int32()
|
|
|
|
This is a partial backport of an upstream commit.
|
|
|
|
(cherry picked from commit 2b87dbb2a990fa6aee9ca1e431a2d1ee2af453e9)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/platform/nm-platform.c | 32 ++++++++++++++++++++++++++++++++
|
|
src/platform/nm-platform.h | 1 +
|
|
2 files changed, 33 insertions(+)
|
|
|
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
|
index 06cdec0..cf21e5c 100644
|
|
--- a/src/platform/nm-platform.c
|
|
+++ b/src/platform/nm-platform.c
|
|
@@ -27,6 +27,7 @@
|
|
#include <netlink/route/addr.h>
|
|
|
|
#include "nm-platform.h"
|
|
+#include "NetworkManagerUtils.h"
|
|
#include "nm-logging.h"
|
|
#include "nm-enum-types.h"
|
|
|
|
@@ -243,6 +244,37 @@ nm_platform_sysctl_get (const char *path)
|
|
return klass->sysctl_get (platform, path);
|
|
}
|
|
|
|
+/**
|
|
+ * nm_platform_sysctl_get_int32:
|
|
+ * @path: Absolute path to sysctl
|
|
+ * @fallback: default value, if the content of path could not be read
|
|
+ * as decimal integer.
|
|
+ *
|
|
+ * Returns: contents of the sysctl file parsed as s32 integer, or
|
|
+ * @fallback on error. Also, on error, @errno will be set to a non-zero
|
|
+ * value.
|
|
+ */
|
|
+gint32
|
|
+nm_platform_sysctl_get_int32 (const char *path, gint32 fallback)
|
|
+{
|
|
+ char *value = NULL;
|
|
+ gint32 ret;
|
|
+
|
|
+ g_return_val_if_fail (path, fallback);
|
|
+
|
|
+ if (path)
|
|
+ value = nm_platform_sysctl_get (path);
|
|
+
|
|
+ if (!value) {
|
|
+ errno = EINVAL;
|
|
+ return fallback;
|
|
+ }
|
|
+
|
|
+ ret = nm_utils_ascii_str_to_int64 (value, 10, G_MININT32, G_MAXINT32, fallback);
|
|
+ g_free (value);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/******************************************************************/
|
|
|
|
/**
|
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
|
index 58f51ce..d4864d0 100644
|
|
--- a/src/platform/nm-platform.h
|
|
+++ b/src/platform/nm-platform.h
|
|
@@ -349,6 +349,7 @@ void nm_platform_query_devices (void);
|
|
|
|
gboolean nm_platform_sysctl_set (const char *path, const char *value);
|
|
char *nm_platform_sysctl_get (const char *path);
|
|
+gint32 nm_platform_sysctl_get_int32 (const char *path, gint32 fallback);
|
|
|
|
GArray *nm_platform_link_get_all (void);
|
|
gboolean nm_platform_dummy_add (const char *name);
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From e72164b28a31355fb71b798b6197113d64f94335 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Fri, 13 Dec 2013 20:12:57 +0100
|
|
Subject: [PATCH 05/14] core: fix NMDevice.ip6_use_tempaddr to avoid buffer
|
|
overrun for zero char in config file
|
|
|
|
(cherry picked from commit bb9deec9ef98ede632e69f8e5a6e017070f714a8)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/devices/nm-device.c | 7 +++----
|
|
1 file changed, 3 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index 92de1db..e32050f 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -3272,7 +3272,6 @@ static int
|
|
ip6_use_tempaddr (void)
|
|
{
|
|
char *contents = NULL;
|
|
- gsize len = 0;
|
|
const char *group_name = "[forged_group]\n";
|
|
char *sysctl_data = NULL;
|
|
GKeyFile *keyfile;
|
|
@@ -3280,15 +3279,15 @@ ip6_use_tempaddr (void)
|
|
int tmp, ret = -1;
|
|
|
|
/* Read file contents to a string. */
|
|
- if (!g_file_get_contents ("/etc/sysctl.conf", &contents, &len, NULL))
|
|
- if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, &len, NULL))
|
|
+ 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 -1;
|
|
|
|
/* 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, len + strlen (group_name), G_KEY_FILE_NONE, NULL))
|
|
+ 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);
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 3edb66027825c327ba0b24339505d99c0432623d Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 7 Nov 2013 20:38:08 +0100
|
|
Subject: [PATCH 06/14] core: IPv6 mode link-local must not behave like auto
|
|
(bgo#706618, bgo#707155)
|
|
|
|
In act_stage3_ip6_config_start, for IPv6 mode link-local, we check
|
|
if there is already an IPv6 address configured. If yes, we are
|
|
already done.
|
|
|
|
For now, as current workaround, if the LL does not exist, we
|
|
NM_ACT_STAGE_RETURN_STOP.
|
|
|
|
Later, we will POSTPONE and wait a timeout until we see a LL address
|
|
that is no longer TENTATIVE. The same should be done for method auto,
|
|
so that the device is usable to send router solitations (bgo#707155).
|
|
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=707155
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=706618
|
|
|
|
(cherry picked from commit 10bd060076befc4b711125a19831d323f9ea8595)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/devices/nm-device.c | 30 ++++++++++++++++++++++++++++--
|
|
1 file changed, 28 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index e32050f..152814c 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -3265,6 +3265,31 @@ addrconf6_cleanup (NMDevice *self)
|
|
|
|
/******************************************/
|
|
|
|
+static int
|
|
+linklocal6_start (NMDevice *self)
|
|
+{
|
|
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
+ int i;
|
|
+
|
|
+ if (priv->ip6_config) {
|
|
+ for (i = 0; i < nm_ip6_config_get_num_addresses (priv->ip6_config); i++) {
|
|
+ const NMPlatformIP6Address *addr = nm_ip6_config_get_address (priv->ip6_config, i);
|
|
+
|
|
+ if (addr->plen == 128 && IN6_IS_ADDR_LINKLOCAL (&addr->address)) {
|
|
+ /* FIXME: only accept the address if it is no longer TENTATIVE */
|
|
+ return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* FIXME: we should NM_ACT_STAGE_RETURN_POSTPONE and wait until with timeout
|
|
+ * we get a link local address that is no longer TENTATIVE. */
|
|
+ nm_log_warn (LOGD_DEVICE, "[%s] starting IPv6 with mode 'link-local', but the device has no link-local addresses configured.",
|
|
+ nm_device_get_iface (self));
|
|
+
|
|
+ return NM_ACT_STAGE_RETURN_STOP;
|
|
+}
|
|
+
|
|
/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or
|
|
* /lib/sysctl.d/sysctl.conf
|
|
*/
|
|
@@ -3387,13 +3412,14 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|
|
|
priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE;
|
|
|
|
- if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
|
- || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
|
|
+ if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
|
if (!addrconf6_start (self)) {
|
|
/* IPv6 might be disabled; allow IPv4 to proceed */
|
|
ret = NM_ACT_STAGE_RETURN_STOP;
|
|
} else
|
|
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
|
+ } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
|
|
+ ret = linklocal6_start (self);
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
|
|
/* Router advertisements shouldn't be used in pure DHCP mode */
|
|
if (priv->ip6_accept_ra_path)
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From e1d059d1a2d359504900d14e9d8acf0307187e6c Mon Sep 17 00:00:00 2001
|
|
From: Dan Williams <dcbw@redhat.com>
|
|
Date: Thu, 7 Nov 2013 21:30:25 -0600
|
|
Subject: [PATCH 07/14] core: fix hanlding of IPv6LL address if interface
|
|
already has one
|
|
|
|
act_stage3_ip6_config_start() expects a non-NULL NMIP6Config if the
|
|
sub-method returns NM_ACT_STAGE_RETURN_SUCCESS.
|
|
|
|
(cherry picked from commit 72063064567312ff6412c6d9996e8a6684df3f1d)
|
|
---
|
|
src/devices/nm-device.c | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index 152814c..4384f6a 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -3420,6 +3420,11 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
|
|
ret = linklocal6_start (self);
|
|
+ if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
|
+ /* New blank config; LL address is already in priv->ext_ip6_config */
|
|
+ *out_config = nm_ip6_config_new ();
|
|
+ g_assert (*out_config);
|
|
+ }
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
|
|
/* Router advertisements shouldn't be used in pure DHCP mode */
|
|
if (priv->ip6_accept_ra_path)
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 82abe50b59f09d80507d286d7259eb9038708363 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 7 Nov 2013 22:59:43 +0100
|
|
Subject: [PATCH 08/14] core: wait for IPv6 link local address with method
|
|
'auto' and 'link-local' (bgo#707155)
|
|
|
|
With the methods 'auto' and 'link-local' we check now, that the device
|
|
has a usable IPv6 LL address configured (after DAD, no longer tentative).
|
|
|
|
We wait for up to 5 seconds, for a suitable LL address to appear.
|
|
Currently, if the address does not get ready, we don't create one and
|
|
IPv6 configuration fails.
|
|
|
|
This is relevant for the methods 'link-local' and 'auto'. In the latter
|
|
case, because we cannot send router solitations without link local
|
|
address.
|
|
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=707155
|
|
|
|
(cherry picked from commit c4a087c36d34e584a48b6b866fc3c12f248f8512)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/devices/nm-device.c | 170 +++++++++++++++++++++++++++++++++++++++---------
|
|
1 file changed, 140 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index 4384f6a..8c20a0d 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -269,6 +269,8 @@ typedef struct {
|
|
/* IP6 config from autoconf */
|
|
NMIP6Config * ac_ip6_config;
|
|
|
|
+ guint linklocal6_timeout_id;
|
|
+
|
|
char * ip6_accept_ra_path;
|
|
gint32 ip6_accept_ra_save;
|
|
|
|
@@ -345,6 +347,8 @@ static void nm_device_queued_ip_config_change_clear (NMDevice *self);
|
|
static void update_ip_config (NMDevice *self);
|
|
static void device_ip_changed (NMPlatform *platform, int ifindex, gpointer platform_object, NMPlatformReason reason, gpointer user_data);
|
|
|
|
+static void addrconf6_start_with_link_ready (NMDevice *self);
|
|
+
|
|
static const char const *platform_ip_signals[] = {
|
|
NM_PLATFORM_IP4_ADDRESS_ADDED,
|
|
NM_PLATFORM_IP4_ADDRESS_CHANGED,
|
|
@@ -3092,6 +3096,104 @@ dhcp6_start (NMDevice *self,
|
|
|
|
/******************************************/
|
|
|
|
+static gboolean
|
|
+linklocal6_config_is_ready (const NMIP6Config *ip6_config)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ if (!ip6_config)
|
|
+ return FALSE;
|
|
+
|
|
+ for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
|
|
+ const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ip6_config, i);
|
|
+
|
|
+ if (IN6_IS_ADDR_LINKLOCAL (&addr->address) &&
|
|
+ !(addr->flags & IFA_F_TENTATIVE))
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static void
|
|
+linklocal6_cleanup (NMDevice *self)
|
|
+{
|
|
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
+
|
|
+ if (priv->linklocal6_timeout_id) {
|
|
+ g_source_remove (priv->linklocal6_timeout_id);
|
|
+ priv->linklocal6_timeout_id = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+linklocal6_timeout_cb (gpointer user_data)
|
|
+{
|
|
+ NMDevice *self = user_data;
|
|
+
|
|
+ linklocal6_cleanup (self);
|
|
+
|
|
+ nm_log_dbg (LOGD_DEVICE, "[%s] linklocal6: waiting for link-local addresses failed due to timeout",
|
|
+ nm_device_get_iface (self));
|
|
+
|
|
+ nm_device_activate_schedule_ip6_config_timeout (self);
|
|
+ return G_SOURCE_REMOVE;
|
|
+}
|
|
+
|
|
+static void
|
|
+linklocal6_complete (NMDevice *self)
|
|
+{
|
|
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
+ NMConnection *connection;
|
|
+ const char *method;
|
|
+
|
|
+ g_assert (priv->linklocal6_timeout_id);
|
|
+ g_assert (linklocal6_config_is_ready (priv->ip6_config));
|
|
+
|
|
+ linklocal6_cleanup (self);
|
|
+
|
|
+ connection = nm_device_get_connection (self);
|
|
+ g_assert (connection);
|
|
+
|
|
+ method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
|
+
|
|
+ nm_log_dbg (LOGD_DEVICE, "[%s] linklocal6: waiting for link-local addresses successful, continue with method %s",
|
|
+ nm_device_get_iface (self), method);
|
|
+
|
|
+ if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0)
|
|
+ addrconf6_start_with_link_ready (self);
|
|
+ else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0)
|
|
+ nm_device_activate_schedule_ip6_config_result (self);
|
|
+ else
|
|
+ g_return_if_fail (FALSE);
|
|
+}
|
|
+
|
|
+static NMActStageReturn
|
|
+linklocal6_start (NMDevice *self)
|
|
+{
|
|
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
+ NMConnection *connection;
|
|
+ const char *method;
|
|
+
|
|
+ linklocal6_cleanup (self);
|
|
+
|
|
+ if (linklocal6_config_is_ready (priv->ip6_config))
|
|
+ return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
+
|
|
+ connection = nm_device_get_connection (self);
|
|
+ g_assert (connection);
|
|
+
|
|
+ method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
|
+ nm_log_dbg (LOGD_DEVICE, "[%s] linklocal6: starting IPv6 with method '%s', but the device has no link-local addresses configured. Wait.",
|
|
+ nm_device_get_iface (self), method);
|
|
+
|
|
+ priv->linklocal6_timeout_id = g_timeout_add_seconds (5, linklocal6_timeout_cb, self);
|
|
+
|
|
+ return NM_ACT_STAGE_RETURN_POSTPONE;
|
|
+}
|
|
+
|
|
+/******************************************/
|
|
+
|
|
static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release);
|
|
|
|
static void
|
|
@@ -3218,6 +3320,7 @@ addrconf6_start (NMDevice *self)
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
NMConnection *connection;
|
|
const char *ip_iface = nm_device_get_ip_iface (self);
|
|
+ NMActStageReturn ret;
|
|
|
|
connection = nm_device_get_connection (self);
|
|
g_assert (connection);
|
|
@@ -3229,23 +3332,40 @@ addrconf6_start (NMDevice *self)
|
|
}
|
|
|
|
priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface);
|
|
- nm_platform_sysctl_set (priv->ip6_accept_ra_path, "0");
|
|
|
|
if (!priv->rdisc) {
|
|
nm_log_err (LOGD_IP6, "(%s): failed to start router discovery.", ip_iface);
|
|
return FALSE;
|
|
}
|
|
|
|
- priv->rdisc_config_changed_sigid = g_signal_connect (
|
|
- priv->rdisc, NM_RDISC_CONFIG_CHANGED, G_CALLBACK (rdisc_config_changed), self);
|
|
+ /* ensure link local is ready... */
|
|
+ ret = linklocal6_start (self);
|
|
+
|
|
+ if (ret == NM_ACT_STAGE_RETURN_SUCCESS)
|
|
+ addrconf6_start_with_link_ready (self);
|
|
+ else
|
|
+ g_return_val_if_fail (ret == NM_ACT_STAGE_RETURN_POSTPONE, TRUE);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static void
|
|
+addrconf6_start_with_link_ready (NMDevice *self)
|
|
+{
|
|
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
+
|
|
+ g_assert (priv->rdisc);
|
|
|
|
/* FIXME: what if interface has no lladdr, like PPP? */
|
|
if (priv->hw_addr_len)
|
|
nm_rdisc_set_lladdr (priv->rdisc, (const char *) priv->hw_addr, priv->hw_addr_len);
|
|
|
|
- nm_rdisc_start (priv->rdisc);
|
|
+ nm_platform_sysctl_set (priv->ip6_accept_ra_path, "0");
|
|
|
|
- return TRUE;
|
|
+ priv->rdisc_config_changed_sigid = g_signal_connect (priv->rdisc, NM_RDISC_CONFIG_CHANGED,
|
|
+ G_CALLBACK (rdisc_config_changed), self);
|
|
+
|
|
+ nm_rdisc_start (priv->rdisc);
|
|
}
|
|
|
|
static void
|
|
@@ -3265,31 +3385,6 @@ addrconf6_cleanup (NMDevice *self)
|
|
|
|
/******************************************/
|
|
|
|
-static int
|
|
-linklocal6_start (NMDevice *self)
|
|
-{
|
|
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
- int i;
|
|
-
|
|
- if (priv->ip6_config) {
|
|
- for (i = 0; i < nm_ip6_config_get_num_addresses (priv->ip6_config); i++) {
|
|
- const NMPlatformIP6Address *addr = nm_ip6_config_get_address (priv->ip6_config, i);
|
|
-
|
|
- if (addr->plen == 128 && IN6_IS_ADDR_LINKLOCAL (&addr->address)) {
|
|
- /* FIXME: only accept the address if it is no longer TENTATIVE */
|
|
- return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* FIXME: we should NM_ACT_STAGE_RETURN_POSTPONE and wait until with timeout
|
|
- * we get a link local address that is no longer TENTATIVE. */
|
|
- nm_log_warn (LOGD_DEVICE, "[%s] starting IPv6 with mode 'link-local', but the device has no link-local addresses configured.",
|
|
- nm_device_get_iface (self));
|
|
-
|
|
- return NM_ACT_STAGE_RETURN_STOP;
|
|
-}
|
|
-
|
|
/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or
|
|
* /lib/sysctl.d/sysctl.conf
|
|
*/
|
|
@@ -4397,6 +4492,7 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
|
|
|
|
dhcp4_cleanup (self, TRUE, FALSE);
|
|
dhcp6_cleanup (self, TRUE, FALSE);
|
|
+ linklocal6_cleanup (self);
|
|
addrconf6_cleanup (self);
|
|
dnsmasq_cleanup (self);
|
|
aipd_cleanup (self);
|
|
@@ -5179,6 +5275,7 @@ dispose (GObject *object)
|
|
/* Clean up and stop DHCP */
|
|
dhcp4_cleanup (self, deconfigure, FALSE);
|
|
dhcp6_cleanup (self, deconfigure, FALSE);
|
|
+ linklocal6_cleanup (self);
|
|
addrconf6_cleanup (self);
|
|
dnsmasq_cleanup (self);
|
|
|
|
@@ -6346,6 +6443,7 @@ update_ip_config (NMDevice *self)
|
|
{
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
int ifindex;
|
|
+ gboolean linklocal6_just_completed = FALSE;
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
if (!ifindex)
|
|
@@ -6367,6 +6465,11 @@ update_ip_config (NMDevice *self)
|
|
g_clear_object (&priv->ext_ip6_config);
|
|
priv->ext_ip6_config = nm_ip6_config_capture (ifindex);
|
|
if (priv->ext_ip6_config) {
|
|
+
|
|
+ /* Check this before modifying ext_ip6_config */
|
|
+ linklocal6_just_completed = priv->linklocal6_timeout_id &&
|
|
+ linklocal6_config_is_ready (priv->ext_ip6_config);
|
|
+
|
|
if (priv->ac_ip6_config)
|
|
nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config);
|
|
if (priv->dhcp6_ip6_config)
|
|
@@ -6376,6 +6479,13 @@ update_ip_config (NMDevice *self)
|
|
|
|
ip6_config_merge_and_apply (self, FALSE, NULL);
|
|
}
|
|
+
|
|
+ if (linklocal6_just_completed) {
|
|
+ /* linklocal6 is ready now, do the state transition... we are also
|
|
+ * invoked as g_idle_add, so no problems with reentrance doing it now.
|
|
+ */
|
|
+ linklocal6_complete (self);
|
|
+ }
|
|
}
|
|
|
|
static gboolean
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 6133195b274165a8494edcf58560e2e96b39a89d Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Mon, 6 Jan 2014 21:05:00 +0100
|
|
Subject: [PATCH 09/14] core/rdisc: limit the number of autoconf addresses to
|
|
'max_addresses'
|
|
|
|
NetworkManager uses the sysctl value 'max_addresses' as the kernel does.
|
|
There is however a difference in what addresses are taken into account.
|
|
The kernel counts all addresses on the interface (including temporary,
|
|
private addresses and user configured ones).
|
|
NM instead only limits the number of public autoconf addresses to
|
|
'max_addresses'. This is because it is difficult for NM to count all
|
|
addresses (which can come from different sources) and it is not
|
|
necessarily a more logical behavior. Only be aware, that NM uses
|
|
the same config value as the kernel, but counts differently.
|
|
|
|
Especially, the kernel might reach the limit earlier then NM in the
|
|
presence of temporary addresses or addresses not from SLAAC.
|
|
|
|
Note, that the kernel uses 'max_addresses' only to limit public, autoconf
|
|
addresses. So this limit does not affect NM adding as many addresses as
|
|
it wants.
|
|
|
|
(cherry picked from commit 84dc64c8affd658077fa3967d42374d6c3a2951c)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/devices/nm-device.c | 23 ++++++++++++++++++++++-
|
|
src/rdisc/nm-fake-rdisc.c | 3 ++-
|
|
src/rdisc/nm-fake-rdisc.h | 2 +-
|
|
src/rdisc/nm-lndp-rdisc.c | 10 +++++++++-
|
|
src/rdisc/nm-lndp-rdisc.h | 2 +-
|
|
src/rdisc/nm-rdisc.h | 1 +
|
|
src/rdisc/tests/rdisc.c | 4 ++--
|
|
7 files changed, 38 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index 8c20a0d..e8ed2ba 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -449,6 +449,21 @@ update_ip6_privacy_save (NMDevice *self)
|
|
}
|
|
}
|
|
|
|
+static gint32
|
|
+sysctl_get_ipv6_max_addresses (const char *dev)
|
|
+{
|
|
+ gint32 max_addresses = 16;
|
|
+ char *path;
|
|
+
|
|
+ g_return_val_if_fail (dev && *dev, max_addresses);
|
|
+
|
|
+ path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/max_addresses", dev);
|
|
+ max_addresses = nm_platform_sysctl_get_int32 (path, max_addresses);
|
|
+ g_free (path);
|
|
+
|
|
+ return max_addresses;
|
|
+}
|
|
+
|
|
/*
|
|
* Get driver info from SIOCETHTOOL ioctl() for 'iface'
|
|
* Returns driver and firmware versions to 'driver_version and' 'firmware_version'
|
|
@@ -3225,6 +3240,11 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|
/* Rebuild address list from router discovery cache. */
|
|
nm_ip6_config_reset_addresses (priv->ac_ip6_config);
|
|
|
|
+ /* rdisc->addresses contains at most max_addresses entries.
|
|
+ * This is different from what the kernel does, which
|
|
+ * also counts static and temporary addresses when checking
|
|
+ * max_addresses.
|
|
+ **/
|
|
for (i = 0; i < rdisc->addresses->len; i++) {
|
|
NMRDiscAddress *discovered_address = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
|
|
NMPlatformIP6Address address;
|
|
@@ -3331,7 +3351,8 @@ addrconf6_start (NMDevice *self)
|
|
priv->ac_ip6_config = NULL;
|
|
}
|
|
|
|
- priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface);
|
|
+ priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface,
|
|
+ sysctl_get_ipv6_max_addresses (ip_iface));
|
|
|
|
if (!priv->rdisc) {
|
|
nm_log_err (LOGD_IP6, "(%s): failed to start router discovery.", ip_iface);
|
|
diff --git a/src/rdisc/nm-fake-rdisc.c b/src/rdisc/nm-fake-rdisc.c
|
|
index f39c5a2..38faa50 100644
|
|
--- a/src/rdisc/nm-fake-rdisc.c
|
|
+++ b/src/rdisc/nm-fake-rdisc.c
|
|
@@ -36,7 +36,7 @@ G_DEFINE_TYPE (NMFakeRDisc, nm_fake_rdisc, NM_TYPE_RDISC)
|
|
/******************************************************************/
|
|
|
|
NMRDisc *
|
|
-nm_fake_rdisc_new (int ifindex, const char *ifname)
|
|
+nm_fake_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses)
|
|
{
|
|
NMRDisc *rdisc = g_object_new (NM_TYPE_FAKE_RDISC, NULL);
|
|
|
|
@@ -44,6 +44,7 @@ nm_fake_rdisc_new (int ifindex, const char *ifname)
|
|
|
|
rdisc->ifindex = ifindex;
|
|
rdisc->ifname = g_strdup (ifname);
|
|
+ rdisc->max_addresses = max_addresses;
|
|
|
|
return rdisc;
|
|
}
|
|
diff --git a/src/rdisc/nm-fake-rdisc.h b/src/rdisc/nm-fake-rdisc.h
|
|
index 248283b..cff9ee4 100644
|
|
--- a/src/rdisc/nm-fake-rdisc.h
|
|
+++ b/src/rdisc/nm-fake-rdisc.h
|
|
@@ -44,6 +44,6 @@ typedef struct {
|
|
|
|
GType nm_fake_rdisc_get_type (void);
|
|
|
|
-NMRDisc *nm_fake_rdisc_new (int ifindex, const char *ifname);
|
|
+NMRDisc *nm_fake_rdisc_new (int ifindex, const char *ifname, gint32 max_addressses);
|
|
|
|
#endif /* NM_FAKE_RDISC_H */
|
|
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
|
|
index c9bb2cf..c328f99 100644
|
|
--- a/src/rdisc/nm-lndp-rdisc.c
|
|
+++ b/src/rdisc/nm-lndp-rdisc.c
|
|
@@ -48,7 +48,7 @@ G_DEFINE_TYPE (NMLNDPRDisc, nm_lndp_rdisc, NM_TYPE_RDISC)
|
|
/******************************************************************/
|
|
|
|
NMRDisc *
|
|
-nm_lndp_rdisc_new (int ifindex, const char *ifname)
|
|
+nm_lndp_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses)
|
|
{
|
|
NMRDisc *rdisc;
|
|
NMLNDPRDiscPrivate *priv;
|
|
@@ -59,6 +59,7 @@ nm_lndp_rdisc_new (int ifindex, const char *ifname)
|
|
|
|
rdisc->ifindex = ifindex;
|
|
rdisc->ifname = g_strdup (ifname);
|
|
+ rdisc->max_addresses = max_addresses;
|
|
|
|
priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
|
error = ndp_open (&priv->ndp);
|
|
@@ -113,6 +114,13 @@ add_address (NMRDisc *rdisc, const NMRDiscAddress *new)
|
|
}
|
|
}
|
|
|
|
+ /* we create at most max_addresses autoconf addresses. This is different from
|
|
+ * what the kernel does, because it considers *all* addresses (including
|
|
+ * static and other temporary addresses).
|
|
+ **/
|
|
+ if (rdisc->max_addresses && rdisc->addresses->len >= rdisc->max_addresses)
|
|
+ return FALSE;
|
|
+
|
|
g_array_insert_val (rdisc->addresses, i, *new);
|
|
return TRUE;
|
|
}
|
|
diff --git a/src/rdisc/nm-lndp-rdisc.h b/src/rdisc/nm-lndp-rdisc.h
|
|
index eb6a1df..30d53db 100644
|
|
--- a/src/rdisc/nm-lndp-rdisc.h
|
|
+++ b/src/rdisc/nm-lndp-rdisc.h
|
|
@@ -44,6 +44,6 @@ typedef struct {
|
|
|
|
GType nm_lndp_rdisc_get_type (void);
|
|
|
|
-NMRDisc *nm_lndp_rdisc_new (int ifindex, const char *ifname);
|
|
+NMRDisc *nm_lndp_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses);
|
|
|
|
#endif /* NM_LNDP_RDISC_H */
|
|
diff --git a/src/rdisc/nm-rdisc.h b/src/rdisc/nm-rdisc.h
|
|
index c645bda..219b6b2 100644
|
|
--- a/src/rdisc/nm-rdisc.h
|
|
+++ b/src/rdisc/nm-rdisc.h
|
|
@@ -106,6 +106,7 @@ typedef struct {
|
|
int ifindex;
|
|
char *ifname;
|
|
GBytes *lladdr;
|
|
+ gint32 max_addresses;
|
|
|
|
NMRDiscDHCPLevel dhcp_level;
|
|
GArray *gateways;
|
|
diff --git a/src/rdisc/tests/rdisc.c b/src/rdisc/tests/rdisc.c
|
|
index 680bb2e..e8e2a9f 100644
|
|
--- a/src/rdisc/tests/rdisc.c
|
|
+++ b/src/rdisc/tests/rdisc.c
|
|
@@ -12,7 +12,7 @@ main (int argc, char **argv)
|
|
{
|
|
GMainLoop *loop;
|
|
NMRDisc *rdisc;
|
|
- NMRDisc *(*new) (int ifindex, const char *ifname) = nm_lndp_rdisc_new;
|
|
+ NMRDisc *(*new) (int ifindex, const char *ifname, gint32 max_addresses) = nm_lndp_rdisc_new;
|
|
int ifindex = 1;
|
|
char ifname[IF_NAMESIZE];
|
|
char mac[6] = { 0x02, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
|
|
@@ -34,7 +34,7 @@ main (int argc, char **argv)
|
|
}
|
|
}
|
|
|
|
- rdisc = new (ifindex, ifname);
|
|
+ rdisc = new (ifindex, ifname, 0);
|
|
if (!rdisc)
|
|
return EXIT_FAILURE;
|
|
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From dc11f1ca2ee02f986b714f1def9fe64e1de14f35 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Fri, 3 Jan 2014 16:07:36 +0100
|
|
Subject: [PATCH 10/14] core/platform: workaround new address flag in
|
|
address_to_string
|
|
|
|
The kernel and libnl adds two new flags IFA_F_MANAGETEMPADDR
|
|
and IFA_F_NOPREFIXROUTE. Older versions of libnl do not recognize
|
|
this flag, so add a workaround to nm_platform_ip6_address_to_string()
|
|
to show "mngtmpaddr" and "noprefixroute", respectively.
|
|
|
|
Also, add function nm_platform_check_support_libnl_extended_ifa_flags()
|
|
that checks whether libnl supports extended ifa_flags that were
|
|
added recently.
|
|
|
|
Extended flags and the two ifa-flags above were added to libnl in close
|
|
succession.
|
|
|
|
(cherry picked from commit 2bc61d1ad3278d4fc38d17bd6178e7e304c6339a)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/platform/nm-platform.c | 41 ++++++++++++++++++++++++++++++++++++++++-
|
|
src/platform/nm-platform.h | 2 ++
|
|
2 files changed, 42 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
|
index cf21e5c..92c9c30 100644
|
|
--- a/src/platform/nm-platform.c
|
|
+++ b/src/platform/nm-platform.c
|
|
@@ -31,6 +31,14 @@
|
|
#include "nm-logging.h"
|
|
#include "nm-enum-types.h"
|
|
|
|
+/* workaround for older libnl version, that does not define these flags. */
|
|
+#ifndef IFA_F_MANAGETEMPADDR
|
|
+#define IFA_F_MANAGETEMPADDR 0x100
|
|
+#endif
|
|
+#ifndef IFA_F_NOPREFIXROUTE
|
|
+#define IFA_F_NOPREFIXROUTE 0x200
|
|
+#endif
|
|
+
|
|
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
|
|
|
|
#define NM_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PLATFORM, NMPlatformPrivate))
|
|
@@ -196,6 +204,22 @@ reset_error (void)
|
|
platform->error = NM_PLATFORM_ERROR_NONE;
|
|
}
|
|
|
|
+#define IFA_F_MANAGETEMPADDR_STR "mngtmpaddr"
|
|
+#define IFA_F_NOPREFIXROUTE_STR "noprefixroute"
|
|
+gboolean
|
|
+nm_platform_check_support_libnl_extended_ifa_flags ()
|
|
+{
|
|
+ static int supported = -1;
|
|
+
|
|
+ /* support for extended ifa-flags was added together
|
|
+ * with the IFA_F_MANAGETEMPADDR flag. So, check if libnl
|
|
+ * is able to parse this flag. */
|
|
+ if (supported == -1)
|
|
+ supported = rtnl_addr_str2flags (IFA_F_MANAGETEMPADDR_STR) == IFA_F_MANAGETEMPADDR;
|
|
+
|
|
+ return supported;
|
|
+}
|
|
+
|
|
/******************************************************************/
|
|
|
|
/**
|
|
@@ -1688,7 +1712,22 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|
inet_ntop (AF_INET6, &address->address, s_address, sizeof (s_address));
|
|
s_dev = address->ifindex > 0 ? nm_platform_link_get_name (address->ifindex) : NULL;
|
|
|
|
- rtnl_addr_flags2str(address->flags, s_flags, sizeof(s_flags));
|
|
+ rtnl_addr_flags2str(address->flags, s_flags, sizeof (s_flags));
|
|
+
|
|
+ /* There are two recent flags IFA_F_MANAGETEMPADDR and IFA_F_NOPREFIXROUTE.
|
|
+ * If libnl does not yet support them, add them by hand.
|
|
+ * These two flags were introduced together with the extended ifa_flags,
|
|
+ * so, check for that.
|
|
+ **/
|
|
+ if ((address->flags && IFA_F_MANAGETEMPADDR) & !nm_platform_check_support_libnl_extended_ifa_flags ()) {
|
|
+ strncat (s_flags, s_flags[0] ? "," IFA_F_MANAGETEMPADDR_STR : IFA_F_MANAGETEMPADDR_STR,
|
|
+ sizeof (s_flags) - strlen (s_flags) - 1);
|
|
+ }
|
|
+ if ((address->flags && IFA_F_NOPREFIXROUTE) & !nm_platform_check_support_libnl_extended_ifa_flags ()) {
|
|
+ strncat (s_flags, s_flags[0] ? "," IFA_F_NOPREFIXROUTE_STR : IFA_F_NOPREFIXROUTE_STR,
|
|
+ sizeof (s_flags) - strlen (s_flags) - 1);
|
|
+ }
|
|
+
|
|
str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL;
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u dev %s%s",
|
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
|
index d4864d0..26a6737 100644
|
|
--- a/src/platform/nm-platform.h
|
|
+++ b/src/platform/nm-platform.h
|
|
@@ -444,6 +444,8 @@ int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatform
|
|
int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b);
|
|
int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b);
|
|
|
|
+gboolean nm_platform_check_support_libnl_extended_ifa_flags (void);
|
|
+
|
|
#define auto_g_free __attribute__((cleanup(put_g_free)))
|
|
static void __attribute__((unused))
|
|
put_g_free (void *ptr)
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 57af43c6118d8d62a8671919833864e2d5e3a270 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Tue, 7 Jan 2014 17:21:12 +0100
|
|
Subject: [PATCH 11/14] core/platform: add
|
|
check_support_kernel_extended_ifa_flags function
|
|
|
|
The kernel adds a new capability to allow user space to manage
|
|
temporary IPv6 addresses. We need to detect this capability
|
|
to act differently, depending on whether NM has an older kernel
|
|
at hand.
|
|
|
|
This capability got introduced together when extending the
|
|
ifa_flags to 32 bit. So, we can check the netlink message,
|
|
whether we have such an nl attribute at hand.
|
|
|
|
(cherry picked from commit 7841f9ea0a4efdcb4540628cf65d7d9356b748f7)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/platform/nm-linux-platform.c | 57 ++++++++++++++++++++++++++++++++++++++++
|
|
src/platform/nm-platform.c | 11 ++++++++
|
|
src/platform/nm-platform.h | 3 +++
|
|
3 files changed, 71 insertions(+)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 1a44c40..b60f101 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -65,6 +65,8 @@ typedef struct {
|
|
|
|
GUdevClient *udev_client;
|
|
GHashTable *udev_devices;
|
|
+
|
|
+ int support_kernel_extended_ifa_flags;
|
|
} NMLinuxPlatformPrivate;
|
|
|
|
#define NM_LINUX_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformPrivate))
|
|
@@ -427,6 +429,45 @@ ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *s
|
|
|
|
/******************************************************************/
|
|
|
|
+static void
|
|
+_check_support_kernel_extended_ifa_flags_init (NMLinuxPlatformPrivate *priv, struct nl_msg *msg)
|
|
+{
|
|
+ struct nlmsghdr *msg_hdr = nlmsg_hdr (msg);
|
|
+
|
|
+ g_return_if_fail (priv->support_kernel_extended_ifa_flags == 0);
|
|
+ g_return_if_fail (msg_hdr->nlmsg_type == RTM_NEWADDR);
|
|
+
|
|
+ /* the extended address flags are only set for AF_INET6 */
|
|
+ if (((struct ifaddrmsg *) nlmsg_data (msg_hdr))->ifa_family != AF_INET6)
|
|
+ return;
|
|
+
|
|
+ /* see if the nl_msg contains the IFA_FLAGS attribute. If it does,
|
|
+ * we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR
|
|
+ * and IFA_F_NOPREFIXROUTE (they were added together).
|
|
+ **/
|
|
+ priv->support_kernel_extended_ifa_flags =
|
|
+ nlmsg_find_attr (msg_hdr, sizeof (struct ifaddrmsg), 8 /* IFA_FLAGS */)
|
|
+ ? 1 : -1;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+check_support_kernel_extended_ifa_flags (NMPlatform *platform)
|
|
+{
|
|
+ NMLinuxPlatformPrivate *priv;
|
|
+
|
|
+ g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), FALSE);
|
|
+
|
|
+ priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
|
+
|
|
+ if (priv->support_kernel_extended_ifa_flags == 0) {
|
|
+ g_warn_if_reached ();
|
|
+ priv->support_kernel_extended_ifa_flags = -1;
|
|
+ }
|
|
+
|
|
+ return priv->support_kernel_extended_ifa_flags > 0;
|
|
+}
|
|
+
|
|
+
|
|
/* Object type specific utilities */
|
|
|
|
static const char *
|
|
@@ -1195,6 +1236,14 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|
int nle;
|
|
|
|
event = nlmsg_hdr (msg)->nlmsg_type;
|
|
+
|
|
+ if (priv->support_kernel_extended_ifa_flags == 0 && event == RTM_NEWADDR) {
|
|
+ /* if kernel support for extended ifa flags is still undecided, use the opportunity
|
|
+ * now and use @msg to decide it. This saves a blocking net link request.
|
|
+ **/
|
|
+ _check_support_kernel_extended_ifa_flags_init (priv, msg);
|
|
+ }
|
|
+
|
|
nl_msg_parse (msg, ref_object, &object);
|
|
g_return_val_if_fail (object, NL_OK);
|
|
|
|
@@ -2744,6 +2793,12 @@ setup (NMPlatform *platform)
|
|
g_list_free (devices);
|
|
g_object_unref (enumerator);
|
|
|
|
+ /* request all IPv6 addresses (hopeing that there is at least one), to check for
|
|
+ * the IFA_FLAGS attribute. */
|
|
+ nle = nl_rtgen_request (priv->nlh_event, RTM_GETADDR, AF_INET6, NLM_F_DUMP);
|
|
+ if (nle != 0)
|
|
+ nm_log_warn (LOGD_PLATFORM, "Netlink error: requesting RTM_GETADDR failed with %s", nl_geterror (nle));
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -2848,4 +2903,6 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
|
|
platform_class->ip6_route_delete = ip6_route_delete;
|
|
platform_class->ip4_route_exists = ip4_route_exists;
|
|
platform_class->ip6_route_exists = ip6_route_exists;
|
|
+
|
|
+ platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags;
|
|
}
|
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
|
index 92c9c30..5871f86 100644
|
|
--- a/src/platform/nm-platform.c
|
|
+++ b/src/platform/nm-platform.c
|
|
@@ -220,6 +220,17 @@ nm_platform_check_support_libnl_extended_ifa_flags ()
|
|
return supported;
|
|
}
|
|
|
|
+gboolean
|
|
+nm_platform_check_support_kernel_extended_ifa_flags ()
|
|
+{
|
|
+ g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE);
|
|
+
|
|
+ if (!klass->check_support_kernel_extended_ifa_flags)
|
|
+ return FALSE;
|
|
+
|
|
+ return klass->check_support_kernel_extended_ifa_flags (platform);
|
|
+}
|
|
+
|
|
/******************************************************************/
|
|
|
|
/**
|
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
|
index 26a6737..d5b3672 100644
|
|
--- a/src/platform/nm-platform.h
|
|
+++ b/src/platform/nm-platform.h
|
|
@@ -302,6 +302,8 @@ typedef struct {
|
|
gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric);
|
|
gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric);
|
|
gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric);
|
|
+
|
|
+ gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
|
|
} NMPlatformClass;
|
|
|
|
/* NMPlatform signals
|
|
@@ -445,6 +447,7 @@ int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4R
|
|
int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b);
|
|
|
|
gboolean nm_platform_check_support_libnl_extended_ifa_flags (void);
|
|
+gboolean nm_platform_check_support_kernel_extended_ifa_flags (void);
|
|
|
|
#define auto_g_free __attribute__((cleanup(put_g_free)))
|
|
static void __attribute__((unused))
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 399f5d8dfd7a74dbd9043015e15df3fa1644fefb Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Fri, 31 Jan 2014 14:54:31 +0100
|
|
Subject: [PATCH 12/14] core/platform: fix wrong warning log in
|
|
nm-linux-platform
|
|
|
|
According to documentation, nl_rtgen_request() returns 0 on success.
|
|
Due to a bug (fixed upstream) in older libnl versions, nl_rtgen_request()
|
|
returns the number of bytes sent, which caused logging although
|
|
succeeding.
|
|
|
|
(cherry picked from commit 6c2f96421b1c7bfd65032bf4de2a6cfc10b3b262)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/platform/nm-linux-platform.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index b60f101..7933678 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -2796,7 +2796,7 @@ setup (NMPlatform *platform)
|
|
/* request all IPv6 addresses (hopeing that there is at least one), to check for
|
|
* the IFA_FLAGS attribute. */
|
|
nle = nl_rtgen_request (priv->nlh_event, RTM_GETADDR, AF_INET6, NLM_F_DUMP);
|
|
- if (nle != 0)
|
|
+ if (nle < 0)
|
|
nm_log_warn (LOGD_PLATFORM, "Netlink error: requesting RTM_GETADDR failed with %s", nl_geterror (nle));
|
|
|
|
return TRUE;
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From b7a960b1287b11ff3db02204a2ff6888efa571f5 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Fri, 3 Jan 2014 17:03:35 +0100
|
|
Subject: [PATCH 13/14] core/rdisc: add autoconf addresses as /64 (instead of
|
|
/128)
|
|
|
|
This feature needs support from the kernel and libnl.
|
|
|
|
If there is no system support, NM acts as before, adding the
|
|
autoconf address as /128. It does so, to prevent the kernel
|
|
from adding a route for this prefix. With system support, we
|
|
add the address as /64 and set the flag IFA_F_NOPREFIXROUTE.
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1044590
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1045118
|
|
|
|
(cherry picked from commit 39cbe772a67aece69dc30f8f394bba2eea9ca762)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/devices/nm-device.c | 28 +++++++++++++++++++++++++++-
|
|
1 file changed, 27 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index e8ed2ba..2e870a8 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -36,6 +36,7 @@
|
|
#include <arpa/inet.h>
|
|
#include <fcntl.h>
|
|
#include <linux/if.h>
|
|
+#include <netlink/route/addr.h>
|
|
|
|
#include "libgsystem.h"
|
|
#include "nm-glib-compat.h"
|
|
@@ -68,6 +69,11 @@
|
|
#include "nm-config.h"
|
|
#include "nm-platform.h"
|
|
|
|
+/* workaround for older libnl version, that does not define this flag. */
|
|
+#ifndef IFA_F_NOPREFIXROUTE
|
|
+#define IFA_F_NOPREFIXROUTE 0x200
|
|
+#endif
|
|
+
|
|
static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context);
|
|
|
|
#include "nm-device-glue.h"
|
|
@@ -3218,6 +3224,25 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|
NMConnection *connection;
|
|
int i;
|
|
NMDeviceStateReason reason;
|
|
+ static int system_support = -1;
|
|
+ guint ifa_flags;
|
|
+
|
|
+ if (system_support == -1) {
|
|
+ /*
|
|
+ * Check, if both libnl and the kernel are recent enough,
|
|
+ * to help user space handling RA. If it's not supported,
|
|
+ * we must add autoconf addresses as /128.
|
|
+ * The reason for /128 is to prevent the kernel from adding
|
|
+ * a prefix route for this address.
|
|
+ **/
|
|
+ system_support = nm_platform_check_support_libnl_extended_ifa_flags () &&
|
|
+ nm_platform_check_support_kernel_extended_ifa_flags ();
|
|
+ }
|
|
+
|
|
+ /* without system_support, this flag will be ignored.
|
|
+ * Still, we set it (why not?).
|
|
+ **/
|
|
+ ifa_flags = IFA_F_NOPREFIXROUTE;
|
|
|
|
g_return_if_fail (priv->act_request);
|
|
connection = nm_device_get_connection (device);
|
|
@@ -3251,10 +3276,11 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|
|
|
memset (&address, 0, sizeof (address));
|
|
address.address = discovered_address->address;
|
|
- address.plen = 128;
|
|
+ address.plen = system_support ? 64 : 128;
|
|
address.timestamp = discovered_address->timestamp;
|
|
address.lifetime = discovered_address->lifetime;
|
|
address.preferred = discovered_address->preferred;
|
|
+ address.flags = ifa_flags;
|
|
|
|
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
|
|
}
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 14705adcd0a1f87d31623cd3c99978d1a5c0161a Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Fri, 3 Jan 2014 17:03:35 +0100
|
|
Subject: [PATCH 14/14] core/rdisc: add support for IPv6 privacy
|
|
|
|
Add support for ipv6-private addresses. This feature
|
|
needs support from the kernel and libnl.
|
|
|
|
If there is no system support, temporary addresses are
|
|
not supported. Log a warning in this case.
|
|
|
|
Depending on whether ipv6-privacy (use_tempaddr) is enabled,
|
|
we add the address flag IFA_F_MANAGETEMPADDR and the kernel
|
|
will add temporary addresses for us.
|
|
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=705170
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1003859
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1047139
|
|
|
|
(cherry picked from commit 1dea2714697b8cfe386c6665d7e556d537bebaf0)
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
---
|
|
src/devices/nm-device.c | 122 +++++++++++++++++++++++++++++++++++++-----------
|
|
1 file changed, 96 insertions(+), 26 deletions(-)
|
|
|
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
|
index 2e870a8..39146a6 100644
|
|
--- a/src/devices/nm-device.c
|
|
+++ b/src/devices/nm-device.c
|
|
@@ -69,7 +69,10 @@
|
|
#include "nm-config.h"
|
|
#include "nm-platform.h"
|
|
|
|
-/* workaround for older libnl version, that does not define this flag. */
|
|
+/* workaround for older libnl version, that does not define these flags. */
|
|
+#ifndef IFA_F_MANAGETEMPADDR
|
|
+#define IFA_F_MANAGETEMPADDR 0x100
|
|
+#endif
|
|
#ifndef IFA_F_NOPREFIXROUTE
|
|
#define IFA_F_NOPREFIXROUTE 0x200
|
|
#endif
|
|
@@ -272,6 +275,7 @@ typedef struct {
|
|
|
|
NMRDisc * rdisc;
|
|
gulong rdisc_config_changed_sigid;
|
|
+ NMSettingIP6ConfigPrivacy rdisc_use_tempaddr;
|
|
/* IP6 config from autoconf */
|
|
NMIP6Config * ac_ip6_config;
|
|
|
|
@@ -3218,6 +3222,53 @@ linklocal6_start (NMDevice *self)
|
|
static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release);
|
|
|
|
static void
|
|
+print_support_extended_ifa_flags (NMSettingIP6ConfigPrivacy use_tempaddr)
|
|
+{
|
|
+ static gint8 warn = 0;
|
|
+ static gint8 s_libnl = -1, s_kernel;
|
|
+
|
|
+ if (warn >= 2)
|
|
+ return;
|
|
+
|
|
+ if (s_libnl == -1) {
|
|
+ s_libnl = !!nm_platform_check_support_libnl_extended_ifa_flags ();
|
|
+ s_kernel = !!nm_platform_check_support_kernel_extended_ifa_flags ();
|
|
+
|
|
+ if (s_libnl && s_kernel) {
|
|
+ nm_log_dbg (LOGD_IP6, "kernel and libnl support extended IFA_FLAGS (needed by NM for IPv6 private addresses)");
|
|
+ warn = 2;
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ( use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
|
+ && use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) {
|
|
+ if (warn == 0) {
|
|
+ nm_log_dbg (LOGD_IP6, "%s%s%s %s not support extended IFA_FLAGS (needed by NM for IPv6 private addresses)",
|
|
+ !s_kernel ? "kernel" : "",
|
|
+ !s_kernel && !s_libnl ? " and " : "",
|
|
+ !s_libnl ? "libnl" : "",
|
|
+ !s_kernel && !s_libnl ? "do" : "does");
|
|
+ warn = 1;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!s_libnl && !s_kernel) {
|
|
+ nm_log_warn (LOGD_IP6, "libnl and the kernel do not support extended IFA_FLAGS needed by NM for "
|
|
+ "IPv6 private addresses. This feature is not available");
|
|
+ } else if (!s_libnl) {
|
|
+ nm_log_warn (LOGD_IP6, "libnl does not support extended IFA_FLAGS needed by NM for "
|
|
+ "IPv6 private addresses. This feature is not available");
|
|
+ } else if (!s_kernel) {
|
|
+ nm_log_warn (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for "
|
|
+ "IPv6 private addresses. This feature is not available");
|
|
+ }
|
|
+
|
|
+ warn = 2;
|
|
+}
|
|
+
|
|
+static void
|
|
rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device)
|
|
{
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
|
|
@@ -3231,18 +3282,21 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|
/*
|
|
* Check, if both libnl and the kernel are recent enough,
|
|
* to help user space handling RA. If it's not supported,
|
|
- * we must add autoconf addresses as /128.
|
|
- * The reason for /128 is to prevent the kernel from adding
|
|
- * a prefix route for this address.
|
|
+ * we have no ipv6-privacy and must add autoconf addresses
|
|
+ * as /128. The reason for the /128 is to prevent the kernel
|
|
+ * from adding a prefix route for this address.
|
|
**/
|
|
system_support = nm_platform_check_support_libnl_extended_ifa_flags () &&
|
|
nm_platform_check_support_kernel_extended_ifa_flags ();
|
|
}
|
|
|
|
- /* without system_support, this flag will be ignored.
|
|
- * Still, we set it (why not?).
|
|
+ /* without system_support, these flags will be ignored.
|
|
+ * Still, we set them (why not?).
|
|
**/
|
|
ifa_flags = IFA_F_NOPREFIXROUTE;
|
|
+ if (priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
|
+ || priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
|
+ ifa_flags |= IFA_F_MANAGETEMPADDR;
|
|
|
|
g_return_if_fail (priv->act_request);
|
|
connection = nm_device_get_connection (device);
|
|
@@ -3361,7 +3415,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|
}
|
|
|
|
static gboolean
|
|
-addrconf6_start (NMDevice *self)
|
|
+addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
|
{
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
NMConnection *connection;
|
|
@@ -3385,6 +3439,9 @@ addrconf6_start (NMDevice *self)
|
|
return FALSE;
|
|
}
|
|
|
|
+ priv->rdisc_use_tempaddr = use_tempaddr;
|
|
+ print_support_extended_ifa_flags (use_tempaddr);
|
|
+
|
|
/* ensure link local is ready... */
|
|
ret = linklocal6_start (self);
|
|
|
|
@@ -3432,10 +3489,23 @@ addrconf6_cleanup (NMDevice *self)
|
|
|
|
/******************************************/
|
|
|
|
+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 int
|
|
+static NMSettingIP6ConfigPrivacy
|
|
ip6_use_tempaddr (void)
|
|
{
|
|
char *contents = NULL;
|
|
@@ -3443,12 +3513,13 @@ ip6_use_tempaddr (void)
|
|
char *sysctl_data = NULL;
|
|
GKeyFile *keyfile;
|
|
GError *error = NULL;
|
|
- int tmp, ret = -1;
|
|
+ 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 -1;
|
|
+ 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);
|
|
@@ -3459,7 +3530,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 = tmp;
|
|
+ ret = use_tempaddr_clamp (tmp);
|
|
|
|
done:
|
|
g_free (contents);
|
|
@@ -3499,8 +3570,7 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
|
|
NMConnection *connection;
|
|
NMSettingIP6Config *s_ip6;
|
|
- const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
|
|
- int conf_use_tempaddr;
|
|
+ const char *method;
|
|
NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
|
const char *ip6_privacy_str = "0\n";
|
|
GSList *slaves;
|
|
@@ -3554,8 +3624,19 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|
|
|
priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE;
|
|
|
|
- if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
|
- if (!addrconf6_start (self)) {
|
|
+ /* 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) {
|
|
+ if (s_ip6)
|
|
+ ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6);
|
|
+ }
|
|
+ ip6_privacy = use_tempaddr_clamp (ip6_privacy);
|
|
+
|
|
+ if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
|
+ if (!addrconf6_start (self, ip6_privacy)) {
|
|
/* IPv6 might be disabled; allow IPv4 to proceed */
|
|
ret = NM_ACT_STAGE_RETURN_STOP;
|
|
} else
|
|
@@ -3597,17 +3678,6 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|
|
|
/* Other methods (shared) aren't implemented yet */
|
|
|
|
- /* 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.
|
|
- */
|
|
- conf_use_tempaddr = ip6_use_tempaddr ();
|
|
- if (conf_use_tempaddr >= 0)
|
|
- ip6_privacy = conf_use_tempaddr;
|
|
- else if (s_ip6)
|
|
- ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6);
|
|
- ip6_privacy = CLAMP (ip6_privacy, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
|
|
-
|
|
switch (ip6_privacy) {
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN:
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
|
|
--
|
|
1.8.5.3
|
|
|