summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-08-05 16:30:34 +0200
committerThomas Haller <thaller@redhat.com>2020-08-05 16:30:34 +0200
commit06e7d72265a20026fad82bad8dab0997080e9d45 (patch)
tree80c5c82062686c3009a9893f08504daea0efbb57
parent26d768a2b670e8f98253e2958e8d0d1017d8f4ee (diff)
parent79db3972d734d16785b451ab93e25291eb620d33 (diff)
downloadNetworkManager-06e7d72265a20026fad82bad8dab0997080e9d45.tar.gz
l3cfg: merge branch 'th/l3cfg-4'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/595
-rw-r--r--Makefile.am15
-rw-r--r--shared/nm-glib-aux/nm-macros-internal.h24
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c87
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h24
-rw-r--r--shared/nm-glib-aux/tests/test-shared-general.c57
-rw-r--r--shared/nm-std-aux/nm-std-aux.h60
-rw-r--r--shared/nm-utils/nm-test-utils.h8
-rw-r--r--src/NetworkManagerUtils.c243
-rw-r--r--src/NetworkManagerUtils.h15
-rw-r--r--src/devices/nm-device.c2
-rw-r--r--src/dhcp/nm-dhcp-client.c2
-rw-r--r--src/dhcp/nm-dhcp-nettools.c5
-rw-r--r--src/dhcp/nm-dhcp-utils.c122
-rw-r--r--src/dns/nm-dns-manager.c6
-rw-r--r--src/meson.build7
-rw-r--r--src/nm-core-utils.c14
-rw-r--r--src/nm-dbus-object.c28
-rw-r--r--src/nm-dbus-object.h2
-rw-r--r--src/nm-ip-config.c135
-rw-r--r--src/nm-ip-config.h44
-rw-r--r--src/nm-ip4-config.c182
-rw-r--r--src/nm-ip4-config.h5
-rw-r--r--src/nm-ip6-config.c167
-rw-r--r--src/nm-ip6-config.h1
-rw-r--r--src/nm-l3-config-data.c185
-rw-r--r--src/nm-l3-config-data.h151
-rw-r--r--src/nm-l3cfg.c200
-rw-r--r--src/nm-l3cfg.h2
-rw-r--r--src/nm-policy.c4
-rw-r--r--src/nm-types.h1
30 files changed, 1210 insertions, 588 deletions
diff --git a/Makefile.am b/Makefile.am
index af2c7cb24b..5841cbe72a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2120,6 +2120,14 @@ src_libNetworkManagerBase_la_SOURCES = \
src/nm-dbus-utils.h \
src/nm-dbus-object.c \
src/nm-dbus-object.h \
+ src/nm-netns.c \
+ src/nm-netns.h \
+ src/nm-l3-config-data.c \
+ src/nm-l3-config-data.h \
+ src/nm-l3cfg.c \
+ src/nm-l3cfg.h \
+ src/nm-ip-config.c \
+ src/nm-ip-config.h \
src/nm-ip4-config.c \
src/nm-ip4-config.h \
src/nm-ip6-config.c \
@@ -2170,11 +2178,6 @@ src_libNetworkManager_la_SOURCES = \
src/nm-checkpoint-manager.c \
src/nm-checkpoint-manager.h \
\
- src/nm-l3-config-data.c \
- src/nm-l3-config-data.h \
- src/nm-l3cfg.c \
- src/nm-l3cfg.h \
- \
src/devices/nm-acd-manager.c \
src/devices/nm-acd-manager.h \
src/devices/nm-lldp-listener.c \
@@ -2315,8 +2318,6 @@ src_libNetworkManager_la_SOURCES = \
src/nm-connectivity.h \
src/nm-dcb.c \
src/nm-dcb.h \
- src/nm-netns.c \
- src/nm-netns.h \
src/nm-dhcp-config.c \
src/nm-dhcp-config.h \
src/nm-dispatcher.c \
diff --git a/shared/nm-glib-aux/nm-macros-internal.h b/shared/nm-glib-aux/nm-macros-internal.h
index 551cd92f16..c917272384 100644
--- a/shared/nm-glib-aux/nm-macros-internal.h
+++ b/shared/nm-glib-aux/nm-macros-internal.h
@@ -1233,6 +1233,30 @@ nm_strcmp_p (gconstpointer a, gconstpointer b)
/*****************************************************************************/
+static inline int
+_NM_IN_STRSET_ASCII_CASE_op_streq (const char *x, const char *s)
+{
+ return s && g_ascii_strcasecmp (x, s) == 0;
+}
+
+#define NM_IN_STRSET_ASCII_CASE(x, ...) _NM_IN_STRSET_EVAL_N(||, _NM_IN_STRSET_ASCII_CASE_op_streq, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
+
+#define NM_STR_HAS_SUFFIX_ASCII_CASE(str, suffix) \
+ ({ \
+ const char *const _str_has_suffix = (str); \
+ size_t _l; \
+ \
+ nm_assert (strlen (suffix) == NM_STRLEN (suffix)); \
+ \
+ ( _str_has_suffix \
+ && ((_l = strlen (_str_has_suffix)) >= NM_STRLEN (suffix)) \
+ && (g_ascii_strncasecmp (&_str_has_suffix[_l - NM_STRLEN (suffix)], \
+ ""suffix"", \
+ NM_STRLEN (suffix)) == 0)); \
+ })
+
+/*****************************************************************************/
+
#define nm_g_slice_free(ptr) \
g_slice_free (typeof (*(ptr)), ptr)
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
index e7dbaa8a81..b973d8aafc 100644
--- a/shared/nm-glib-aux/nm-shared-utils.c
+++ b/shared/nm-glib-aux/nm-shared-utils.c
@@ -1382,6 +1382,15 @@ nm_strcmp0_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data)
}
int
+nm_strcmp_ascii_case_with_data (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ const char *s1 = a;
+ const char *s2 = b;
+
+ return g_ascii_strcasecmp (s1, s2);
+}
+
+int
nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
{
const guint32 a = *((const guint32 *) p_a);
@@ -5148,3 +5157,81 @@ _nm_utils_format_variant_attributes (GHashTable *attributes,
key_value_separator);
return g_string_free (str, FALSE);
}
+
+/*****************************************************************************/
+
+gboolean
+nm_utils_is_localhost (const char *name)
+{
+ static const char *const NAMES[] = {
+ "localhost",
+ "localhost4",
+ "localhost6",
+ "localhost.localdomain",
+ "localhost4.localdomain4",
+ "localhost6.localdomain6",
+ };
+ gsize name_len;
+ int i;
+
+ if (!name)
+ return FALSE;
+
+ /* This tries to identify local host and domain names
+ * described in RFC6761 plus the redhatism of localdomain.
+ *
+ * Similar to systemd's is_localhost(). */
+
+ name_len = strlen (name);
+
+ if (name_len == 0)
+ return FALSE;
+
+ if (name[name_len - 1] == '.') {
+ /* one trailing dot is fine. Hide it. */
+ name_len--;
+ }
+
+ for (i = 0; i < (int) G_N_ELEMENTS (NAMES); i++) {
+ const char *n = NAMES[i];
+ gsize l = strlen (n);
+ gsize s;
+
+ if (name_len < l)
+ continue;
+
+ s = name_len - l;
+
+ if (g_ascii_strncasecmp (&name[s], n, l) != 0)
+ continue;
+
+ /* we accept the name if it is equal to one of the well-known names,
+ * or if it is some prefix, a '.' and the well-known name. */
+ if (s == 0)
+ return TRUE;
+ if (name[s - 1] == '.')
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+nm_utils_is_specific_hostname (const char *name)
+{
+ if (nm_str_is_empty (name))
+ return FALSE;
+
+ if (nm_streq (name, "(none)")) {
+ /* This is not a special hostname. Probably an artefact by somebody wrongly
+ * printing NULL. */
+ return FALSE;
+ }
+
+ if (nm_utils_is_localhost (name))
+ return FALSE;
+
+ /* FIXME: properly validate the hostname, like systemd's hostname_is_valid() */
+
+ return TRUE;
+}
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
index d44321d34e..f9c76d880e 100644
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ b/shared/nm-glib-aux/nm-shared-utils.h
@@ -1427,6 +1427,7 @@ nm_utf8_collate0 (const char *a, const char *b)
int nm_strcmp_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
int nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
int nm_strcmp0_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
+int nm_strcmp_ascii_case_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
int nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data);
int nm_cmp_int2ptr_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data);
@@ -1821,6 +1822,23 @@ nm_strv_ptrarray_ensure (GPtrArray **p_arr)
return *p_arr;
}
+static inline const char *const*
+nm_strv_ptrarray_get_unsafe (GPtrArray *arr,
+ guint *out_len)
+{
+ /* warning: the GPtrArray is not NULL terminated. So, it
+ * isn't really a strv array (sorry the misnomer). That's why
+ * the function is potentially "unsafe" and you must provide a
+ * out_len parameter. */
+ if ( !arr
+ || arr->len == 0) {
+ *out_len = 0;
+ return NULL;
+ }
+ *out_len = arr->len;
+ return (const char *const*) arr->pdata;
+}
+
static inline GPtrArray *
nm_strv_ptrarray_clone (const GPtrArray *src, gboolean null_if_empty)
{
@@ -2177,4 +2195,10 @@ char *_nm_utils_format_variant_attributes (GHashTable *attributes,
char attr_separator,
char key_value_separator);
+/*****************************************************************************/
+
+gboolean nm_utils_is_localhost (const char *name);
+
+gboolean nm_utils_is_specific_hostname (const char *name);
+
#endif /* __NM_SHARED_UTILS_H__ */
diff --git a/shared/nm-glib-aux/tests/test-shared-general.c b/shared/nm-glib-aux/tests/test-shared-general.c
index 02b2f4e1ea..9af5f2b050 100644
--- a/shared/nm-glib-aux/tests/test-shared-general.c
+++ b/shared/nm-glib-aux/tests/test-shared-general.c
@@ -25,6 +25,11 @@ G_STATIC_ASSERT (NM_AF_INET_SIZE == sizeof (in_addr_t));
G_STATIC_ASSERT (NM_AF_INET_SIZE == sizeof (struct in_addr));
G_STATIC_ASSERT (NM_AF_INET6_SIZE == sizeof (struct in6_addr));
+G_STATIC_ASSERT (4 == _nm_alignof (in_addr_t));
+G_STATIC_ASSERT (4 == _nm_alignof (struct in_addr));
+G_STATIC_ASSERT (4 == _nm_alignof (struct in6_addr));
+G_STATIC_ASSERT (4 == _nm_alignof (NMIPAddr));
+
/*****************************************************************************/
static void
@@ -886,6 +891,56 @@ again:
/*****************************************************************************/
+static void
+test_in_strset_ascii_case (void)
+{
+ const char *x;
+
+ x = NULL;
+ g_assert (NM_IN_STRSET_ASCII_CASE (x, NULL));
+ g_assert (NM_IN_STRSET_ASCII_CASE (x, NULL, "b"));
+ g_assert (!NM_IN_STRSET_ASCII_CASE (x, "b"));
+
+ x = "b";
+ g_assert (NM_IN_STRSET (x, "b"));
+ g_assert (NM_IN_STRSET_ASCII_CASE (x, "b"));
+ g_assert (!NM_IN_STRSET (x, "B"));
+ g_assert (NM_IN_STRSET_ASCII_CASE (x, "B"));
+}
+
+/*****************************************************************************/
+
+static void
+test_is_specific_hostname (void)
+{
+ g_assert (!nm_utils_is_specific_hostname (NULL));
+ g_assert (!nm_utils_is_specific_hostname (""));
+ g_assert (!nm_utils_is_specific_hostname ("(none)"));
+ g_assert (nm_utils_is_specific_hostname ("(NONE)"));
+
+ g_assert (!nm_utils_is_specific_hostname ("localhost"));
+ g_assert (!nm_utils_is_specific_hostname ("lOcalHost"));
+ g_assert (!nm_utils_is_specific_hostname ("LOCALHOST"));
+
+ g_assert (!nm_utils_is_specific_hostname ("LOCALHOST.localdomain"));
+
+ g_assert (nm_utils_is_specific_hostname ("xlocalhost"));
+ g_assert (nm_utils_is_specific_hostname ("lOcalHxost"));
+ g_assert (nm_utils_is_specific_hostname ("LOCALxHOST"));
+
+ g_assert (!nm_utils_is_specific_hostname ("foo.LOCALHOST"));
+ g_assert (!nm_utils_is_specific_hostname ("foo.LOCALHOsT6."));
+ g_assert (!nm_utils_is_specific_hostname ("foo.LOCALHOsT6.localdomain6"));
+ g_assert (!nm_utils_is_specific_hostname (".LOCALHOsT6.localdomain6"));
+ g_assert (!nm_utils_is_specific_hostname ("LOCALHOsT6.localdomain6"));
+ g_assert (!nm_utils_is_specific_hostname ("LOCALHOsT6.localdomain6."));
+ g_assert (nm_utils_is_specific_hostname ("LOCALHOsT6.localdomain."));
+
+ g_assert (nm_utils_is_specific_hostname (" "));
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -908,6 +963,8 @@ int main (int argc, char **argv)
g_test_add_func ("/general/test_nm_utils_get_next_realloc_size", test_nm_utils_get_next_realloc_size);
g_test_add_func ("/general/test_nm_str_buf", test_nm_str_buf);
g_test_add_func ("/general/test_nm_utils_parse_next_line", test_nm_utils_parse_next_line);
+ g_test_add_func ("/general/test_in_strset_ascii_case", test_in_strset_ascii_case);
+ g_test_add_func ("/general/test_is_specific_hostname", test_is_specific_hostname);
return g_test_run ();
}
diff --git a/shared/nm-std-aux/nm-std-aux.h b/shared/nm-std-aux/nm-std-aux.h
index b3f80bbd65..0133a79643 100644
--- a/shared/nm-std-aux/nm-std-aux.h
+++ b/shared/nm-std-aux/nm-std-aux.h
@@ -370,47 +370,51 @@ nm_streq0 (const char *s1, const char *s2)
/*****************************************************************************/
-static inline int
-_NM_IN_STRSET_streq (const char *x, const char *s)
-{
- return s && strcmp (x, s) == 0;
-}
+#define _NM_IN_SETOP_EVAL_1( op, op_eq, _x, y) (op_eq (_x, y))
+#define _NM_IN_SETOP_EVAL_2( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_1 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_3( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_2 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_4( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_3 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_5( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_4 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_6( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_5 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_7( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_6 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_8( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_7 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_9( op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_8 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_10(op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_9 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_11(op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_10 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_12(op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_11 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_13(op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_12 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_14(op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_13 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_15(op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_14 (op, op_eq, _x, __VA_ARGS__)
+#define _NM_IN_SETOP_EVAL_16(op, op_eq, _x, y, ...) (op_eq (_x, y)) op _NM_IN_SETOP_EVAL_15 (op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_1( op, _x, y) _NM_IN_STRSET_streq (_x, y)
-#define _NM_IN_STRSET_EVAL_2( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_1 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_3( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_2 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_4( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_3 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_5( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_4 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_6( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_5 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_7( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_6 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_8( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_7 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_9( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_8 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_10(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_9 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_11(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_10 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_12(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_11 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_13(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_12 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_14(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_13 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_15(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_14 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_16(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_15 (op, _x, __VA_ARGS__)
-
-#define _NM_IN_STRSET_EVAL_N2(op, _x, n, ...) (_NM_IN_STRSET_EVAL_##n(op, _x, __VA_ARGS__))
-#define _NM_IN_STRSET_EVAL_N(op, x, n, ...) \
+/*****************************************************************************/
+
+#define _NM_IN_STRSET_EVAL_N2(op, op_ed, _x, n, ...) (_NM_IN_SETOP_EVAL_##n(op, op_ed, _x, __VA_ARGS__))
+#define _NM_IN_STRSET_EVAL_N(op, op_ed, x, n, ...) \
({ \
const char *_x = (x); \
- ( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, ((const char *) NULL), n, __VA_ARGS__)) \
- || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x, n, __VA_ARGS__)) \
+ ( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, ((const char *) NULL), n, __VA_ARGS__)) \
+ || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, op_ed, _x, n, __VA_ARGS__)) \
); \
})
+/*****************************************************************************/
+
+static inline int
+_NM_IN_STRSET_op_streq (const char *x, const char *s)
+{
+ return s && strcmp (x, s) == 0;
+}
+
/* Beware that this does short-circuit evaluation (use "||" instead of "|")
* which has a possibly unexpected non-function-like behavior.
* Use NM_IN_STRSET_SE if you need all arguments to be evaluated. */
-#define NM_IN_STRSET(x, ...) _NM_IN_STRSET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
+#define NM_IN_STRSET(x, ...) _NM_IN_STRSET_EVAL_N(||, _NM_IN_STRSET_op_streq, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
/* "SE" stands for "side-effect". Contrary to NM_IN_STRSET(), this does not do
* short-circuit evaluation, which can make a difference if the arguments have
* side-effects. */
-#define NM_IN_STRSET_SE(x, ...) _NM_IN_STRSET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
+#define NM_IN_STRSET_SE(x, ...) _NM_IN_STRSET_EVAL_N(|, _NM_IN_STRSET_op_streq, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
/*****************************************************************************/
diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h
index b43e233007..1e3a99eb82 100644
--- a/shared/nm-utils/nm-test-utils.h
+++ b/shared/nm-utils/nm-test-utils.h
@@ -1505,6 +1505,14 @@ _nmtst_assert_ip6_address (const char *file, int line, const struct in6_addr *ad
}
#define nmtst_assert_ip6_address(addr, str_expected) _nmtst_assert_ip6_address (__FILE__, __LINE__, addr, str_expected)
+#define nmtst_assert_ip_address(addr_family, addr, str_expected) \
+ G_STMT_START { \
+ if (NM_IS_IPv4 (addr_family)) \
+ nmtst_assert_ip4_address (*((const in_addr_t *) (addr)), (str_expected)); \
+ else \
+ nmtst_assert_ip6_address ((const struct in6_addr *) (addr), (str_expected)); \
+ } G_STMT_END
+
#define nmtst_spawn_sync(working_directory, standard_out, standard_err, assert_exit_status, ...) \
__nmtst_spawn_sync (working_directory, standard_out, standard_err, assert_exit_status, ##__VA_ARGS__, NULL)
static inline int
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 230ffcda53..49d9a9d723 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -1365,4 +1365,247 @@ nm_utils_ip_route_attribute_to_platform (int addr_family,
#undef GET_ATTR
}
+/*****************************************************************************/
+
+static int
+_addresses_sort_cmp_4 (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ return nm_platform_ip4_address_pretty_sort_cmp (NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) a)),
+ NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) b)));
+}
+
+static int
+_addresses_sort_cmp_6 (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ return nm_platform_ip6_address_pretty_sort_cmp (NMP_OBJECT_CAST_IP6_ADDRESS (*((const NMPObject **) a)),
+ NMP_OBJECT_CAST_IP6_ADDRESS (*((const NMPObject **) b)),
+ (((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT (user_data)) == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
+}
+
+void
+nm_utils_ip_addresses_to_dbus (int addr_family,
+ const NMDedupMultiHeadEntry *head_entry,
+ const NMPObject *best_default_route,
+ NMSettingIP6ConfigPrivacy ipv6_privacy,
+ GVariant **out_address_data,
+ GVariant **out_addresses)
+{
+ const gboolean IS_IPv4 = NM_IS_IPv4 (addr_family);
+ GVariantBuilder builder_data;
+ GVariantBuilder builder_legacy;
+ char addr_str[NM_UTILS_INET_ADDRSTRLEN];
+ gs_free const NMPObject **addresses = NULL;
+ guint naddr;
+ guint i;
+
+ nm_assert_addr_family (addr_family);
+
+ if (out_address_data)
+ g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
+ if (out_addresses) {
+ if (IS_IPv4)
+ g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("aau"));
+ else
+ g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("a(ayuay)"));
+ }
+
+ if (!head_entry)
+ goto out;
+
+ addresses = (const NMPObject **) nm_dedup_multi_objs_to_array_head (head_entry, NULL, NULL, &naddr);
+
+ nm_assert (addresses && naddr);
+
+ g_qsort_with_data (addresses,
+ naddr,
+ sizeof (addresses[0]),
+ IS_IPv4
+ ? _addresses_sort_cmp_4
+ : _addresses_sort_cmp_6,
+ GINT_TO_POINTER (ipv6_privacy));
+
+ for (i = 0; i < naddr; i++) {
+ const NMPlatformIPXAddress *address = NMP_OBJECT_CAST_IPX_ADDRESS (addresses[i]);
+
+ if (out_address_data) {
+ GVariantBuilder addr_builder;
+ gconstpointer p;
+
+ g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
+
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "address",
+ g_variant_new_string (nm_utils_inet_ntop (addr_family, address->ax.address_ptr, addr_str)));
+
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (address->ax.plen));
+
+ p = NULL;
+ if (IS_IPv4) {
+ if (address->a4.peer_address != address->a4.address)
+ p = &address->a4.peer_address;
+ } else {
+ if ( !IN6_IS_ADDR_UNSPECIFIED (&address->a6.peer_address)
+ && !IN6_ARE_ADDR_EQUAL (&address->a6.peer_address, &address->a6.address))
+ p = &address->a6.peer_address;
+ }
+ if (p) {
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "peer",
+ g_variant_new_string (nm_utils_inet_ntop (addr_family, p, addr_str)));
+ }
+
+ if (IS_IPv4) {
+ if (*address->a4.label) {
+ g_variant_builder_add (&addr_builder, "{sv}",
+ NM_IP_ADDRESS_ATTRIBUTE_LABEL,
+ g_variant_new_string (address->a4.label));
+ }
+ }
+
+ g_variant_builder_add (&builder_data, "a{sv}", &addr_builder);
+ }
+ if (out_addresses) {
+ if (IS_IPv4) {
+ const guint32 dbus_addr[3] = {
+ address->a4.address,
+ address->a4.plen,
+ ( i == 0
+ && best_default_route)
+ ? NMP_OBJECT_CAST_IP4_ROUTE (best_default_route)->gateway
+ : (guint32) 0,
+ };
+
+ g_variant_builder_add (&builder_legacy, "@au",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ dbus_addr, 3, sizeof (guint32)));
+ } else {
+ g_variant_builder_add (&builder_legacy, "(@ayu@ay)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ &address->a6.address, 16, 1),
+ address->a6.plen,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ ( i == 0
+ && best_default_route)
+ ? &NMP_OBJECT_CAST_IP6_ROUTE (best_default_route)->gateway
+ : &in6addr_any,
+ 16, 1));
+ }
+ }
+ }
+
+out:
+ NM_SET_OUT (out_address_data, g_variant_builder_end (&builder_data));
+ NM_SET_OUT (out_addresses, g_variant_builder_end (&builder_legacy));
+}
+
+void
+nm_utils_ip_routes_to_dbus (int addr_family,
+ const NMDedupMultiHeadEntry *head_entry,
+ GVariant **out_route_data,
+ GVariant **out_routes)
+{
+ const gboolean IS_IPv4 = NM_IS_IPv4 (addr_family);
+ NMDedupMultiIter iter;
+ const NMPObject *obj;
+ GVariantBuilder builder_data;
+ GVariantBuilder builder_legacy;
+ char addr_str[NM_UTILS_INET_ADDRSTRLEN];
+
+ nm_assert_addr_family (addr_family);
+
+ if (out_route_data)
+ g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
+ if (out_routes) {
+ if (IS_IPv4)
+ g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("aau"));
+ else
+ g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("a(ayuayu)"));
+ }
+
+ nm_dedup_multi_iter_init (&iter, head_entry);
+ while (nm_platform_dedup_multi_iter_next_obj (&iter, &obj, NMP_OBJECT_TYPE_IP_ROUTE (IS_IPv4))) {
+ const NMPlatformIPXRoute *r = NMP_OBJECT_CAST_IPX_ROUTE (obj);
+ struct in6_addr n;
+
+ nm_assert (r);
+ nm_assert (r->rx.plen <= 8u * nm_utils_addr_family_to_size (addr_family));
+ nm_assert ( !IS_IPv4
+ || r->r4.network == nm_utils_ip4_address_clear_host_address (r->r4.network, r->r4.plen));
+ nm_assert ( IS_IPv4
+ || (memcmp (&r->r6.network,
+ nm_utils_ip6_address_clear_host_address (&n, &r->r6.network, r->r6.plen),
+ sizeof (n)) == 0));
+
+ if (r->rx.type_coerced != nm_platform_route_type_coerce (RTN_UNICAST))
+ continue;
+
+ if (out_route_data) {
+ GVariantBuilder route_builder;
+ gconstpointer gateway;
+
+ g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
+
+ g_variant_builder_add (&route_builder, "{sv}",
+ "dest",
+ g_variant_new_string (nm_utils_inet_ntop (addr_family, r->rx.network_ptr, addr_str)));
+
+ g_variant_builder_add (&route_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (r->rx.plen));
+
+ gateway = nm_platform_ip_route_get_gateway (addr_family, &r->rx);
+ if (!nm_ip_addr_is_null (addr_family, gateway)) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "next-hop",
+ g_variant_new_string (nm_utils_inet_ntop (addr_family, gateway, addr_str)));
+ }
+
+ g_variant_builder_add (&route_builder, "{sv}",
+ "metric",
+ g_variant_new_uint32 (r->rx.metric));
+
+ if (!nm_platform_route_table_is_main (r->rx.table_coerced)) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "table",
+ g_variant_new_uint32 (nm_platform_route_table_uncoerce (r->rx.table_coerced, TRUE)));
+ }
+
+ g_variant_builder_add (&builder_data, "a{sv}", &route_builder);
+ }
+
+ if (out_routes) {
+ /* legacy versions of nm_ip[46]_route_set_prefix() in libnm-util assert that the
+ * plen is positive. Skip the default routes not to break older clients. */
+ if ( !nm_platform_route_table_is_main (r->rx.table_coerced)
+ || NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
+ continue;
+
+ if (IS_IPv4) {
+ const guint32 dbus_route[4] = {
+ r->r4.network,
+ r->r4.plen,
+ r->r4.gateway,
+ r->r4.metric,
+ };
+
+ g_variant_builder_add (&builder_legacy, "@au",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ dbus_route, 4, sizeof (guint32)));
+ } else {
+ g_variant_builder_add (&builder_legacy, "(@ayu@ayu)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ &r->r6.network, 16, 1),
+ (guint32) r->r6.plen,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ &r->r6.gateway, 16, 1),
+ (guint32) r->r6.metric);
+ }
+ }
+ }
+
+ NM_SET_OUT (out_route_data, g_variant_builder_end (&builder_data));
+ NM_SET_OUT (out_routes, g_variant_builder_end (&builder_legacy));
+}
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index b0cb68e306..7d2b81dd49 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -8,8 +8,9 @@
#define __NETWORKMANAGER_UTILS_H__
#include "nm-core-utils.h"
-
+#include "nm-glib-aux/nm-dedup-multi.h"
#include "nm-setting-ip-config.h"
+#include "nm-setting-ip6-config.h"
#include "platform/nm-platform.h"
/*****************************************************************************/
@@ -146,4 +147,16 @@ void nm_utils_ip_route_attribute_to_platform (int addr_family,
NMPlatformIPRoute *r,
guint32 route_table);
+void nm_utils_ip_addresses_to_dbus (int addr_family,
+ const NMDedupMultiHeadEntry *head_entry,
+ const NMPObject *best_default_route,
+ NMSettingIP6ConfigPrivacy ipv6_privacy,
+ GVariant **out_address_data,
+ GVariant **out_addresses);
+
+void nm_utils_ip_routes_to_dbus (int addr_family,
+ const NMDedupMultiHeadEntry *head_entry,
+ GVariant **out_route_data,
+ GVariant **out_routes);
+
#endif /* __NETWORKMANAGER_UTILS_H__ */
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 03a1a59db6..ad23d14ce4 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1247,7 +1247,7 @@ applied_config_init (AppliedConfig *config, gpointer ip_config)
|| (!config->orig && !config->current)
|| nm_ip_config_get_addr_family (ip_config) == nm_ip_config_get_addr_family (config->orig ?: config->current));
nm_assert ( !ip_config
- || NM_IS_IP_CONFIG (ip_config, AF_UNSPEC));
+ || NM_IS_IP_CONFIG (ip_config));
nm_g_object_ref (ip_config);
applied_config_clear (config);
diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c
index 1a41f1b343..a1b786ca9b 100644
--- a/src/dhcp/nm-dhcp-client.c
+++ b/src/dhcp/nm-dhcp-client.c
@@ -428,7 +428,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
gs_free char *event_id = NULL;
if (NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
- g_return_if_fail (NM_IS_IP_CONFIG (ip_config, priv->addr_family));
+ g_return_if_fail (NM_IS_IP_CONFIG_ADDR_FAMILY (ip_config, priv->addr_family));
g_return_if_fail (options);
} else {
g_return_if_fail (!ip_config);
diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/dhcp/nm-dhcp-nettools.c
index a8127236c7..8d7d021710 100644
--- a/src/dhcp/nm-dhcp-nettools.c
+++ b/src/dhcp/nm-dhcp-nettools.c
@@ -14,7 +14,6 @@
#include <net/if_arp.h>
#include "nm-sd-adapt-shared.h"
-#include "hostname-util.h"
#include "nm-glib-aux/nm-dedup-multi.h"
#include "nm-std-aux/unaligned.h"
@@ -747,7 +746,7 @@ lease_parse_hostname (NDhcp4ClientLease *lease,
str = g_string_new_len ((char *)data, n_data);
- if (is_localhost(str->str))
+ if (nm_utils_is_localhost (str->str))
return;
nm_dhcp_option_add_option (options,
@@ -778,7 +777,7 @@ lease_parse_domainname (NDhcp4ClientLease *lease,
nm_gstring_prepare (&str);
for (char **d = domains; *d; d++) {
- if (is_localhost(*d))
+ if (nm_utils_is_localhost (*d))
return;
g_string_append (nm_gstring_add_space_delimiter (str), *d);
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c
index 1c305238fd..88ced0548e 100644
--- a/src/dhcp/nm-dhcp-utils.c
+++ b/src/dhcp/nm-dhcp-utils.c
@@ -28,16 +28,17 @@ ip4_process_dhcpcd_rfc3442_routes (const char *iface,
NMIP4Config *ip4_config,
guint32 *gwaddr)
{
- char **routes, **r;
+ gs_free const char **routes = NULL;
+ const char **r;
gboolean have_routes = FALSE;
- routes = g_strsplit (str, " ", 0);
- if (g_strv_length (routes) == 0)
- goto out;
+ routes = nm_utils_strsplit_set (str, " ");
+ if (!routes)
+ return FALSE;
- if ((g_strv_length (routes) % 2) != 0) {
+ if ((NM_PTRARRAY_LEN (routes) % 2) != 0) {
_LOG2W (LOGD_DHCP4, iface, " classless static routes provided, but invalid");
- goto out;
+ return FALSE;
}
for (r = routes; *r; r += 2) {
@@ -82,8 +83,6 @@ ip4_process_dhcpcd_rfc3442_routes (const char *iface,
}
}
-out:
- g_strfreev (routes);
return have_routes;
}
@@ -263,17 +262,21 @@ process_classful_routes (const char *iface,
guint32 route_metric,
NMIP4Config *ip4_config)
{
+ gs_free const char **searches = NULL;
+ const char **s;
const char *str;
- char **searches, **s;
str = g_hash_table_lookup (options, "static_routes");
if (!str)
return;
- searches = g_strsplit (str, " ", 0);
- if ((g_strv_length (searches) % 2)) {
+ searches = nm_utils_strsplit_set (str, " ");
+ if (!searches)
+ return;
+
+ if ((NM_PTRARRAY_LEN (searches) % 2) != 0) {
_LOG2I (LOGD_DHCP, iface, " static routes provided, but invalid");
- goto out;
+ return;
}
for (s = searches; *s; s += 2) {
@@ -313,9 +316,6 @@ process_classful_routes (const char *iface,
_LOG2I (LOGD_DHCP, iface, " static route %s",
nm_platform_ip4_route_to_string (&route, NULL, 0));
}
-
-out:
- g_strfreev (searches);
}
static void
@@ -324,14 +324,18 @@ process_domain_search (const char *iface,
GFunc add_func,
gpointer user_data)
{
- char **searches, **s;
- char *unescaped, *p;
+ gs_free const char **searches = NULL;
+ gs_free char *unescaped = NULL;
+ const char **s;
+ char *p;
int i;
g_return_if_fail (str != NULL);
g_return_if_fail (add_func != NULL);
- p = unescaped = g_strdup (str);
+ unescaped = g_strdup (str);
+
+ p = unescaped;
do {
p = strstr (p, "\\032");
if (!p)
@@ -344,20 +348,14 @@ process_domain_search (const char *iface,
if (strchr (unescaped, '\\')) {
_LOG2W (LOGD_DHCP, iface, " invalid domain search: '%s'", unescaped);
- goto out;
+ return;
}
- searches = g_strsplit (unescaped, " ", 0);
- for (s = searches; *s; s++) {
- if (strlen (*s)) {
- _LOG2I (LOGD_DHCP, iface, " domain search '%s'", *s);
- add_func (*s, user_data);
- }
+ searches = nm_utils_strsplit_set (unescaped, " ");
+ for (s = searches; searches && *s; s++) {
+ _LOG2I (LOGD_DHCP, iface, " domain search '%s'", *s);
+ add_func ((gpointer) *s, user_data);
}
- g_strfreev (searches);
-
-out:
- g_free (unescaped);
}
static void
@@ -374,7 +372,7 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
guint32 route_table,
guint32 route_metric)
{
- NMIP4Config *ip4_config = NULL;
+ gs_unref_object NMIP4Config *ip4_config = NULL;
guint32 tmp_addr;
in_addr_t addr;
NMPlatformIP4Address address;
@@ -394,7 +392,7 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
if (str && (inet_pton (AF_INET, str, &addr) > 0))
_LOG2I (LOGD_DHCP4, iface, " address %s", str);
else
- goto error;
+ return NULL;
str = g_hash_table_lookup (options, "subnet_mask");
if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) {
@@ -422,10 +420,10 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
*/
str = g_hash_table_lookup (options, "routers");
if (str) {
- char **routers = g_strsplit (str, " ", 0);
- char **s;
+ gs_free const char **routers = nm_utils_strsplit_set (str, " ");
+ const char **s;
- for (s = routers; *s; s++) {
+ for (s = routers; routers && *s; s++) {
/* FIXME: how to handle multiple routers? */
if (inet_pton (AF_INET, *s, &gateway) > 0) {
_LOG2I (LOGD_DHCP4, iface, " gateway %s", *s);
@@ -434,7 +432,6 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
} else
_LOG2W (LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s);
}
- g_strfreev (routers);
}
}
@@ -464,10 +461,10 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
str = g_hash_table_lookup (options, "domain_name_servers");
if (str) {
- char **dns = g_strsplit (str, " ", 0);
- char **s;
+ gs_free const char **dns = nm_utils_strsplit_set (str, " ");
+ const char **s;
- for (s = dns; *s; s++) {
+ for (s = dns; dns && *s; s++) {
if (inet_pton (AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
nm_ip4_config_add_nameserver (ip4_config, tmp_addr);
@@ -476,19 +473,17 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
} else
_LOG2W (LOGD_DHCP4, iface, "ignoring invalid nameserver '%s'", *s);
}
- g_strfreev (dns);
}
str = g_hash_table_lookup (options, "domain_name");
if (str) {
- char **domains = g_strsplit (str, " ", 0);
- char **s;
+ gs_free const char **domains = nm_utils_strsplit_set (str, " ");
+ const char **s;
- for (s = domains; *s; s++) {
+ for (s = domains; domains && *s; s++) {
_LOG2I (LOGD_DHCP4, iface, " domain name '%s'", *s);
nm_ip4_config_add_domain (ip4_config, *s);
}
- g_strfreev (domains);
}
str = g_hash_table_lookup (options, "domain_search");
@@ -497,10 +492,10 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
str = g_hash_table_lookup (options, "netbios_name_servers");
if (str) {
- char **nbns = g_strsplit (str, " ", 0);
- char **s;
+ gs_free const char **nbns = nm_utils_strsplit_set (str, " ");
+ const char **s;
- for (s = nbns; *s; s++) {
+ for (s = nbns; nbns && *s; s++) {
if (inet_pton (AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
nm_ip4_config_add_wins (ip4_config, tmp_addr);
@@ -509,7 +504,6 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
} else
_LOG2W (LOGD_DHCP4, iface, "ignoring invalid WINS server '%s'", *s);
}
- g_strfreev (nbns);
}
str = g_hash_table_lookup (options, "interface_mtu");
@@ -519,7 +513,7 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
errno = 0;
int_mtu = strtol (str, NULL, 10);
if (NM_IN_SET (errno, EINVAL, ERANGE))
- goto error;
+ return NULL;
if (int_mtu > 576)
nm_ip4_config_set_mtu (ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP);
@@ -533,10 +527,10 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
str = g_hash_table_lookup (options, "nis_servers");
if (str) {
- char **nis = g_strsplit (str, " ", 0);
- char **s;
+ gs_free const char **nis = nm_utils_strsplit_set (str, " ");
+ const char **s;
- for (s = nis; *s; s++) {
+ for (s = nis; nis && *s; s++) {
if (inet_pton (AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
nm_ip4_config_add_nis_server (ip4_config, tmp_addr);
@@ -545,17 +539,12 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
} else
_LOG2W (LOGD_DHCP4, iface, "ignoring invalid NIS server '%s'", *s);
}
- g_strfreev (nis);
}
str = g_hash_table_lookup (options, "vendor_encapsulated_options");
nm_ip4_config_set_metered (ip4_config, str && strstr (str, "ANDROID_METERED"));
- return ip4_config;
-
-error:
- g_object_unref (ip4_config);
- return NULL;
+ return g_steal_pointer (&ip4_config);
}
/*****************************************************************************/
@@ -621,7 +610,7 @@ nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx,
GHashTable *options,
gboolean info_only)
{
- NMIP6Config *ip6_config = NULL;
+ gs_unref_object NMIP6Config *ip6_config = NULL;
struct in6_addr tmp_addr;
NMPlatformIP6Address address;
char *str = NULL;
@@ -651,7 +640,7 @@ nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx,
if (!inet_pton (AF_INET6, str, &tmp_addr)) {
_LOG2W (LOGD_DHCP6, iface, "(%s): DHCP returned invalid address '%s'",
iface, str);
- goto error;
+ return NULL;
}
address.address = tmp_addr;
@@ -660,7 +649,7 @@ nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx,
_LOG2I (LOGD_DHCP6, iface, " address %s", str);
} else if (info_only == FALSE) {
/* No address in Managed mode is a hard error */
- goto error;
+ return NULL;
}
str = g_hash_table_lookup (options, "host_name");
@@ -669,10 +658,10 @@ nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx,
str = g_hash_table_lookup (options, "dhcp6_name_servers");
if (str) {
- char **dns = g_strsplit (str, " ", 0);
- char **s;
+ gs_free const char **dns = nm_utils_strsplit_set (str, " ");
+ const char **s;
- for (s = dns; *s; s++) {
+ for (s = dns; dns && *s; s++) {
if (inet_pton (AF_INET6, *s, &tmp_addr) > 0) {
if (!IN6_IS_ADDR_UNSPECIFIED (&tmp_addr)) {
nm_ip6_config_add_nameserver (ip6_config, &tmp_addr);
@@ -681,18 +670,13 @@ nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx,
} else
_LOG2W (LOGD_DHCP6, iface, "ignoring invalid nameserver '%s'", *s);
}
- g_strfreev (dns);
}
str = g_hash_table_lookup (options, "dhcp6_domain_search");
if (str)
process_domain_search (iface, str, ip6_add_domain_search, ip6_config);
- return ip6_config;
-
-error:
- g_object_unref (ip6_config);
- return NULL;
+ return g_steal_pointer (&ip6_config);
}
char *
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c
index 355d2ee445..407d4282d1 100644
--- a/src/dns/nm-dns-manager.c
+++ b/src/dns/nm-dns-manager.c
@@ -215,7 +215,7 @@ _ASSERT_ip_config_data (const NMDnsIPConfigData *ip_data)
{
nm_assert (ip_data);
_ASSERT_config_data (ip_data->data);
- nm_assert (NM_IS_IP_CONFIG (ip_data->ip_config, AF_UNSPEC));
+ nm_assert (NM_IS_IP_CONFIG (ip_data->ip_config));
nm_assert (c_list_contains (&ip_data->data->data_lst_head, &ip_data->data_lst));
nm_assert (ip_data->data->ifindex == nm_ip_config_get_ifindex (ip_data->ip_config));
}
@@ -228,7 +228,7 @@ _ip_config_data_new (NMDnsConfigData *data,
NMDnsIPConfigData *ip_data;
_ASSERT_config_data (data);
- nm_assert (NM_IS_IP_CONFIG (ip_config, AF_UNSPEC));
+ nm_assert (NM_IS_IP_CONFIG (ip_config));
nm_assert (ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED);
ip_data = g_slice_new0 (NMDnsIPConfigData);
@@ -1644,7 +1644,7 @@ nm_dns_manager_set_ip_config (NMDnsManager *self,
NMDnsIPConfigData **p_best;
g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE);
- g_return_val_if_fail (NM_IS_IP_CONFIG (ip_config, AF_UNSPEC), FALSE);
+ g_return_val_if_fail (NM_IS_IP_CONFIG (ip_config), FALSE);
ifindex = nm_ip_config_get_ifindex (ip_config);
g_return_val_if_fail (ifindex > 0, FALSE);
diff --git a/src/meson.build b/src/meson.build
index 468f2159da..b2ea2ba0a1 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -43,6 +43,10 @@ sources = files(
'nm-core-utils.c',
'nm-dbus-object.c',
'nm-dbus-utils.c',
+ 'nm-netns.c',
+ 'nm-l3-config-data.c',
+ 'nm-l3cfg.c',
+ 'nm-ip-config.c',
'nm-ip4-config.c',
'nm-ip6-config.c',
'nm-logging.c',
@@ -131,8 +135,6 @@ sources = files(
'nm-auth-manager.c',
'nm-auth-utils.c',
'nm-dbus-manager.c',
- 'nm-l3-config-data.c',
- 'nm-l3cfg.c',
'nm-checkpoint.c',
'nm-checkpoint-manager.c',
'nm-config.c',
@@ -145,7 +147,6 @@ sources = files(
'nm-hostname-manager.c',
'nm-keep-alive.c',
'nm-manager.c',
- 'nm-netns.c',
'nm-pacrunner-manager.c',
'nm-policy.c',
'nm-proxy-config.c',
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
index 75e0941aa9..674f5de135 100644
--- a/src/nm-core-utils.c
+++ b/src/nm-core-utils.c
@@ -2373,20 +2373,6 @@ NM_ASSERT_VALID_PATH_COMPONENT (const char *name)
g_assert_not_reached ();
}
-gboolean
-nm_utils_is_specific_hostname (const char *name)
-{
- if (!name)
- return FALSE;
- if ( strcmp (name, "(none)")
- && strcmp (name, "localhost")
- && strcmp (name, "localhost6")
- && strcmp (name, "localhost.localdomain")
- && strcmp (name, "localhost6.localdomain6"))
- return TRUE;
- return FALSE;
-}
-
/*****************************************************************************/
typedef struct {
diff --git a/src/nm-dbus-object.c b/src/nm-dbus-object.c
index a133268600..db793b9da3 100644
--- a/src/nm-dbus-object.c
+++ b/src/nm-dbus-object.c
@@ -8,6 +8,7 @@
#include "nm-dbus-object.h"
#include "nm-dbus-manager.h"
+#include "NetworkManagerUtils.h"
/*****************************************************************************/
@@ -144,6 +145,33 @@ nm_dbus_object_unexport (NMDBusObject *self)
self->internal.is_unexporting = FALSE;
}
+static gboolean
+_unexport_on_idle_cb (gpointer user_data)
+{
+ gs_unref_object NMDBusObject *self = user_data;
+
+ nm_dbus_object_unexport (self);
+ return G_SOURCE_REMOVE;
+}
+
+void
+nm_dbus_object_unexport_on_idle (NMDBusObject *self_take)
+{
+ g_return_if_fail (NM_IS_DBUS_OBJECT (self_take));
+
+ g_return_if_fail (self_take->internal.path);
+
+ /* There is no mechanism to cancel or abort the unexport. It will always
+ * gonna happen.
+ *
+ * However, we register it to block shutdown, so that we ensure that it will happen. */
+
+ nm_shutdown_wait_obj_register_object (self_take, "unexport-dbus-obj-on-idle");
+
+ g_idle_add (_unexport_on_idle_cb,
+ g_steal_pointer (&self_take));
+}
+
/*****************************************************************************/
void
diff --git a/src/nm-dbus-object.h b/src/nm-dbus-object.h
index 8b36bce897..ab09465f6c 100644
--- a/src/nm-dbus-object.h
+++ b/src/nm-dbus-object.h
@@ -166,6 +166,8 @@ nm_dbus_object_get_path_still_exported (NMDBusObject *self)
const char *nm_dbus_object_export (NMDBusObject *self);
void nm_dbus_object_unexport (NMDBusObject *self);
+void nm_dbus_object_unexport_on_idle (NMDBusObject *self_take);
+
void _nm_dbus_object_clear_and_unexport (NMDBusObject **location);
#define nm_dbus_object_clear_and_unexport(location) _nm_dbus_object_clear_and_unexport ((NMDBusObject **) (location))
diff --git a/src/nm-ip-config.c b/src/nm-ip-config.c
new file mode 100644
index 0000000000..a7207a5f57
--- /dev/null
+++ b/src/nm-ip-config.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2005 - 2017 Red Hat, Inc.
+ * Copyright (C) 2006 - 2008 Novell, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-ip-config.h"
+
+#include "nm-l3cfg.h"
+
+/*****************************************************************************/
+
+NM_GOBJECT_PROPERTIES_DEFINE (NMIPConfig,
+ PROP_L3CFG,
+ PROP_IS_VPN,
+);
+
+typedef struct _NMIPConfigPrivate {
+ NML3Cfg *l3cfg;
+ bool is_vpn:1;
+} NMIPConfigPrivate;
+
+G_DEFINE_ABSTRACT_TYPE (NMIPConfig, nm_ip_config, NM_TYPE_DBUS_OBJECT)
+
+#define NM_IP_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMIPConfig, NM_IS_IP_CONFIG)
+
+/*****************************************************************************/
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NMIPConfig *self = NM_IP_CONFIG (object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (self);
+
+ (void) priv;
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NMIPConfig *self = NM_IP_CONFIG (object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (self);
+
+ switch (prop_id) {
+ case PROP_L3CFG:
+ /* construct-only */
+ priv->l3cfg = nm_g_object_ref (g_value_get_pointer (value));
+ nm_assert (!priv->l3cfg || NM_IS_L3CFG (priv->l3cfg));
+ break;
+ case PROP_IS_VPN:
+ /* construct-only */
+ priv->is_vpn = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/*****************************************************************************/
+
+static void
+nm_ip_config_init (NMIPConfig *self)
+{
+ NMIPConfigPrivate *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_IP_CONFIG, NMIPConfigPrivate);
+
+ self->_priv = priv;
+}
+
+NMIPConfig *
+nm_ip_config_new (int addr_family,
+ NML3Cfg *l3cfg,
+ gboolean is_vpn)
+{
+ nm_assert_addr_family (addr_family);
+ nm_assert (NM_L3CFG (l3cfg));
+
+ return g_object_new ( NM_IS_IPv4 (addr_family)
+ ? nm_ip4_config_get_type ()
+ : nm_ip6_config_get_type (),
+ NM_IP_CONFIG_L3CFG, l3cfg,
+ NM_IP_CONFIG_IS_VPN, is_vpn,
+ NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMIPConfig *self = NM_IP_CONFIG (object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (self);
+
+ nm_g_object_unref (priv->l3cfg);
+
+ G_OBJECT_CLASS (nm_ip_config_parent_class)->finalize (object);
+}
+
+static void
+nm_ip_config_class_init (NMIPConfigClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (NMIPConfigPrivate));
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->finalize = finalize;
+
+ obj_properties[PROP_L3CFG] =
+ g_param_spec_pointer (NM_IP_CONFIG_L3CFG, "", "",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_IS_VPN] =
+ g_param_spec_boolean (NM_IP_CONFIG_IS_VPN, "", "",
+ FALSE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+}
diff --git a/src/nm-ip-config.h b/src/nm-ip-config.h
new file mode 100644
index 0000000000..2b6e88534d
--- /dev/null
+++ b/src/nm-ip-config.h
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2008 - 2013 Red Hat, Inc.
+ */
+
+#ifndef __NM_IP_CONFIG_H__
+#define __NM_IP_CONFIG_H__
+
+#include "nm-dbus-object.h"
+
+/*****************************************************************************/
+
+#define NM_TYPE_IP_CONFIG (nm_ip_config_get_type ())
+#define NM_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP_CONFIG, NMIPConfig))
+#define NM_IP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP_CONFIG, NMIPConfigClass))
+#define NM_IS_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP_CONFIG))
+#define NM_IS_IP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP_CONFIG))
+#define NM_IP_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP_CONFIG, NMIPConfigClass))
+
+#define NM_IP_CONFIG_L3CFG "l3cfg"
+#define NM_IP_CONFIG_IS_VPN "is-vpn"
+
+struct _NMIPConfigPrivate;
+
+struct _NMIPConfig {
+ NMDBusObject parent;
+ struct _NMIPConfigPrivate *_priv;
+};
+
+typedef struct {
+ NMDBusObjectClass parent;
+ gboolean is_ipv4;
+ int addr_family;
+} NMIPConfigClass;
+
+GType nm_ip_config_get_type (void);
+GType nm_ip4_config_get_type (void);
+GType nm_ip6_config_get_type (void);
+
+NMIPConfig *nm_ip_config_new (int addr_family,
+ NML3Cfg *l3cfg,
+ gboolean is_vpn);
+
+#endif /* __NM_IP_CONFIG_H__ */
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index a31b24c84f..e71432c51f 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -307,15 +307,15 @@ typedef struct {
} NMIP4ConfigPrivate;
struct _NMIP4Config {
- NMDBusObject parent;
+ NMIPConfig parent;
NMIP4ConfigPrivate _priv;
};
struct _NMIP4ConfigClass {
- NMDBusObjectClass parent;
+ NMIPConfigClass parent;
};
-G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_DBUS_OBJECT)
+G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG)
#define NM_IP4_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP4Config, NM_IS_IP4_CONFIG)
@@ -497,15 +497,6 @@ _notify_routes (NMIP4Config *self)
/*****************************************************************************/
static int
-_addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
-{
- return nm_platform_ip4_address_pretty_sort_cmp (NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) a)),
- NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) b)));
-}
-
-/*****************************************************************************/
-
-static int
sort_captured_addresses (const CList *lst_a, const CList *lst_b, gconstpointer user_data)
{
const NMPlatformIP4Address *addr_a = NMP_OBJECT_CAST_IP4_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj);
@@ -2952,12 +2943,9 @@ get_property (GObject *object, guint prop_id,
{
NMIP4Config *self = NM_IP4_CONFIG (object);
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Route *route;
- GVariantBuilder builder_data, builder_legacy;
- guint i;
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
+ GVariantBuilder builder_data;
+ guint i;
switch (prop_id) {
case PROP_IFINDEX:
@@ -2967,145 +2955,39 @@ get_property (GObject *object, guint prop_id,
case PROP_ADDRESSES:
nm_assert (!!priv->address_data_variant == !!priv->addresses_variant);
- if (priv->address_data_variant)
- goto out_addresses_cached;
-
- g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
- g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("aau"));
-
- head_entry = nm_ip4_config_lookup_addresses (self);
- if (head_entry) {
- gs_free const NMPObject **addresses = NULL;
- guint naddr;
-
- addresses = (const NMPObject **) nm_dedup_multi_objs_to_array_head (head_entry, NULL, NULL, &naddr);
- nm_assert (addresses && naddr);
-
- g_qsort_with_data (addresses,
- naddr,
- sizeof (addresses[0]),
- _addresses_sort_cmp,
- NULL);
-
- /* Build address data variant */
- for (i = 0; i < naddr; i++) {
- GVariantBuilder addr_builder;
- const NMPlatformIP4Address *address = NMP_OBJECT_CAST_IP4_ADDRESS (addresses[i]);
-
- g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&addr_builder, "{sv}",
- "address",
- g_variant_new_string (_nm_utils_inet4_ntop (address->address, addr_str)));
- g_variant_builder_add (&addr_builder, "{sv}",
- "prefix",
- g_variant_new_uint32 (address->plen));
- if (address->peer_address != address->address) {
- g_variant_builder_add (&addr_builder, "{sv}",
- "peer",
- g_variant_new_string (_nm_utils_inet4_ntop (address->peer_address, addr_str)));
- }
-
- if (*address->label) {
- g_variant_builder_add (&addr_builder, "{sv}",
- NM_IP_ADDRESS_ATTRIBUTE_LABEL,
- g_variant_new_string (address->label));
- }
-
- g_variant_builder_add (&builder_data, "a{sv}", &addr_builder);
-
- {
- const guint32 dbus_addr[3] = {
- address->address,
- address->plen,
- ( i == 0
- && priv->best_default_route)
- ? NMP_OBJECT_CAST_IP4_ROUTE (priv->best_default_route)->gateway
- : (guint32) 0,
- };
-
- g_variant_builder_add (&builder_legacy, "@au",
- g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
- dbus_addr, 3, sizeof (guint32)));
- }
- }
+ if (!priv->address_data_variant) {
+ nm_utils_ip_addresses_to_dbus (AF_INET,
+ nm_ip4_config_lookup_addresses (self),
+ priv->best_default_route,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
+ &priv->address_data_variant,
+ &priv->addresses_variant);
+ g_variant_ref_sink (priv->address_data_variant);
+ g_variant_ref_sink (priv->addresses_variant);
}
- priv->address_data_variant = g_variant_ref_sink (g_variant_builder_end (&builder_data));
- priv->addresses_variant = g_variant_ref_sink (g_variant_builder_end (&builder_legacy));
-
-out_addresses_cached:
g_value_set_variant (value,
- prop_id == PROP_ADDRESS_DATA ?
- priv->address_data_variant :
- priv->addresses_variant);
+ prop_id == PROP_ADDRESS_DATA
+ ? priv->address_data_variant
+ : priv->addresses_variant);
break;
case PROP_ROUTE_DATA:
case PROP_ROUTES:
nm_assert (!!priv->route_data_variant == !!priv->routes_variant);
- if (priv->route_data_variant)
- goto out_routes_cached;
-
- g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
- g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("aau"));
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
- GVariantBuilder route_builder;
-
- nm_assert (_route_valid (route));
-
- if (route->type_coerced != nm_platform_route_type_coerce (RTN_UNICAST))
- continue;
-
- g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&route_builder, "{sv}",
- "dest",
- g_variant_new_string (_nm_utils_inet4_ntop (route->network, addr_str)));
- g_variant_builder_add (&route_builder, "{sv}",
- "prefix",
- g_variant_new_uint32 (route->plen));
- if (route->gateway) {
- g_variant_builder_add (&route_builder, "{sv}",
- "next-hop",
- g_variant_new_string (_nm_utils_inet4_ntop (route->gateway, addr_str)));
- }
- g_variant_builder_add (&route_builder, "{sv}",
- "metric",
- g_variant_new_uint32 (route->metric));
-
- if (!nm_platform_route_table_is_main (route->table_coerced)) {
- g_variant_builder_add (&route_builder, "{sv}",
- "table",
- g_variant_new_uint32 (nm_platform_route_table_uncoerce (route->table_coerced, TRUE)));
- }
-
- g_variant_builder_add (&builder_data, "a{sv}", &route_builder);
-
- /* legacy versions of nm_ip4_route_set_prefix() in libnm-util assert that the
- * plen is positive. Skip the default routes not to break older clients. */
- if ( nm_platform_route_table_is_main (route->table_coerced)
- && !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
- const guint32 dbus_route[4] = {
- route->network,
- route->plen,
- route->gateway,
- route->metric,
- };
-
- g_variant_builder_add (&builder_legacy, "@au",
- g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
- dbus_route, 4, sizeof (guint32)));
- }
+ if (!priv->route_data_variant) {
+ nm_utils_ip_routes_to_dbus (AF_INET,
+ nm_ip4_config_lookup_routes (self),
+ &priv->route_data_variant,
+ &priv->routes_variant);
+ g_variant_ref_sink (priv->route_data_variant);
+ g_variant_ref_sink (priv->routes_variant);
}
- priv->route_data_variant = g_variant_ref_sink (g_variant_builder_end (&builder_data));
- priv->routes_variant = g_variant_ref_sink (g_variant_builder_end (&builder_legacy));
-
-out_routes_cached:
g_value_set_variant (value,
- prop_id == PROP_ROUTE_DATA ?
- priv->route_data_variant :
- priv->routes_variant);
+ prop_id == PROP_ROUTE_DATA
+ ? priv->route_data_variant
+ : priv->routes_variant);
break;
case PROP_GATEWAY:
if (priv->best_default_route) {
@@ -3290,10 +3172,14 @@ static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
};
static void
-nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
+nm_ip4_config_class_init (NMIP4ConfigClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (config_class);
- NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (config_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
+ NMIPConfigClass *ip_config_class = NM_IP_CONFIG_CLASS (klass);
+
+ ip_config_class->is_ipv4 = TRUE;
+ ip_config_class->addr_family = AF_INET;
dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/IP4Config");
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_ip4_config);
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index 04a0cfa5fe..d876f69ce0 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -12,6 +12,7 @@
#include "nm-glib-aux/nm-dedup-multi.h"
#include "platform/nmp-object.h"
+#include "nm-ip-config.h"
/*****************************************************************************/
@@ -262,7 +263,7 @@ void nm_ip_config_dump (const NMIPConfig *self,
#include "nm-ip6-config.h"
static inline gboolean
-NM_IS_IP_CONFIG (gconstpointer config, int addr_family)
+NM_IS_IP_CONFIG_ADDR_FAMILY (gconstpointer config, int addr_family)
{
if (addr_family == AF_UNSPEC)
return NM_IS_IP4_CONFIG (config) || NM_IS_IP6_CONFIG (config);
@@ -307,7 +308,7 @@ NM_IS_IP_CONFIG (gconstpointer config, int addr_family)
NMIP6Config * : (NM_IS_IP6_CONFIG (_config))); \
})
#else
-#define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config, AF_UNSPEC)
+#define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config)
#endif
#define NM_IP_CONFIG_CAST(config) \
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index cf7aa59f0d..69b74c7298 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -67,15 +67,15 @@ typedef struct {
} NMIP6ConfigPrivate;
struct _NMIP6Config {
- NMDBusObject parent;
+ NMIPConfig parent;
NMIP6ConfigPrivate _priv;
};
struct _NMIP6ConfigClass {
- NMDBusObjectClass parent;
+ NMIPConfigClass parent;
};
-G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_DBUS_OBJECT)
+G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_IP_CONFIG)
#define NM_IP6_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP6Config, NM_IS_IP6_CONFIG)
@@ -213,14 +213,6 @@ _notify_routes (NMIP6Config *self)
/*****************************************************************************/
static int
-_addresses_sort_cmp_prop (gconstpointer a, gconstpointer b, gpointer user_data)
-{
- return nm_platform_ip6_address_pretty_sort_cmp (NMP_OBJECT_CAST_IP6_ADDRESS (*((const NMPObject **) a)),
- NMP_OBJECT_CAST_IP6_ADDRESS (*((const NMPObject **) b)),
- (((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT (user_data)) == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
-}
-
-static int
sort_captured_addresses (const CList *lst_a, const CList *lst_b, gconstpointer user_data)
{
return nm_platform_ip6_address_pretty_sort_cmp (NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj),
@@ -2475,11 +2467,6 @@ get_property (GObject *object, guint prop_id,
{
NMIP6Config *self = NM_IP6_CONFIG (object);
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Route *route;
- GVariantBuilder builder_data, builder_legacy;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
switch (prop_id) {
case PROP_IFINDEX:
@@ -2489,131 +2476,39 @@ get_property (GObject *object, guint prop_id,
case PROP_ADDRESSES:
nm_assert (!!priv->address_data_variant == !!priv->addresses_variant);
- if (priv->address_data_variant)
- goto out_addresses_cached;
-
- g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
- g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("a(ayuay)"));
-
- head_entry = nm_ip6_config_lookup_addresses (self);
- if (head_entry) {
- gs_free const NMPObject **addresses = NULL;
- guint naddr, i;
-
- addresses = (const NMPObject **) nm_dedup_multi_objs_to_array_head (head_entry, NULL, NULL, &naddr);
- nm_assert (addresses && naddr);
-
- g_qsort_with_data (addresses,
- naddr,
- sizeof (addresses[0]),
- _addresses_sort_cmp_prop,
- GINT_TO_POINTER (priv->privacy));
-
- for (i = 0; i < naddr; i++) {
- GVariantBuilder addr_builder;
- const NMPlatformIP6Address *address = NMP_OBJECT_CAST_IP6_ADDRESS (addresses[i]);
-
- g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&addr_builder, "{sv}",
- "address",
- g_variant_new_string (_nm_utils_inet6_ntop (&address->address, sbuf)));
- g_variant_builder_add (&addr_builder, "{sv}",
- "prefix",
- g_variant_new_uint32 (address->plen));
- if ( !IN6_IS_ADDR_UNSPECIFIED (&address->peer_address)
- && !IN6_ARE_ADDR_EQUAL (&address->peer_address, &address->address)) {
- g_variant_builder_add (&addr_builder, "{sv}",
- "peer",
- g_variant_new_string (_nm_utils_inet6_ntop (&address->peer_address, sbuf)));
- }
-
- g_variant_builder_add (&builder_data, "a{sv}", &addr_builder);
-
- g_variant_builder_add (&builder_legacy, "(@ayu@ay)",
- g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- &address->address, 16, 1),
- address->plen,
- g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- ( i == 0
- && priv->best_default_route)
- ? &NMP_OBJECT_CAST_IP6_ROUTE (priv->best_default_route)->gateway
- : &in6addr_any,
- 16, 1));
- }
+ if (!priv->address_data_variant) {
+ nm_utils_ip_addresses_to_dbus (AF_INET6,
+ nm_ip6_config_lookup_addresses (self),
+ priv->best_default_route,
+ priv->privacy,
+ &priv->address_data_variant,
+ &priv->addresses_variant);
+ g_variant_ref_sink (priv->address_data_variant);
+ g_variant_ref_sink (priv->addresses_variant);
}
-
- priv->address_data_variant = g_variant_ref_sink (g_variant_builder_end (&builder_data));
- priv->addresses_variant = g_variant_ref_sink (g_variant_builder_end (&builder_legacy));
-out_addresses_cached:
g_value_set_variant (value,
- prop_id == PROP_ADDRESS_DATA ?
- priv->address_data_variant :
- priv->addresses_variant);
+ prop_id == PROP_ADDRESS_DATA
+ ? priv->address_data_variant
+ : priv->addresses_variant);
break;
case PROP_ROUTE_DATA:
case PROP_ROUTES:
nm_assert (!!priv->route_data_variant == !!priv->routes_variant);
- if (priv->route_data_variant)
- goto out_routes_cached;
-
- g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
- g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("a(ayuayu)"));
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, &route) {
- GVariantBuilder route_builder;
-
- nm_assert (_route_valid (route));
-
- if (route->type_coerced != nm_platform_route_type_coerce (RTN_UNICAST))
- continue;
-
- g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&route_builder, "{sv}",
- "dest",
- g_variant_new_string (_nm_utils_inet6_ntop (&route->network, sbuf)));
- g_variant_builder_add (&route_builder, "{sv}",
- "prefix",
- g_variant_new_uint32 (route->plen));
- if (!IN6_IS_ADDR_UNSPECIFIED (&route->gateway)) {
- g_variant_builder_add (&route_builder, "{sv}",
- "next-hop",
- g_variant_new_string (_nm_utils_inet6_ntop (&route->gateway, sbuf)));
- }
-
- g_variant_builder_add (&route_builder, "{sv}",
- "metric",
- g_variant_new_uint32 (route->metric));
-
- if (!nm_platform_route_table_is_main (route->table_coerced)) {
- g_variant_builder_add (&route_builder, "{sv}",
- "table",
- g_variant_new_uint32 (nm_platform_route_table_uncoerce (route->table_coerced, TRUE)));
- }
-
- g_variant_builder_add (&builder_data, "a{sv}", &route_builder);
-
- /* legacy versions of nm_ip6_route_set_prefix() in libnm-util assert that the
- * plen is positive. Skip the default routes not to break older clients. */
- if ( nm_platform_route_table_is_main (route->table_coerced)
- && !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
- g_variant_builder_add (&builder_legacy, "(@ayu@ayu)",
- g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- &route->network, 16, 1),
- (guint32) route->plen,
- g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- &route->gateway, 16, 1),
- (guint32) route->metric);
- }
+ if (!priv->route_data_variant) {
+ nm_utils_ip_routes_to_dbus (AF_INET6,
+ nm_ip6_config_lookup_routes (self),
+ &priv->route_data_variant,
+ &priv->routes_variant);
+ g_variant_ref_sink (priv->route_data_variant);
+ g_variant_ref_sink (priv->routes_variant);
}
- priv->route_data_variant = g_variant_ref_sink (g_variant_builder_end (&builder_data));
- priv->routes_variant = g_variant_ref_sink (g_variant_builder_end (&builder_legacy));
-out_routes_cached:
+
g_value_set_variant (value,
- prop_id == PROP_ROUTE_DATA ?
- priv->route_data_variant :
- priv->routes_variant);
+ prop_id == PROP_ROUTE_DATA
+ ? priv->route_data_variant
+ : priv->routes_variant);
break;
case PROP_GATEWAY:
if (priv->best_default_route) {
@@ -2760,10 +2655,14 @@ static const NMDBusInterfaceInfoExtended interface_info_ip6_config = {
};
static void
-nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
+nm_ip6_config_class_init (NMIP6ConfigClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (config_class);
- NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (config_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
+ NMIPConfigClass *ip_config_class = NM_IP_CONFIG_CLASS (klass);
+
+ ip_config_class->is_ipv4 = FALSE;
+ ip_config_class->addr_family = AF_INET6;
dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/IP6Config");
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_ip6_config);
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index 079005e477..187da967a9 100644
--- a/src/nm-ip6-config.h
+++ b/src/nm-ip6-config.h
@@ -12,6 +12,7 @@
#include "nm-glib-aux/nm-dedup-multi.h"
#include "platform/nmp-object.h"
+#include "nm-ip-config.h"
/*****************************************************************************/
diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c
index f384ae2343..412c5aa3a6 100644
--- a/src/nm-l3-config-data.c
+++ b/src/nm-l3-config-data.c
@@ -109,6 +109,8 @@ struct _NML3ConfigData {
NML3ConfigDatFlags flags;
+ NMIPConfigSource source;
+
guint32 mtu;
NMTernary metered:3;
@@ -217,6 +219,20 @@ _garray_inaddr_find (GArray *arr,
return -1;
}
+static gconstpointer
+_garray_inaddr_get (GArray *arr,
+ guint *out_len)
+{
+ nm_assert (out_len);
+
+ if (!arr) {
+ *out_len = 0;
+ return NULL;
+ }
+ *out_len = arr->len;
+ return arr->data;
+}
+
static gboolean
_garray_inaddr_add (GArray **p_arr,
int addr_family,
@@ -376,6 +392,7 @@ nm_l3_config_data_new (NMDedupMultiIndex *multi_idx,
.metered = NM_TERNARY_DEFAULT,
.route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
.route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
+ .source = NM_IP_CONFIG_SOURCE_UNKNOWN,
};
_idx_type_init (&self->idx_addresses_4, NMP_OBJECT_TYPE_IP4_ADDRESS);
@@ -543,8 +560,7 @@ nm_l3_config_data_lookup_index (const NML3ConfigData *self, NMPObjectType obj_ty
case NMP_OBJECT_TYPE_IP6_ROUTE:
return &self->idx_routes_6.parent;
default:
- nm_assert_not_reached ();
- return NULL;
+ return nm_assert_unreachable_val (NULL);
}
}
@@ -572,6 +588,30 @@ nm_l3_config_data_lookup_obj (const NML3ConfigData *self,
obj);
}
+const NMPObject *
+nmtst_l3_config_data_get_obj_at (const NML3ConfigData *self,
+ NMPObjectType obj_type,
+ guint i)
+{
+ NMDedupMultiIter iter;
+ guint j;
+
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
+
+ j = 0;
+ nm_dedup_multi_iter_init (&iter,
+ nm_l3_config_data_lookup_objs (self, obj_type));
+ while (nm_dedup_multi_iter_next (&iter)) {
+ nm_assert (iter.current);
+ nm_assert (NMP_OBJECT_GET_TYPE (iter.current->obj) == obj_type);
+ if (i == j)
+ return iter.current->obj;
+ j++;
+ }
+
+ g_return_val_if_reached (NULL);
+}
+
/*****************************************************************************/
NMDedupMultiIndex *
@@ -889,6 +929,16 @@ nm_l3_config_data_add_route_full (NML3ConfigData *self,
return changed;
}
+const NMPObject *
+nm_l3_config_data_get_best_default_route (const NML3ConfigData *self,
+ int addr_family)
+{
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
+ nm_assert_addr_family (addr_family);
+
+ return self->best_default_route_x[NM_IS_IPv4 (addr_family)];
+}
+
/*****************************************************************************/
static gboolean
@@ -921,6 +971,18 @@ _check_and_add_domain (GPtrArray **p_arr, const char *domain)
return TRUE;
}
+gconstpointer
+nm_l3_config_data_get_nameservers (const NML3ConfigData *self,
+ int addr_family,
+ guint *out_len)
+{
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
+ nm_assert_addr_family (addr_family);
+ nm_assert (out_len);
+
+ return _garray_inaddr_get (self->nameservers_x[NM_IS_IPv4 (addr_family)], out_len);
+}
+
gboolean
nm_l3_config_data_add_nameserver (NML3ConfigData *self,
int addr_family,
@@ -935,6 +997,15 @@ nm_l3_config_data_add_nameserver (NML3ConfigData *self,
nameserver);
}
+const in_addr_t *
+nm_l3_config_data_get_wins (const NML3ConfigData *self,
+ guint *out_len)
+{
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
+
+ return _garray_inaddr_get (self->wins, out_len);
+}
+
gboolean
nm_l3_config_data_add_wins (NML3ConfigData *self,
in_addr_t wins)
@@ -977,6 +1048,18 @@ nm_l3_config_data_add_domain (NML3ConfigData *self,
return _check_and_add_domain (&self->domains_x[NM_IS_IPv4 (addr_family)], domain);
}
+const char *const*
+nm_l3_config_data_get_searches (const NML3ConfigData *self,
+ int addr_family,
+ guint *out_len)
+{
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
+ nm_assert_addr_family (addr_family);
+ nm_assert (out_len);
+
+ return nm_strv_ptrarray_get_unsafe (self->searches_x[NM_IS_IPv4 (addr_family)], out_len);
+}
+
gboolean
nm_l3_config_data_add_search (NML3ConfigData *self,
int addr_family,
@@ -1086,6 +1169,14 @@ nm_l3_config_data_set_route_table_sync (NML3ConfigData *self,
return TRUE;
}
+NMTernary
+nm_l3_config_data_get_metered (const NML3ConfigData *self)
+{
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
+
+ return self->metered;
+}
+
gboolean
nm_l3_config_data_set_metered (NML3ConfigData *self,
NMTernary metered)
@@ -1099,18 +1190,37 @@ nm_l3_config_data_set_metered (NML3ConfigData *self,
return TRUE;
}
+guint32
+nm_l3_config_data_get_mtu (const NML3ConfigData *self)
+{
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
+
+ return self->mtu;
+}
+
gboolean
nm_l3_config_data_set_mtu (NML3ConfigData *self,
guint32 mtu)
{
nm_assert (_NM_IS_L3_CONFIG_DATA (self, FALSE));
- if ( self->mtu == mtu
- && NM_FLAGS_HAS (self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_MTU))
+ if (self->mtu == mtu)
return FALSE;
self->mtu = mtu;
- self->flags |= NM_L3_CONFIG_DAT_FLAGS_HAS_MTU;
+ return TRUE;
+}
+
+gboolean
+nm_l3_config_data_set_source (NML3ConfigData *self,
+ NMIPConfigSource source)
+{
+ nm_assert (_NM_IS_L3_CONFIG_DATA (self, FALSE));
+
+ if (self->source == source)
+ return FALSE;
+
+ self->source = source;
return TRUE;
}
@@ -1193,10 +1303,11 @@ nm_l3_config_data_cmp (const NML3ConfigData *a, const NML3ConfigData *b)
NM_CMP_FIELD_STR0 (a, b, nis_domain);
NM_CMP_DIRECT (a->mdns, b->mdns);
NM_CMP_DIRECT (a->llmnr, b->llmnr);
- if (NM_FLAGS_HAS (a->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_MTU))
- NM_CMP_DIRECT (a->mtu, b->mtu);
+ NM_CMP_DIRECT (a->mtu, b->mtu);
NM_CMP_DIRECT_UNSAFE (a->metered, b->metered);
+ NM_CMP_FIELD (a, b, source);
+
/* these fields are not considered by cmp():
*
* - multi_idx
@@ -1668,15 +1779,17 @@ NML3ConfigData *
nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_idx,
int ifindex,
NMConnection *connection,
- guint32 route_table,
- guint32 route_metric)
+ guint32 route_table_4,
+ guint32 route_table_6,
+ guint32 route_metric_4,
+ guint32 route_metric_6)
{
NML3ConfigData *self;
self = nm_l3_config_data_new (multi_idx, ifindex);
- _init_from_connection_ip (self, AF_INET, connection, route_table, route_metric);
- _init_from_connection_ip (self, AF_INET6, connection, route_table, route_metric);
+ _init_from_connection_ip (self, AF_INET, connection, route_table_4, route_metric_4);
+ _init_from_connection_ip (self, AF_INET6, connection, route_table_6, route_metric_6);
return self;
}
@@ -1781,11 +1894,13 @@ nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_idx,
/*****************************************************************************/
-static void
-_init_merge (NML3ConfigData *self,
- const NML3ConfigData *src,
- NML3ConfigMergeFlags merge_flags,
- const guint32 *default_route_penalty_x /* length 2, for IS_IPv4 */)
+void
+nm_l3_config_data_merge (NML3ConfigData *self,
+ const NML3ConfigData *src,
+ NML3ConfigMergeFlags merge_flags,
+ const guint32 *default_route_penalty_x /* length 2, for IS_IPv4 */,
+ NML3ConfigMergeHookAddObj hook_add_addr,
+ gpointer hook_user_data)
{
NMDedupMultiIter iter;
const NMPObject *obj;
@@ -1802,6 +1917,11 @@ _init_merge (NML3ConfigData *self,
src,
obj,
NMP_OBJECT_TYPE_IP_ADDRESS (IS_IPv4)) {
+
+ if ( hook_add_addr
+ && !hook_add_addr (src, obj, hook_user_data))
+ continue;
+
if ( NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_EXTERNAL)
&& !NMP_OBJECT_CAST_IP_ADDRESS (obj)->external) {
NMPlatformIPXAddress a;
@@ -1909,11 +2029,10 @@ _init_merge (NML3ConfigData *self,
if (self->metered == NM_TERNARY_DEFAULT)
self->metered = src->metered;
- if ( !NM_FLAGS_HAS (self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_MTU)
- && NM_FLAGS_HAS (src->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_MTU)) {
+ if (self->mtu != 0u)
self->mtu = src->mtu;
- self->flags |= NM_L3_CONFIG_DAT_FLAGS_HAS_MTU;
- }
+
+ /* self->source does not get merged. */
}
NML3ConfigData *
@@ -1931,30 +2050,6 @@ nm_l3_config_data_new_clone (const NML3ConfigData *src,
ifindex = src->ifindex;
self = nm_l3_config_data_new (src->multi_idx, ifindex);
- _init_merge (self, src, NM_L3_CONFIG_MERGE_FLAGS_NONE, NULL);
- return self;
-}
-
-NML3ConfigData *
-nm_l3_config_data_new_combined (NMDedupMultiIndex *multi_idx,
- int ifindex,
- const NML3ConfigDatMergeInfo *const*merge_infos,
- guint merge_infos_len)
-{
- NML3ConfigData *self;
- guint i;
-
- nm_assert (multi_idx);
- nm_assert (ifindex > 0);
-
- self = nm_l3_config_data_new (multi_idx, ifindex);
-
- for (i = 0; i < merge_infos_len; i++) {
- _init_merge (self,
- merge_infos[i]->l3cfg,
- merge_infos[i]->merge_flags,
- merge_infos[i]->default_route_penalty_x);
- }
-
+ nm_l3_config_data_merge (self, src, NM_L3_CONFIG_MERGE_FLAGS_NONE, NULL, NULL, NULL);
return self;
}
diff --git a/src/nm-l3-config-data.h b/src/nm-l3-config-data.h
index 59fbffce66..fde82b99a1 100644
--- a/src/nm-l3-config-data.h
+++ b/src/nm-l3-config-data.h
@@ -7,6 +7,7 @@
#include "nm-setting-connection.h"
#include "nm-setting-ip6-config.h"
#include "platform/nm-platform.h"
+#include "platform/nmp-object.h"
typedef enum {
NM_L3_CONFIG_DAT_FLAGS_NONE = 0,
@@ -20,7 +21,6 @@ typedef enum {
#define NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY(is_ipv4) ( (is_ipv4) \
? NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_4 \
: NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_6)
- NM_L3_CONFIG_DAT_FLAGS_HAS_MTU = (1ull << 3),
} NML3ConfigDatFlags;
@@ -63,20 +63,6 @@ typedef enum {
/*****************************************************************************/
-typedef struct _NML3ConfigData NML3ConfigData;
-
-typedef struct {
- const NML3ConfigData *l3cfg;
- NML3ConfigMergeFlags merge_flags;
- union {
- struct {
- guint32 default_route_penalty_6;
- guint32 default_route_penalty_4;
- };
- guint32 default_route_penalty_x[2];
- };
-} NML3ConfigDatMergeInfo;
-
NML3ConfigData *nm_l3_config_data_new (NMDedupMultiIndex *multi_idx,
int ifindex);
const NML3ConfigData *nm_l3_config_data_ref (const NML3ConfigData *self);
@@ -84,11 +70,11 @@ const NML3ConfigData *nm_l3_config_data_ref_and_seal (const NML3ConfigData *self
const NML3ConfigData *nm_l3_config_data_seal (const NML3ConfigData *self);
void nm_l3_config_data_unref (const NML3ConfigData *self);
-NM_AUTO_DEFINE_FCN0 (const NML3ConfigData *, _nm_auto_unref_l3cfg, nm_l3_config_data_unref);
-#define nm_auto_unref_l3cfg nm_auto (_nm_auto_unref_l3cfg)
+NM_AUTO_DEFINE_FCN0 (const NML3ConfigData *, _nm_auto_unref_l3cd, nm_l3_config_data_unref);
+#define nm_auto_unref_l3cd nm_auto (_nm_auto_unref_l3cd)
-NM_AUTO_DEFINE_FCN0 (NML3ConfigData *, _nm_auto_unref_l3cfg_init, nm_l3_config_data_unref);
-#define nm_auto_unref_l3cfg_init nm_auto (_nm_auto_unref_l3cfg_init)
+NM_AUTO_DEFINE_FCN0 (NML3ConfigData *, _nm_auto_unref_l3cd_init, nm_l3_config_data_unref);
+#define nm_auto_unref_l3cd_init nm_auto (_nm_auto_unref_l3cd_init)
gboolean nm_l3_config_data_is_sealed (const NML3ConfigData *self);
@@ -98,18 +84,26 @@ NML3ConfigData *nm_l3_config_data_new_clone (const NML3ConfigData *src,
NML3ConfigData *nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_idx,
int ifindex,
NMConnection *connection,
- guint32 route_table,
- guint32 route_metric);
+ guint32 route_table_4,
+ guint32 route_table_6,
+ guint32 route_metric_4,
+ guint32 route_metric_6);
NML3ConfigData *nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_idx,
int ifindex,
NMPlatform *platform,
NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941);
-NML3ConfigData *nm_l3_config_data_new_combined (NMDedupMultiIndex *multi_idx,
- int ifindex,
- const NML3ConfigDatMergeInfo *const*merge_infos,
- guint merge_infos_len);
+typedef gboolean (*NML3ConfigMergeHookAddObj) (const NML3ConfigData *l3cd,
+ const NMPObject *obj,
+ gpointer user_data);
+
+void nm_l3_config_data_merge (NML3ConfigData *self,
+ const NML3ConfigData *src,
+ NML3ConfigMergeFlags merge_flags,
+ const guint32 *default_route_penalty_x /* length 2, for IS_IPv4 */,
+ NML3ConfigMergeHookAddObj hook_add_addr,
+ gpointer hook_user_data);
void nm_l3_config_data_add_dependent_routes (NML3ConfigData *self,
int addr_family,
@@ -211,6 +205,73 @@ nm_l3_config_data_lookup_routes (const NML3ConfigData *self, int addr_family)
nm_platform_dedup_multi_iter_next_ip6_route (&(iter), &(route)); \
)
+static inline guint
+nm_l3_config_data_get_num_objs (const NML3ConfigData *self, NMPObjectType obj_type)
+{
+ const NMDedupMultiHeadEntry *head_entry;
+
+ head_entry = nm_l3_config_data_lookup_objs (self, obj_type);
+ return head_entry ? head_entry->len : 0u;
+}
+
+static inline guint
+nm_l3_config_data_get_num_addresses (const NML3ConfigData *self, int addr_family)
+{
+ return nm_l3_config_data_get_num_objs (self,
+ NM_IS_IPv4 (addr_family)
+ ? NMP_OBJECT_TYPE_IP4_ADDRESS
+ : NMP_OBJECT_TYPE_IP6_ADDRESS);
+}
+
+static inline guint
+nm_l3_config_data_get_num_routes (const NML3ConfigData *self, int addr_family)
+{
+ return nm_l3_config_data_get_num_objs (self,
+ NM_IS_IPv4 (addr_family)
+ ? NMP_OBJECT_TYPE_IP4_ROUTE
+ : NMP_OBJECT_TYPE_IP6_ROUTE);
+}
+
+const NMPObject *nmtst_l3_config_data_get_obj_at (const NML3ConfigData *self,
+ NMPObjectType obj_type,
+ guint i);
+
+static inline const NMPlatformIP4Address *
+nmtst_l3_config_data_get_address_at_4 (const NML3ConfigData *self,
+ guint i)
+{
+ return NMP_OBJECT_CAST_IP4_ADDRESS (nmtst_l3_config_data_get_obj_at (self,
+ NMP_OBJECT_TYPE_IP4_ADDRESS,
+ i));
+}
+
+static inline const NMPlatformIP6Address *
+nmtst_l3_config_data_get_address_at_6 (const NML3ConfigData *self,
+ guint i)
+{
+ return NMP_OBJECT_CAST_IP6_ADDRESS (nmtst_l3_config_data_get_obj_at (self,
+ NMP_OBJECT_TYPE_IP6_ADDRESS,
+ i));
+}
+
+static inline const NMPlatformIP4Route *
+nmtst_l3_config_data_get_route_at_4 (const NML3ConfigData *self,
+ guint i)
+{
+ return NMP_OBJECT_CAST_IP4_ROUTE (nmtst_l3_config_data_get_obj_at (self,
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ i));
+}
+
+static inline const NMPlatformIP6Route *
+nmtst_l3_config_data_get_route_at_6 (const NML3ConfigData *self,
+ guint i)
+{
+ return NMP_OBJECT_CAST_IP6_ROUTE (nmtst_l3_config_data_get_obj_at (self,
+ NMP_OBJECT_TYPE_IP6_ROUTE,
+ i));
+}
+
/*****************************************************************************/
NML3ConfigDatFlags nm_l3_config_data_get_flags (const NML3ConfigData *self);
@@ -235,6 +296,9 @@ nm_l3_config_data_unset_flags (NML3ConfigData *self,
/*****************************************************************************/
+gboolean nm_l3_config_data_set_source (NML3ConfigData *self,
+ NMIPConfigSource source);
+
gboolean nm_l3_config_data_add_address_full (NML3ConfigData *self,
int addr_family,
const NMPObject *obj_new,
@@ -303,6 +367,9 @@ nm_l3_config_data_add_route_6 (NML3ConfigData *self, const NMPlatformIP6Route *r
return nm_l3_config_data_add_route (self, AF_INET6, NULL, NM_PLATFORM_IP_ROUTE_CAST (rt));
}
+const NMPObject *nm_l3_config_data_get_best_default_route (const NML3ConfigData *self,
+ int addr_family);
+
gboolean nm_l3_config_data_set_mdns (NML3ConfigData *self,
NMSettingConnectionMdns mdns);
@@ -316,19 +383,30 @@ gboolean nm_l3_config_data_set_route_table_sync (NML3ConfigData *self,
int addr_family,
NMIPRouteTableSyncMode route_table_sync);
+NMTernary nm_l3_config_data_get_metered (const NML3ConfigData *self);
+
gboolean nm_l3_config_data_set_metered (NML3ConfigData *self,
NMTernary metered);
+guint32 nm_l3_config_data_get_mtu (const NML3ConfigData *self);
+
gboolean nm_l3_config_data_set_mtu (NML3ConfigData *self,
guint32 mtu);
-gboolean nm_l3_config_data_add_nameserver (NML3ConfigData *self,
- int addr_family,
- gconstpointer /* (const NMIPAddr *) */ nameserver);
+const in_addr_t *nm_l3_config_data_get_wins (const NML3ConfigData *self,
+ guint *out_len);
gboolean nm_l3_config_data_add_wins (NML3ConfigData *self,
in_addr_t wins);
+gconstpointer nm_l3_config_data_get_nameservers (const NML3ConfigData *self,
+ int addr_family,
+ guint *out_len);
+
+gboolean nm_l3_config_data_add_nameserver (NML3ConfigData *self,
+ int addr_family,
+ gconstpointer /* (const NMIPAddr *) */ nameserver);
+
gboolean nm_l3_config_data_add_nis_server (NML3ConfigData *self,
in_addr_t nis_server);
@@ -339,6 +417,10 @@ gboolean nm_l3_config_data_add_domain (NML3ConfigData *self,
int addr_family,
const char *domain);
+const char *const*nm_l3_config_data_get_searches (const NML3ConfigData *self,
+ int addr_family,
+ guint *out_len);
+
gboolean nm_l3_config_data_add_search (NML3ConfigData *self,
int addr_family,
const char *search);
@@ -351,4 +433,17 @@ gboolean nm_l3_config_data_set_dns_priority (NML3ConfigData *self,
int addr_family,
int dns_priority);
+static inline const NMIPAddr *
+nmtst_l3_config_data_get_best_gateway (const NML3ConfigData *self,
+ int addr_family)
+{
+ const NMPObject *rt;
+
+ rt = nm_l3_config_data_get_best_default_route (self, addr_family);
+ if (!rt)
+ return NULL;
+
+ return nm_platform_ip_route_get_gateway (addr_family, NMP_OBJECT_CAST_IP_ROUTE (rt));
+}
+
#endif /* __NM_L3_CONFIG_DATA_H__ */
diff --git a/src/nm-l3cfg.c b/src/nm-l3cfg.c
index 5e0890ded2..b26f7bab8c 100644
--- a/src/nm-l3cfg.c
+++ b/src/nm-l3cfg.c
@@ -11,7 +11,15 @@
/*****************************************************************************/
typedef struct {
- NML3ConfigDatMergeInfo merge_info;
+ const NML3ConfigData *l3cd;
+ NML3ConfigMergeFlags merge_flags;
+ union {
+ struct {
+ guint32 default_route_penalty_6;
+ guint32 default_route_penalty_4;
+ };
+ guint32 default_route_penalty_x[2];
+ };
gconstpointer tag;
guint64 pseudo_timestamp;
int priority;
@@ -37,7 +45,7 @@ static GQuark signal_notify_quarks[_NM_L3_CONFIG_NOTIFY_TYPE_NUM];
typedef struct _NML3CfgPrivate {
GArray *property_emit_list;
GArray *l3_config_datas;
- const NML3ConfigData *combined_l3cfg;
+ const NML3ConfigData *combined_l3cd;
GHashTable *routes_temporary_not_available_hash;
@@ -191,14 +199,14 @@ _l3cfg_externally_removed_objs_drop_unused (NML3Cfg *self)
if (!self->priv.p->externally_removed_objs_hash)
return;
- if (!self->priv.p->combined_l3cfg) {
+ if (!self->priv.p->combined_l3cd) {
_l3cfg_externally_removed_objs_drop (self, AF_UNSPEC);
return;
}
g_hash_table_iter_init (&h_iter, self->priv.p->externally_removed_objs_hash);
while (g_hash_table_iter_next (&h_iter, (gpointer *) &obj, NULL)) {
- if (!nm_l3_config_data_lookup_route_obj (self->priv.p->combined_l3cfg,
+ if (!nm_l3_config_data_lookup_route_obj (self->priv.p->combined_l3cd,
obj)) {
/* The object is no longer tracked in the configuration.
* The externally_removed_objs_hash is to prevent adding entires that were
@@ -221,7 +229,7 @@ _l3cfg_externally_removed_objs_track (NML3Cfg *self,
nm_assert (NM_IS_L3CFG (self));
- if (!self->priv.p->combined_l3cfg)
+ if (!self->priv.p->combined_l3cd)
return;
if (!is_removed) {
@@ -238,7 +246,7 @@ _l3cfg_externally_removed_objs_track (NML3Cfg *self,
return;
}
- if (!nm_l3_config_data_lookup_route_obj (self->priv.p->combined_l3cfg,
+ if (!nm_l3_config_data_lookup_route_obj (self->priv.p->combined_l3cd,
obj)) {
/* we don't care about this object, so there is nothing to hide hide */
return;
@@ -268,16 +276,16 @@ _l3cfg_externally_removed_objs_pickup (NML3Cfg *self,
NMDedupMultiIter iter;
const NMPObject *obj;
- if (!self->priv.p->combined_l3cfg)
+ if (!self->priv.p->combined_l3cd)
return;
- nm_l3_config_data_iter_obj_for_each (iter, self->priv.p->combined_l3cfg, obj, NMP_OBJECT_TYPE_IP_ADDRESS (IS_IPv4)) {
+ nm_l3_config_data_iter_obj_for_each (iter, self->priv.p->combined_l3cd, obj, NMP_OBJECT_TYPE_IP_ADDRESS (IS_IPv4)) {
if (!nm_platform_lookup_entry (self->priv.platform,
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
obj))
_l3cfg_externally_removed_objs_track (self, obj, TRUE);
}
- nm_l3_config_data_iter_obj_for_each (iter, self->priv.p->combined_l3cfg, obj, NMP_OBJECT_TYPE_IP_ROUTE (IS_IPv4)) {
+ nm_l3_config_data_iter_obj_for_each (iter, self->priv.p->combined_l3cd, obj, NMP_OBJECT_TYPE_IP_ROUTE (IS_IPv4)) {
if (!nm_platform_lookup_entry (self->priv.platform,
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
obj))
@@ -514,7 +522,7 @@ static gssize
_l3_config_datas_find_next (GArray *l3_config_datas,
guint start_idx,
gconstpointer needle_tag,
- const NML3ConfigData *needle_l3cfg)
+ const NML3ConfigData *needle_l3cd)
{
guint i;
@@ -525,7 +533,7 @@ _l3_config_datas_find_next (GArray *l3_config_datas,
const L3ConfigData *l3_config_data = _l3_config_datas_at (l3_config_datas, i);
if ( NM_IN_SET (needle_tag, NULL, l3_config_data->tag)
- && NM_IN_SET (needle_l3cfg, NULL, l3_config_data->merge_info.l3cfg))
+ && NM_IN_SET (needle_l3cd, NULL, l3_config_data->l3cd))
return i;
}
return -1;
@@ -542,7 +550,7 @@ _l3_config_datas_remove_index_fast (GArray *arr,
l3_config_data = _l3_config_datas_at (arr, idx);
- nm_l3_config_data_unref (l3_config_data->merge_info.l3cfg);
+ nm_l3_config_data_unref (l3_config_data->l3cd);
g_array_remove_index_fast (arr, idx);
}
@@ -580,7 +588,7 @@ void
nm_l3cfg_add_config (NML3Cfg *self,
gconstpointer tag,
gboolean replace_same_tag,
- const NML3ConfigData *l3cfg,
+ const NML3ConfigData *l3cd,
int priority,
guint32 default_route_penalty_4,
guint32 default_route_penalty_6,
@@ -593,15 +601,15 @@ nm_l3cfg_add_config (NML3Cfg *self,
nm_assert (NM_IS_L3CFG (self));
nm_assert (tag);
- nm_assert (l3cfg);
- nm_assert (nm_l3_config_data_get_ifindex (l3cfg) == self->priv.ifindex);
+ nm_assert (l3cd);
+ nm_assert (nm_l3_config_data_get_ifindex (l3cd) == self->priv.ifindex);
l3_config_datas = _l3_config_datas_ensure (&self->priv.p->l3_config_datas);
idx = _l3_config_datas_find_next (l3_config_datas,
0,
tag,
- replace_same_tag ? NULL : l3cfg);
+ replace_same_tag ? NULL : l3cd);
if (replace_same_tag) {
gssize idx2;
@@ -611,7 +619,7 @@ nm_l3cfg_add_config (NML3Cfg *self,
while (TRUE) {
l3_config_data = _l3_config_datas_at (l3_config_datas, idx2);
- if (l3_config_data->merge_info.l3cfg == l3cfg) {
+ if (l3_config_data->l3cd == l3cd) {
nm_assert (idx == -1);
idx = idx2;
continue;
@@ -629,35 +637,35 @@ nm_l3cfg_add_config (NML3Cfg *self,
if (idx < 0) {
l3_config_data = nm_g_array_append_new (l3_config_datas, L3ConfigData);
*l3_config_data = (L3ConfigData) {
- .tag = tag,
- .merge_info.l3cfg = nm_l3_config_data_ref_and_seal (l3cfg),
- .merge_info.merge_flags = merge_flags,
- .merge_info.default_route_penalty_4 = default_route_penalty_4,
- .merge_info.default_route_penalty_6 = default_route_penalty_6,
- .priority = priority,
- .pseudo_timestamp = ++self->priv.p->pseudo_timestamp_counter,
- .dirty = FALSE,
+ .tag = tag,
+ .l3cd = nm_l3_config_data_ref_and_seal (l3cd),
+ .merge_flags = merge_flags,
+ .default_route_penalty_4 = default_route_penalty_4,
+ .default_route_penalty_6 = default_route_penalty_6,
+ .priority = priority,
+ .pseudo_timestamp = ++self->priv.p->pseudo_timestamp_counter,
+ .dirty = FALSE,
};
changed = TRUE;
} else {
l3_config_data = _l3_config_datas_at (l3_config_datas, idx);
l3_config_data->dirty = FALSE;
nm_assert (l3_config_data->tag == tag);
- nm_assert (l3_config_data->merge_info.l3cfg == l3cfg);
+ nm_assert (l3_config_data->l3cd == l3cd);
if (l3_config_data->priority != priority) {
l3_config_data->priority = priority;
changed = TRUE;
}
- if (l3_config_data->merge_info.merge_flags != merge_flags) {
- l3_config_data->merge_info.merge_flags = merge_flags;
+ if (l3_config_data->merge_flags != merge_flags) {
+ l3_config_data->merge_flags = merge_flags;
changed = TRUE;
}
- if (l3_config_data->merge_info.default_route_penalty_4 != default_route_penalty_4) {
- l3_config_data->merge_info.default_route_penalty_4 = default_route_penalty_4;
+ if (l3_config_data->default_route_penalty_4 != default_route_penalty_4) {
+ l3_config_data->default_route_penalty_4 = default_route_penalty_4;
changed = TRUE;
}
- if (l3_config_data->merge_info.default_route_penalty_6 != default_route_penalty_6) {
- l3_config_data->merge_info.default_route_penalty_6 = default_route_penalty_6;
+ if (l3_config_data->default_route_penalty_6 != default_route_penalty_6) {
+ l3_config_data->default_route_penalty_6 = default_route_penalty_6;
changed = TRUE;
}
}
@@ -670,7 +678,7 @@ static void
_l3cfg_remove_config (NML3Cfg *self,
gconstpointer tag,
gboolean only_dirty,
- const NML3ConfigData *l3cfg)
+ const NML3ConfigData *l3cd)
{
GArray *l3_config_datas;
gssize idx;
@@ -687,7 +695,7 @@ _l3cfg_remove_config (NML3Cfg *self,
idx = _l3_config_datas_find_next (l3_config_datas,
idx,
tag,
- l3cfg);
+ l3cd);
if (idx < 0)
return;
@@ -699,7 +707,7 @@ _l3cfg_remove_config (NML3Cfg *self,
self->priv.changed_configs = TRUE;
_l3_config_datas_remove_index_fast (l3_config_datas, idx);
- if (!l3cfg)
+ if (!l3cd)
return;
}
}
@@ -734,7 +742,7 @@ _l3_config_combine_sort_fcn (gconstpointer p_a,
nm_assert (a);
nm_assert (b);
- nm_assert (nm_l3_config_data_get_ifindex (a->merge_info.l3cfg) == nm_l3_config_data_get_ifindex (b->merge_info.l3cfg));
+ nm_assert (nm_l3_config_data_get_ifindex (a->l3cd) == nm_l3_config_data_get_ifindex (b->l3cd));
/* we sort the entries with higher priority (more important, lower numerical value)
* first. */
@@ -747,79 +755,75 @@ _l3_config_combine_sort_fcn (gconstpointer p_a,
return nm_assert_unreachable_val (0);
}
-static const NML3ConfigData *
-_l3cfg_combine_config (GArray *l3_config_datas,
- NMDedupMultiIndex *multi_idx,
- int ifindex)
+static gboolean
+_l3cfg_update_combined_config (NML3Cfg *self,
+ const NML3ConfigData **out_old /* transfer reference */)
{
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMDedupMultiIndex *multi_idx;
gs_free L3ConfigData **infos_heap = NULL;
- NML3ConfigData *l3cfg;
L3ConfigData **infos;
+ GArray *l3_config_datas;
guint i;
- if ( !l3_config_datas
- || l3_config_datas->len == 0)
- return NULL;
-
- if (l3_config_datas->len == 1)
- return nm_l3_config_data_ref (_l3_config_datas_at (l3_config_datas, 0)->merge_info.l3cfg);
-
- if (l3_config_datas->len < 300 / sizeof (infos[0]))
- infos = g_alloca (l3_config_datas->len * sizeof (infos[0]));
- else {
- infos_heap = g_new (L3ConfigData *, l3_config_datas->len);
- infos = infos_heap;
- }
+ nm_assert (NM_IS_L3CFG (self));
+ nm_assert (!out_old || !*out_old);
- for (i = 0; i < l3_config_datas->len; i++)
- infos[i] = _l3_config_datas_at (l3_config_datas, i);
+ if (!self->priv.changed_configs)
+ return FALSE;
- g_qsort_with_data (infos,
- l3_config_datas->len,
- sizeof (infos[0]),
- _l3_config_combine_sort_fcn,
- NULL);
+ self->priv.changed_configs = FALSE;
- nm_assert (&infos[0]->merge_info == (NML3ConfigDatMergeInfo *) infos[0]);
+ multi_idx = nm_platform_get_multi_idx (self->priv.platform);
- l3cfg = nm_l3_config_data_new_combined (multi_idx,
- ifindex,
- (const NML3ConfigDatMergeInfo *const*) infos,
- l3_config_datas->len);
+ l3_config_datas = self->priv.p->l3_config_datas;
- nm_assert (l3cfg);
- nm_assert (nm_l3_config_data_get_ifindex (l3cfg) == ifindex);
+ if ( l3_config_datas
+ && l3_config_datas->len > 0) {
- return nm_l3_config_data_seal (l3cfg);
-}
+ l3cd = nm_l3_config_data_new (multi_idx, self->priv.ifindex);
-static gboolean
-_l3cfg_update_combined_config (NML3Cfg *self,
- const NML3ConfigData **out_old /* transfer reference */)
-{
- nm_auto_unref_l3cfg const NML3ConfigData *l3cfg_old = NULL;
- nm_auto_unref_l3cfg const NML3ConfigData *l3cfg = NULL;
+ if (l3_config_datas->len < 300 / sizeof (infos[0]))
+ infos = g_alloca (l3_config_datas->len * sizeof (infos[0]));
+ else {
+ infos_heap = g_new (L3ConfigData *, l3_config_datas->len);
+ infos = infos_heap;
+ }
- nm_assert (NM_IS_L3CFG (self));
- nm_assert (!out_old || !*out_old);
+ for (i = 0; i < l3_config_datas->len; i++)
+ infos[i] = _l3_config_datas_at (l3_config_datas, i);
+
+ g_qsort_with_data (infos,
+ l3_config_datas->len,
+ sizeof (infos[0]),
+ _l3_config_combine_sort_fcn,
+ NULL);
+
+ for (i = 0; i < l3_config_datas->len; i++) {
+ nm_l3_config_data_merge (l3cd,
+ infos[i]->l3cd,
+ infos[i]->merge_flags,
+ infos[i]->default_route_penalty_x,
+ NULL,
+ NULL);
+ }
- if (!self->priv.changed_configs)
- return FALSE;
+ nm_assert (l3cd);
+ nm_assert (nm_l3_config_data_get_ifindex (l3cd) == self->priv.ifindex);
- self->priv.changed_configs = FALSE;
+ nm_l3_config_data_seal (l3cd);
+ }
- l3cfg = _l3cfg_combine_config (self->priv.p->l3_config_datas,
- nm_platform_get_multi_idx (self->priv.platform),
- self->priv.ifindex);
- if (nm_l3_config_data_equal (l3cfg, self->priv.p->combined_l3cfg))
+ if (nm_l3_config_data_equal (l3cd, self->priv.p->combined_l3cd))
return FALSE;
_LOGT ("desired IP configuration changed");
- l3cfg_old = g_steal_pointer (&self->priv.p->combined_l3cfg);
- self->priv.p->combined_l3cfg = nm_l3_config_data_seal (g_steal_pointer (&l3cfg));
- NM_SET_OUT (out_old, nm_l3_config_data_ref (self->priv.p->combined_l3cfg));
+ l3cd_old = g_steal_pointer (&self->priv.p->combined_l3cd);
+ self->priv.p->combined_l3cd = nm_l3_config_data_seal (g_steal_pointer (&l3cd));
+ NM_SET_OUT (out_old, nm_l3_config_data_ref (self->priv.p->combined_l3cd));
return TRUE;
}
@@ -1008,7 +1012,7 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
int addr_family,
gboolean *out_final_failure_for_temporary_not_available)
{
- nm_auto_unref_l3cfg const NML3ConfigData *l3cfg_old = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_unref_ptrarray GPtrArray *routes = NULL;
gs_unref_ptrarray GPtrArray *addresses_prune = NULL;
@@ -1046,7 +1050,7 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
nm_utils_addr_family_to_char (addr_family),
_l3_cfg_commit_type_to_string (commit_type, sbuf_commit_type, sizeof (sbuf_commit_type)));
- combined_changed = _l3cfg_update_combined_config (self, &l3cfg_old);
+ combined_changed = _l3cfg_update_combined_config (self, &l3cd_old);
IS_IPv4 = NM_IS_IPv4 (addr_family);
@@ -1061,7 +1065,7 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
_l3cfg_externally_removed_objs_pickup (self, addr_family);
}
- if (self->priv.p->combined_l3cfg) {
+ if (self->priv.p->combined_l3cd) {
NMDedupMultiFcnSelectPredicate predicate;
if ( commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY
@@ -1069,7 +1073,7 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
predicate = _l3cfg_externally_removed_objs_filter;
else
predicate = NULL;
- addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_l3_config_data_lookup_objs (self->priv.p->combined_l3cfg,
+ addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_l3_config_data_lookup_objs (self->priv.p->combined_l3cd,
NMP_OBJECT_TYPE_IP_ADDRESS (IS_IPv4)),
predicate,
self->priv.p->externally_removed_objs_hash);
@@ -1079,12 +1083,12 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
predicate = _l3cfg_externally_removed_objs_filter;
else
predicate = NULL;
- routes = nm_dedup_multi_objs_to_ptr_array_head (nm_l3_config_data_lookup_objs (self->priv.p->combined_l3cfg,
+ routes = nm_dedup_multi_objs_to_ptr_array_head (nm_l3_config_data_lookup_objs (self->priv.p->combined_l3cd,
NMP_OBJECT_TYPE_IP_ROUTE (IS_IPv4)),
predicate,
self->priv.p->externally_removed_objs_hash);
- route_table_sync = nm_l3_config_data_get_route_table_sync (self->priv.p->combined_l3cfg, addr_family);
+ route_table_sync = nm_l3_config_data_get_route_table_sync (self->priv.p->combined_l3cd, addr_family);
}
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_NONE)
@@ -1104,16 +1108,16 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
*
* Of course, if an entry is both to be pruned and to be added, then
* the latter wins. So, this works just nicely. */
- if (l3cfg_old) {
+ if (l3cd_old) {
const NMDedupMultiHeadEntry *head_entry;
- head_entry = nm_l3_config_data_lookup_objs (l3cfg_old,
+ head_entry = nm_l3_config_data_lookup_objs (l3cd_old,
NMP_OBJECT_TYPE_IP_ADDRESS (IS_IPv4));
addresses_prune = nm_dedup_multi_objs_to_ptr_array_head (head_entry,
NULL,
NULL);
- head_entry = nm_l3_config_data_lookup_objs (l3cfg_old,
+ head_entry = nm_l3_config_data_lookup_objs (l3cd_old,
NMP_OBJECT_TYPE_IP_ROUTE (IS_IPv4));
addresses_prune = nm_dedup_multi_objs_to_ptr_array_head (head_entry,
NULL,
@@ -1230,7 +1234,7 @@ finalize (GObject *object)
g_clear_object (&self->priv.netns);
g_clear_object (&self->priv.platform);
- nm_clear_pointer (&self->priv.p->combined_l3cfg, nm_l3_config_data_unref);
+ nm_clear_pointer (&self->priv.p->combined_l3cd, nm_l3_config_data_unref);
nm_clear_pointer (&self->priv.pllink, nmp_object_unref);
diff --git a/src/nm-l3cfg.h b/src/nm-l3cfg.h
index 55a062156d..69748b6e79 100644
--- a/src/nm-l3cfg.h
+++ b/src/nm-l3cfg.h
@@ -113,7 +113,7 @@ void nm_l3cfg_mark_config_dirty (NML3Cfg *self,
void nm_l3cfg_add_config (NML3Cfg *self,
gconstpointer tag,
gboolean replace_same_tag,
- const NML3ConfigData *l3cfg,
+ const NML3ConfigData *l3cd,
int priority,
guint32 default_route_penalty_4,
guint32 default_route_penalty_6,
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 5067fdf329..d0ddeb9c3e 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -1975,8 +1975,8 @@ device_ip_config_changed (NMDevice *device,
int addr_family;
nm_assert (new_config || old_config);
- nm_assert (!new_config || NM_IS_IP_CONFIG (new_config, AF_UNSPEC));
- nm_assert (!old_config || NM_IS_IP_CONFIG (old_config, AF_UNSPEC));
+ nm_assert (!new_config || NM_IS_IP_CONFIG (new_config));
+ nm_assert (!old_config || NM_IS_IP_CONFIG (old_config));
if (new_config) {
addr_family = nm_ip_config_get_addr_family (new_config);
diff --git a/src/nm-types.h b/src/nm-types.h
index 5d9eb67dc4..b3530f5bfb 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -24,6 +24,7 @@ typedef struct _NMConfig NMConfig;
typedef struct _NMConfigData NMConfigData;
typedef struct _NMConnectivity NMConnectivity;
typedef struct _NML3Cfg NML3Cfg;
+typedef struct _NML3ConfigData NML3ConfigData;
typedef struct _NMDevice NMDevice;
typedef struct _NMDhcpConfig NMDhcpConfig;
typedef struct _NMProxyConfig NMProxyConfig;