diff options
author | Thomas Haller <thaller@redhat.com> | 2020-08-05 16:30:34 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-08-05 16:30:34 +0200 |
commit | 06e7d72265a20026fad82bad8dab0997080e9d45 (patch) | |
tree | 80c5c82062686c3009a9893f08504daea0efbb57 | |
parent | 26d768a2b670e8f98253e2958e8d0d1017d8f4ee (diff) | |
parent | 79db3972d734d16785b451ab93e25291eb620d33 (diff) | |
download | NetworkManager-06e7d72265a20026fad82bad8dab0997080e9d45.tar.gz |
l3cfg: merge branch 'th/l3cfg-4'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/595
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; |