From 8346870aa654177b841029a439aeeb8b82dfba94 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 24 Jul 2020 09:39:14 +0200 Subject: [PATCH 01/16] shared: add nm_assert_unreachable_val() macro --- shared/nm-std-aux/nm-std-aux.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shared/nm-std-aux/nm-std-aux.h b/shared/nm-std-aux/nm-std-aux.h index 91cd6c37fa..01409cefbb 100644 --- a/shared/nm-std-aux/nm-std-aux.h +++ b/shared/nm-std-aux/nm-std-aux.h @@ -125,6 +125,12 @@ #define nm_assert_not_reached() do { ; } while (0) #endif +#define nm_assert_unreachable_val(val) \ + ({ \ + nm_assert_not_reached (); \ + (val); \ + }) + #define NM_STATIC_ASSERT(cond) static_assert(cond, "") #define NM_STATIC_ASSERT_EXPR(cond) ({ NM_STATIC_ASSERT (cond); 1; }) From 66d4af6daf8dba02c424592b54daa4d33db3ba10 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 11:05:13 +0200 Subject: [PATCH 02/16] shared: add compat function nm_g_ptr_array_copy() for older glib This is not in "nm-glib.h", because it's not a complete replacement. In glib before 2.62, it's not possible to implement g_ptr_array_copy() as glib provides it, because the element_free_func is not accessible. So, instead add our own implemented, which follows glib's version as much as it can. --- shared/nm-glib-aux/nm-shared-utils.c | 23 ++++++++++++++++++ shared/nm-glib-aux/nm-shared-utils.h | 35 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c index f7ae5b88de..e7dbaa8a81 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -2188,6 +2188,29 @@ _nm_utils_strv_cleanup (char **strv, /*****************************************************************************/ +GPtrArray * +_nm_g_ptr_array_copy (GPtrArray *array, + GCopyFunc func, + gpointer user_data, + GDestroyNotify element_free_func) +{ + GPtrArray *new_array; + guint i; + + g_return_val_if_fail (array, NULL); + + new_array = g_ptr_array_new_full (array->len, element_free_func); + for (i = 0; i < array->len; i++) { + g_ptr_array_add (new_array, + func + ? func (array->pdata[i], user_data) + : array->pdata[i]); + } + return new_array; +} + +/*****************************************************************************/ + int _nm_utils_ascii_str_to_bool (const char *str, int default_value) diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index 6aafd09e98..10dd145df2 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -1539,6 +1539,41 @@ nm_g_ptr_array_len (const GPtrArray *arr) return arr ? arr->len : 0u; } +GPtrArray *_nm_g_ptr_array_copy (GPtrArray *array, + GCopyFunc func, + gpointer user_data, + GDestroyNotify element_free_func); + +/** + * nm_g_ptr_array_copy: + * @array: the #GPtrArray to clone. + * @func: the copy function. + * @user_data: the user data for the copy function + * @element_free_func: the free function of the elements. @array MUST have + * the same element_free_func. This argument is only used on older + * glib, that doesn't support g_ptr_array_copy(). + * + * This is a replacement for g_ptr_array_copy(), which is not available + * before glib 2.62. Since GPtrArray does not allow to access the internal + * element_free_func, we cannot add a compatibility implementation of g_ptr_array_copy() + * and the user must provide a suitable destroy function. + * + * Note that the @element_free_func MUST correspond to free function set in @array. + */ +#if GLIB_CHECK_VERSION(2,62,0) +#define nm_g_ptr_array_copy(array, func, user_data, element_free_func) \ + ({ \ + _nm_unused GDestroyNotify const _element_free_func = (element_free_func); \ + \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; \ + g_ptr_array_copy ((array), (func), (user_data)); \ + G_GNUC_END_IGNORE_DEPRECATIONS; \ + }) +#else +#define nm_g_ptr_array_copy(array, func, user_data, element_free_func) \ + _nm_g_ptr_array_copy ((array), (func), (user_data), (element_free_func)) +#endif + /*****************************************************************************/ static inline guint From c470cbf7058df38db44301c5cc09fd2191e2bf7d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 10:50:40 +0200 Subject: [PATCH 03/16] shared: add nm_copy_func_g_strdup() helper --- shared/nm-glib-aux/nm-shared-utils.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index 10dd145df2..f90f7629af 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -525,6 +525,14 @@ char **_nm_utils_strv_cleanup (char **strv, /*****************************************************************************/ +static inline gpointer +nm_copy_func_g_strdup (gconstpointer arg, gpointer user_data) +{ + return g_strdup (arg); +} + +/*****************************************************************************/ + static inline const char ** nm_utils_escaped_tokens_split (const char *str, const char *delimiters) From a8517423c73783a5f182b925ebda063d481f1330 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 10:50:53 +0200 Subject: [PATCH 04/16] shared: add nm_strv_ptrarray_clone() helper --- shared/nm-glib-aux/nm-shared-utils.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index f90f7629af..2f6681cb70 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -1809,6 +1809,16 @@ nm_strv_ptrarray_ensure (GPtrArray **p_arr) return *p_arr; } +static inline GPtrArray * +nm_strv_ptrarray_clone (const GPtrArray *src, gboolean null_if_empty) +{ + if ( !src + || ( null_if_empty + && src->len == 0)) + return NULL; + return nm_g_ptr_array_copy ((GPtrArray *) src, nm_copy_func_g_strdup, NULL, g_free); +} + static inline void nm_strv_ptrarray_add_string_take (GPtrArray *cmd, char *str) From b2df6fde303eab163e4dff9a260e9bf7a35588ed Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 16:43:20 +0200 Subject: [PATCH 05/16] shared/tests: add nmtst_stable_rand() Generate a list of pseudo random numbers, the important part here is that the result is stable and independent of endianness. --- shared/nm-utils/nm-test-utils.h | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index c270d2b941..b43e233007 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -984,6 +984,50 @@ nmtst_rand_perm_gslist (GRand *rand, GSList *list) return result; } +static inline void +nmtst_stable_rand (guint64 seed, + gpointer buf, + gsize len) +{ + const guint64 C = 1442695040888963407llu; + const guint64 A = 6364136223846793005llu; + guint8 *b; + union { + guint8 a[sizeof (guint64)]; + guint64 n; + } n; + + /* We want a stable random generator that is in our control and does not + * depend on glibc/glib versions. + * Use a linear congruential generator (x[n+1] = (A * x[n] + C) % M) + * https://en.wikipedia.org/wiki/Linear_congruential_generator + * + * We choose (Knuth’s LCG MMIX) + * A = 6364136223846793005llu + * C = 1442695040888963407llu + * M = 2^64 + */ + + g_assert (len == 0 || buf); + + n.n = seed; + b = buf; + for (; len > 0; len--, b++) { + n.n = (A * n.n + C); + + /* let's combine the 64 bits randomness in one byte. By xor-ing, it's + * also independent of endianness. */ + b[0] = n.a[0] + ^ n.a[1] + ^ n.a[2] + ^ n.a[3] + ^ n.a[4] + ^ n.a[5] + ^ n.a[6] + ^ n.a[7]; + } +} + /*****************************************************************************/ /** From b15c85cf8b0135b76b60bbae4863cac6a2efcb22 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 18:28:12 +0200 Subject: [PATCH 06/16] core: move nm_utils_ip4_address_is_link_local() to header file It's so simple, let's move it so it can be inlined. --- src/nm-core-utils.c | 11 ----------- src/nm-core-utils.h | 13 ++++++++++++- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index d186405672..75e0941aa9 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -3829,17 +3829,6 @@ nm_utils_ifname_cpy (char *dst, const char *name) /*****************************************************************************/ -#define IPV4LL_NETWORK (htonl (0xA9FE0000L)) -#define IPV4LL_NETMASK (htonl (0xFFFF0000L)) - -gboolean -nm_utils_ip4_address_is_link_local (in_addr_t addr) -{ - return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK; -} - -/*****************************************************************************/ - /** * Takes a pair @timestamp and @duration, and returns the remaining duration based * on the new timestamp @now. diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 190a81aa81..5d36bd593c 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -446,7 +446,18 @@ guint32 nm_utils_lifetime_get (guint32 timestamp, gint32 now, guint32 *out_preferred); -gboolean nm_utils_ip4_address_is_link_local (in_addr_t addr); +/*****************************************************************************/ + +#define NM_IPV4LL_NETWORK ((in_addr_t) (htonl (0xA9FE0000lu))) +#define NM_IPV4LL_NETMASK ((in_addr_t) (htonl (0xFFFF0000lu))) + +static inline gboolean +nm_utils_ip4_address_is_link_local (in_addr_t addr) +{ + return (addr & NM_IPV4LL_NETMASK) == NM_IPV4LL_NETWORK; +} + +/*****************************************************************************/ const char *nm_utils_dnsmasq_status_to_string (int status, char *dest, gsize size); From be655e6ed1530bc0a606ddfa1b5d91a495392d47 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 14:51:58 +0200 Subject: [PATCH 07/16] core: read "disable_ipv6" sysctl before nm_ip6_config_create_setting() First of all, the entire nm_device_generate_connection() and nm_ip._config_create_setting() approach is fundamentally flawed. You cannot generate sensible configuration by reading IP addresses from an interface. Anyway, that's what we still sometimes do, and we possibly should do it less and less. It's ugly that nm_ip6_config_capture() would read the "disable_ipv6" sysctl value and cache it in NMIP6Config. Only so that it can be use much later during nm_ip6_config_create_setting(). Instead, read the sysctl value shortly before it's needed. --- src/devices/nm-device.c | 29 +++++++++++++++++++++++++---- src/nm-ip6-config.c | 23 ++--------------------- src/nm-ip6-config.h | 2 +- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 91b0edfd50..8950f01bde 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -6169,6 +6169,26 @@ nm_device_master_update_slave_connection (NMDevice *self, return FALSE; } +static gboolean +_get_maybe_ipv6_disabled (NMDevice *self) +{ + NMPlatform *platform; + int ifindex; + const char *path; + char ifname[IFNAMSIZ]; + + ifindex = nm_device_get_ip_ifindex (self); + if (ifindex <= 0) + return FALSE; + + platform = nm_device_get_platform (self); + if (!nm_platform_if_indextoname (platform, ifindex, ifname)) + return FALSE; + + path = nm_sprintf_bufa (128, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname); + return (nm_platform_sysctl_get_int32 (platform, NMP_SYSCTL_PATHID_ABSOLUTE (path), 0) == 0); +} + NMConnection * nm_device_generate_connection (NMDevice *self, NMDevice *master, @@ -6237,7 +6257,7 @@ nm_device_generate_connection (NMDevice *self, s_ip4 = nm_ip4_config_create_setting (priv->ip_config_4); nm_connection_add_setting (connection, s_ip4); - s_ip6 = nm_ip6_config_create_setting (priv->ip_config_6); + s_ip6 = nm_ip6_config_create_setting (priv->ip_config_6, _get_maybe_ipv6_disabled (self)); nm_connection_add_setting (connection, s_ip6); nm_connection_add_setting (connection, nm_setting_proxy_new ()); @@ -13415,9 +13435,10 @@ nm_device_set_ip_config (NMDevice *self, new_connection = nm_simple_connection_new_clone (nm_settings_connection_get_connection (settings_connection)); nm_connection_add_setting (new_connection, - IS_IPv4 - ? nm_ip4_config_create_setting (priv->ip_config_4) - : nm_ip6_config_create_setting (priv->ip_config_6)); + IS_IPv4 + ? nm_ip4_config_create_setting (priv->ip_config_4) + : nm_ip6_config_create_setting (priv->ip_config_6, + _get_maybe_ipv6_disabled (self))); nm_settings_connection_update (settings_connection, new_connection, diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 6c15e99765..61b32b68a1 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -64,7 +64,6 @@ typedef struct { NMDedupMultiIdxType idx_ip6_routes; }; NMIPConfigFlags config_flags; - bool ipv6_disabled; } NMIP6ConfigPrivate; struct _NMIP6Config { @@ -373,8 +372,6 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i const NMDedupMultiHeadEntry *head_entry; NMDedupMultiIter iter; const NMPObject *plobj = NULL; - char ifname[IFNAMSIZ]; - char *path; nm_assert (ifindex > 0); @@ -416,12 +413,6 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i nmp_cache_iter_for_each (&iter, head_entry, &plobj) _add_route (self, plobj, NULL, NULL); - if (nm_platform_if_indextoname (platform, ifindex, ifname)) { - path = nm_sprintf_bufa (128, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname); - if (nm_platform_sysctl_get_int32 (platform, NMP_SYSCTL_PATHID_ABSOLUTE (path), 0) != 0) - priv->ipv6_disabled = TRUE; - } - return self; } @@ -757,7 +748,7 @@ nm_ip6_config_merge_setting (NMIP6Config *self, } NMSetting * -nm_ip6_config_create_setting (const NMIP6Config *self) +nm_ip6_config_create_setting (const NMIP6Config *self, gboolean maybe_ipv6_disabled) { const NMIP6ConfigPrivate *priv; NMSettingIPConfig *s_ip6; @@ -822,7 +813,7 @@ nm_ip6_config_create_setting (const NMIP6Config *self) /* Use 'ignore' if the method wasn't previously set */ if (!method) { - method = priv->ipv6_disabled + method = maybe_ipv6_disabled ? NM_SETTING_IP6_CONFIG_METHOD_DISABLED : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; } @@ -893,13 +884,11 @@ nm_ip6_config_merge (NMIP6Config *dst, NMDedupMultiIter ipconf_iter; const NMPlatformIP6Address *address = NULL; const NMIP6ConfigPrivate *src_priv; - NMIP6ConfigPrivate *dst_priv; g_return_if_fail (src != NULL); g_return_if_fail (dst != NULL); src_priv = NM_IP6_CONFIG_GET_PRIVATE (src); - dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst); g_object_freeze_notify (G_OBJECT (dst)); @@ -965,9 +954,6 @@ nm_ip6_config_merge (NMIP6Config *dst, if (nm_ip6_config_get_dns_priority (src)) nm_ip6_config_set_dns_priority (dst, nm_ip6_config_get_dns_priority (src)); - if (src_priv->ipv6_disabled) - dst_priv->ipv6_disabled = src_priv->ipv6_disabled; - g_object_thaw_notify (G_OBJECT (dst)); } @@ -1573,11 +1559,6 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev has_minor_changes = TRUE; } - if (src_priv->ipv6_disabled != dst_priv->ipv6_disabled) { - dst_priv->ipv6_disabled = src_priv->ipv6_disabled; - has_minor_changes = TRUE; - } - #if NM_MORE_ASSERTS /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index b6f461b29f..4c21768ad8 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -105,7 +105,7 @@ void nm_ip6_config_merge_setting (NMIP6Config *self, NMSettingIPConfig *setting, guint32 route_table, guint32 route_metric); -NMSetting *nm_ip6_config_create_setting (const NMIP6Config *self); +NMSetting *nm_ip6_config_create_setting (const NMIP6Config *self, gboolean maybe_ipv6_disabled); void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, From d7608f32a6b7b3c3ddc72d2ece16db4009648ace Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 15:23:23 +0200 Subject: [PATCH 08/16] platform: add nm_platform_ip[46]_address_pretty_sort_cmp() This is the code from _addresses_sort_cmp() in "nm-ip[46]-config.h" and will replace it soon. --- src/nm-ip4-config.c | 15 + src/nm-ip4-config.h | 2 + src/nm-ip6-config.c | 8 + src/nm-ip6-config.h | 2 + src/platform/nm-platform.c | 132 +++++ src/platform/nm-platform.h | 7 + src/platform/tests/test-platform-general.c | 658 +++++++++++++++++++++ 7 files changed, 824 insertions(+) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index bd09ed511f..c247ffc92a 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -549,6 +549,21 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data) return memcmp (&n1, &n2, sizeof (guint32)); } +int +nmtst_ip4_config_addresses_sort_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) +{ + NMPObject o_a; + NMPObject o_b; + NMPObject *p_o_a = &o_a; + NMPObject *p_o_b = &o_b; + + g_assert (a); + g_assert (b); + nmp_object_stackinit (&o_a, NMP_OBJECT_TYPE_IP4_ADDRESS, a); + nmp_object_stackinit (&o_b, NMP_OBJECT_TYPE_IP4_ADDRESS, b); + return _addresses_sort_cmp (&p_o_a, &p_o_b, NULL); +} + /*****************************************************************************/ static int diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index f1c4a57e85..0d1a67b1bf 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -603,4 +603,6 @@ nm_ip_config_intersect_alloc (const NMIPConfig *a, } } +int nmtst_ip4_config_addresses_sort_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); + #endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 61b32b68a1..cfe63431f0 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -290,6 +290,14 @@ _addresses_sort_cmp (const NMPlatformIP6Address *a1, return c != 0 ? c : memcmp (a1, a2, sizeof (*a1)); } +int +nmtst_ip6_config_addresses_sort_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean prefer_temp) +{ + g_assert (a); + g_assert (b); + return _addresses_sort_cmp (a, b, prefer_temp); +} + static int _addresses_sort_cmp_prop (gconstpointer a, gconstpointer b, gpointer user_data) { diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 4c21768ad8..ae1b8c0a46 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -220,4 +220,6 @@ void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self, void nm_ip6_config_update_routes_metric (NMIP6Config *self, gint64 metric); +int nmtst_ip6_config_addresses_sort_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean prefer_temp); + #endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 5c4a3abb55..0ab2c52b33 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -7202,6 +7202,138 @@ nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireGuard *a, const NMPlatform return 0; } +static int +_address_pretty_sort_get_prio_4 (in_addr_t addr) +{ + if (nm_utils_ip4_address_is_link_local (addr)) + return 0; + return 1; +} + +int +nm_platform_ip4_address_pretty_sort_cmp (const NMPlatformIP4Address *a1, + const NMPlatformIP4Address *a2) +{ + in_addr_t n1; + in_addr_t n2; + int p1; + int p2; + + nm_assert (a1); + nm_assert (a2); + + /* Sort by address type. For example link local will + * be sorted *after* a global address. */ + p1 = _address_pretty_sort_get_prio_4 (a1->address); + p2 = _address_pretty_sort_get_prio_4 (a2->address); + if (p1 != p2) + return p1 > p2 ? -1 : 1; + + /* Sort the addresses based on their source. */ + if (a1->addr_source != a2->addr_source) + return a1->addr_source > a2->addr_source ? -1 : 1; + + if ((a1->label[0] == '\0') != (a2->label[0] == '\0')) + return (a1->label[0] == '\0') ? -1 : 1; + + /* Finally, sort addresses lexically. We compare only the + * network part so that the order of addresses in the same + * subnet (and thus also the primary/secondary role) is + * preserved. + */ + n1 = a1->address & _nm_utils_ip4_prefix_to_netmask (a1->plen); + n2 = a2->address & _nm_utils_ip4_prefix_to_netmask (a2->plen); + + return memcmp (&n1, &n2, sizeof (guint32)); +} + +static int +_address_pretty_sort_get_prio_6 (const struct in6_addr *addr) +{ + if (IN6_IS_ADDR_V4MAPPED (addr)) + return 0; + if (IN6_IS_ADDR_V4COMPAT (addr)) + return 1; + if (IN6_IS_ADDR_UNSPECIFIED (addr)) + return 2; + if (IN6_IS_ADDR_LOOPBACK (addr)) + return 3; + if (IN6_IS_ADDR_LINKLOCAL (addr)) + return 4; + if (IN6_IS_ADDR_SITELOCAL (addr)) + return 5; + return 6; +} + +int +nm_platform_ip6_address_pretty_sort_cmp (const NMPlatformIP6Address *a1, + const NMPlatformIP6Address *a2, + gboolean prefer_temp) +{ + gboolean ipv6_privacy1; + gboolean ipv6_privacy2; + gboolean perm1; + gboolean perm2; + gboolean tent1; + gboolean tent2; + int p1; + int p2; + int c; + + nm_assert (a1); + nm_assert (a2); + + /* tentative addresses are always sorted back... */ + /* sort tentative addresses after non-tentative. */ + tent1 = (a1->n_ifa_flags & IFA_F_TENTATIVE); + tent2 = (a2->n_ifa_flags & IFA_F_TENTATIVE); + if (tent1 != tent2) + return tent1 ? 1 : -1; + + /* Sort by address type. For example link local will + * be sorted *after* site local or global. */ + p1 = _address_pretty_sort_get_prio_6 (&a1->address); + p2 = _address_pretty_sort_get_prio_6 (&a2->address); + if (p1 != p2) + return p1 > p2 ? -1 : 1; + + ipv6_privacy1 = !!(a1->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); + ipv6_privacy2 = !!(a2->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); + if (ipv6_privacy1 || ipv6_privacy2) { + gboolean public1 = TRUE, public2 = TRUE; + + if (ipv6_privacy1) { + if (a1->n_ifa_flags & IFA_F_TEMPORARY) + public1 = prefer_temp; + else + public1 = !prefer_temp; + } + if (ipv6_privacy2) { + if (a2->n_ifa_flags & IFA_F_TEMPORARY) + public2 = prefer_temp; + else + public2 = !prefer_temp; + } + + if (public1 != public2) + return public1 ? -1 : 1; + } + + /* Sort the addresses based on their source. */ + if (a1->addr_source != a2->addr_source) + return a1->addr_source > a2->addr_source ? -1 : 1; + + /* sort permanent addresses before non-permanent. */ + perm1 = (a1->n_ifa_flags & IFA_F_PERMANENT); + perm2 = (a2->n_ifa_flags & IFA_F_PERMANENT); + if (perm1 != perm2) + return perm1 ? -1 : 1; + + /* finally sort addresses lexically */ + c = memcmp (&a1->address, &a2->address, sizeof (a2->address)); + return c != 0 ? c : memcmp (a1, a2, sizeof (*a1)); +} + void nm_platform_ip4_address_hash_update (const NMPlatformIP4Address *obj, NMHashState *h) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 339ef5ba3b..1a2e339100 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1943,6 +1943,13 @@ int nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireGuard *a, const NMPlat int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b); +int nm_platform_ip4_address_pretty_sort_cmp (const NMPlatformIP4Address *a1, + const NMPlatformIP4Address *a2); + +int nm_platform_ip6_address_pretty_sort_cmp (const NMPlatformIP6Address *a1, + const NMPlatformIP6Address *a2, + gboolean prefer_temp); + int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteCmpType cmp_type); int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, NMPlatformIPRouteCmpType cmp_type); diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c index 255210f220..a5efdb399e 100644 --- a/src/platform/tests/test-platform-general.c +++ b/src/platform/tests/test-platform-general.c @@ -9,6 +9,7 @@ #include "platform/nm-platform-utils.h" #include "platform/nm-linux-platform.h" +#include "nm-ip4-config.h" #include "nm-test-utils-core.h" @@ -62,6 +63,660 @@ test_nm_platform_link_flags2str (void) /*****************************************************************************/ +static int +_address_pretty_sort_cmp (gconstpointer a, + gconstpointer b, + gpointer test_data) +{ + const int TEST_DATA_I = GPOINTER_TO_INT (test_data); + const int addr_family = (TEST_DATA_I == 0 ? AF_INET : AF_INET6); + const int IPV6_PREFER_TEMP = (TEST_DATA_I == 2); + const NMPlatformIPXAddress *a_a = a; + const NMPlatformIPXAddress *a_b = b; + + if (addr_family == AF_INET) + return nm_platform_ip4_address_pretty_sort_cmp (&a_a->a4, &a_b->a4); + + return nm_platform_ip6_address_pretty_sort_cmp (&a_a->a6, &a_b->a6, IPV6_PREFER_TEMP); +} + +static void +test_platform_ip_address_pretty_sort_cmp (gconstpointer test_data) +{ + static const char *const EXPECTED_BUFFER[3] = { + [0] = ( + "5b1aea34648cabfec7c3523f76cf1ce34ca17a9a32f3f0f218424e48836dd1cb504e03d53e1124c5" + "0065aeb2e6fbf952902383028e3b47f280f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a" + "8982c42f0000003437c5156e072b2f2f0037c9cfe07c34ddb3980deb14ab7b5af84a034703000000" + "883b0f3fd6ed84d6c959e553b887edcd01c2f5d200000043b809d259e499db7d00f1853bdcb0e4bc" + "0e2b00b667b7b16d8d1e69c803000000b973972c17a47631c169f11ff9119c400368b6630000007a" + "034f43340d01683c0045097aea4a849f060ddf57b24a5be9636360d603000000ad7c499dd538d345" + "74c038404923e75d0209e2fc0000004acc807cdce682f80f00315c45ef817264c89a736ed55ed637" + "b96c200203000000faf1809becd2506315a6da29b2e94d3a031fe0e900000083a36035fb6297dfa7" + "00686b5efd0d53bb6215de4bb6f6f3d031a79028030000008bb836c0a25ea71f5daaed4d99eb2ebe" + "033c432f000000bf4ccf30d3aaaf02a4005d7308b67f91bf9d82c856ba942455e8d07c8403000000" + "f2abb982b001ec16901f55f960c55c22022099a80000002b4d4647f53b1921af0088e3759a08e7a5" + "6663861eea1bf42c12ea3b9503000000fb95e8332fdfff658483a2d039a7bf1402d3481e00000060" + "e89f7abdb682380a00eae374835b4a49a2b980b6aba92da6409969aa03000000e00473755d31e5b2" + "de252167c1c91b3a02ba0c700000007740318db913a353ed006efc068829c0e66ad0143a0554efb4" + "40e55b8b03000000c0cfb2b4386bec092fa5757ecde9348b00c12ebd000000ab667224dae775e5cc" + "0041aca2ff0f576767d3648102b61886d149f07403000000153ece68ade15cec25a59273e7519f34" + "c4458d70000000f3819aa46fbe1439340033ae6dec0fb124f264af67eed7c9a8ecc8fb1103000000" + "fcebbaeb0c56535923f14874042a8aff021f8e5ec3cc13cc36bbe3c9bb0ec36f00e007bb64a2827b" + "7cdd38d0314c178e5a06c40b03000000ab90135fa636af4464d210a256be75e0029c44770000004b" + "2e69220d6c0fc09c25d6534c809829af4a9df58dbfef186d416f3a1e030000002c932e655203d82a" + "3c84c4eb274ed18603780281000000f2235376239daeaacb3cae864b437baaae91921681c2162b9b" + "69e66142030000004fda8a3e0b841cf76391dd68269b53ec0244a831000000b78c54dda9ac3bb1b1" + "d43e6505621b9a7f0422ae3fc8979ee0416f95e70300000057d6249b652ba98c7dc7f17f666969e4" + "023baf7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695111d891d03000000" + "cd897619f51f44e644d7cf1d06b2b1150082549e62c12fba5b1cdec48d10bbb13b8313d8cd2a24d3" + "4fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5d8a4c5cf3351ee1c03c2056c00000051" + "bbce426cfa4b861cc78592be7b14e7ba9c15acb881ae55f0e5fe7d360300000066a3ae3939762df3" + "3a2d55060c78d55100b110fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b" + "86ed271803000000a5edc511c1507a141e0f515638c7ba31027609450000003357ae79989870ccec" + "3def0ad92749e016663fe6ee0228c1da82d1595603000000348352d715cf9d411ea012e5307294b6" + "0146dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26bb20413203000000" + "862573c2303dd1d65c7b2cffeca6d1adaccae11f0000000f855ebf3b772eb2b1c896c9a7304f6645" + "0a5f6abd850b06e3b10123e6030000001dff045298cfee0636674cdefb57b9ae54cfe8f400000038" + "1ba2c4396de60f032bc7f34de2959871c0d4c0d4eb720c4ab550c5db03000000f32f4af595d785d5" + "c1b5aad487c192f08bd7a09b00000043288cd9bf66ec305a225a0c71b2ce78bb16104c8eaf18c565" + "b16c7376030000005219061ab4c5c79489b2cc6a883c146972decb8b000000f5e6d66df46ea13910" + "7754dee62c36d2fc70ccc567df7a49b8585287dc03000000cfb18b2b2cb749e2e03e544d0eb4f73e" + "75039fcf251b32fc79685b05ddd3aa9ba511d2e40edb4d758fb554158ae5c7c0beb42b3403000000" + "895d5f24037d233302ad3b82d639272e0246eadfbd2146bf8cfdb205f90e54b58a6ee136a779f37c" + "30d2c5053c40ecaec38b6b8e03000000bea73223e59bf0193432e9fa7a899f2d8ec7e4b89bf5a5d0" + "6776e66a9d80ab132e1ac921eb76adbb229df32e561fa80a0fc4676703000000a23eb66e720da9e0" + "7ac998b5690807d50217369ee1af4ca5a6a95581af5fd7ceacdca10f47d7b351a36b178aabc78a4a" + "1a0dd8c003000000e2815a1a37a52bddd1c2f1018b587eed03bb58f0e9201f17bd99fcf72909ac9e" + "7a55299e9bb4fd53bc7417940fcffe3f81cafd6302000000d6732578acd14320aefd4503189f7630" + "038e501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eb62f22ca02000000" + "891715df7fc6a902edae579e2e10c7f7022ba0340436242cbeb0248cee3fbc160032d4f28aa28c08" + "f80dd50c6712dfb4abba4a32020000008ffe423d01883918039249f398f9b37ea091465100000064" + "3722d9b707c0d8a400b7c8307f06b4b29088f20d9ac676d5e4bafc4e02000000fde69eec3af2e6d0" + "bd68ab722af14548b29572e504265f6c72923e22594f3f790008ed2e2ebb0771db46a54cadb245ea" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd6011fa56dfdcfc1155f236c8b9c79a620" + "00660bbf024b03ff0a8e27c405e64244e36f90d402000000fd41fe47684b370b6ec6584d64496089" + "570968ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a119c64ed0402000000" + "a660ac824b7fae389861419c50da49bf02092583000000259f9f0251becc987907879cca68fec7bb" + "bb5f8edf248b4995d184e82002000000a19cdf6dd1c173f6078a806d329c9b0000bfc972000000f5" + "b2cd3dbddc74e26de958e48d2ab8b0313e7f8933e315130f641e447502000000b9b68c08a5e4351e" + "a349e1ccf662e058b879a45100000045fcb6a035339d504c9726d80d9c2d89df765b4d9a130257dc" + "d1e1b34902000000bcd7be07d78e6222e45aaf61814f703b40125e6b000000cbaaa37b861e6d46da" + "fe7d6ec4ac1ea051010911915ddb05f2c43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0" + "032d2ec50000000103781b0f294a2b7300421398f4de67e9cee64b38b56e03e01539ce4101000000" + "18238487a417f3da01d99dae5f19009601582cab0000005b2363d13edc5aa115005eb914d8fbe9a4" + "fdb3d117d76b0de5bd82e9ea010000003d1b91caae8cb60b49ba9be338d856a40267c3d400000064" + "9da90bd2fff2f2560046870bd7d5f14870c6d18d6242b356b9ef1b2101000000f90adac616a31dc2" + "e46a234558817151008fc9c900000073e64b0bd761fdf274005dca8ce1bd1871ae17bb4515856092" + "b4d9e89b010000006855676c277cf1bd017c9148da5892bb0351c3a70000009f3391ce7d3fd48469" + "005f0c233dbdd2a97835df1f1782dee86c1de913010000003ee1d76fc1ea76e98c9dfc78997ab53e" + "00c21963f5b4cb2454830c68e44ea74b002b83f9b3bee14d861a4c9eeecc89f65408c1b701000000" + "d9e1825fa638e1af284a024b7f9e85ff00e050a2000000276e08cb887464b93400c3127c750fabdd" + "69121aec129cdc690d58fbcc01000000d0d44ff1e51c35157666c05348e6f50700a8e89800000012" + "b900b2061d0c334b009f2dd1cdf64b0f9a60e0e289f08db3fde6b0250100000039dd8f88152a5845" + "4d9ca9d20f45dfa702e78604000000fbcd7db68b9ae586da00b4070c50320427c4dd3d031e33f22c" + "210aeb09010000007000b96d06992b6a58acd3995b9663d20248f333ef467092818aa77d6732b678" + "00844ef5a943825fcd743f59bd14c89b955e1a13010000007acbce3e3bcdf3824f1b134847ff26ba" + "009a774900000017ec852d59f3d17232edd86ad6c3103a68843a9aef34983882d3d3878501000000" + "5e0dfe491d1ba96742c7b5e02b2271220188b02a06d0dc5504b0595daf37deb499996bfb667f072d" + "ec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2ccd47724a3c460ba80383f4c500000063" + "eafb1ac4c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8ca0100000027335a25a364d101" + "5ffac03089f4553902b01784000000d7b83579b8da27345a72437f9b6245de39ec9e71ee4b951507" + "f121014a01000000efc67bce716c856e3973dc42a1003be94f89d8ee0000009b5d5bbe6c10085f3d" + "6176f78a19bb8df1804c122fce5078c156e8f3fe010000000ea8042602a1f8e6f5657f3f9e3eb807" + "cbad7645000000b8df6f628a70456d79f25d5895fb57fa60d9279fb2b8fcbac65ad47b8a01000000" + "da40d88d40a6d75bc404156225b7eedefc2b44574b15e2ae496ad01bf007eacb0a28aec868282510" + "b60291ea6480e356925b568a0000000087bb24e5264fd3ebe9cf9f6df9615189018ee815000000a7" + "5c9555876b6a3f13002b6cb8360feaac1d5c302df59dd32a7a859db500000000362956cd46646a0e" + "222160e5f769bb290366ed370000005b6a813387e99bb834009da86c64fefab2548759d313a5b92d" + "8e47935e0000000034f0386a253c21d94064f6b021281e230094ae20000000d71fd050bf8d85055b" + "00e3756ccdb3455c60ca7b11c66af76e594f24a100000000e143fd52599364e13468f80fd514573f" + "b572671c0000006932d1d5f5d0ce2cf6007a70ba5193a162bc92ec1b11d9172c857ae81200000000" + "3e29535402e9b690c628d048eacce745ea213cb1000000b632ef3be6070dafa200187470e9da5570" + "9427c226d324d9a08487fd0d00000000b7a350f9fc1519defa7db4532545666937c22a3b000000dc" + "c405cbee5016c25200d8901d7a0165fe20744edb6ba04f14a4c73cf500000000a4bab14874afdf54" + "e6aae816430607ca0675e09818e9bbec5918c59068baf76a008940f6fc3bbdc7f6090f756aae660b" + "6e4c699300000000d9c1e67743efb54e54270e46042e911803894e38000000376feecb80ac245409" + "c0becc271d9c2f67179bff0644399ae7e3c9472e00000000c5cfd9f2343b21362c19a0921dce2f83" + "00defa45000000270b9977e166bee737fe73670c439a644c323b59b4cd20eb7dabea74f700000000" + "f6989d2d6a909e986ff7add5df2c93e05459507b0000000f466554d2ae4d52a8c67b2e48b47003c8" + "1785d3ffdbd9a617df6b3542000000004c5cf8107ba282f4f983821918f93e742d08f0550000006f" + "2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b5159747cf200000000ab2dadc5a39411fd" + "4ff1116d478987316a553fc2000000cfc6ebe434a7ae8ff040483e310819e3b10db116431ec6f769" + "438a72e1000000002495a609675344f7e2e3a5ebaec3c85f0a1742f70abe95c50345132a61eda239" + "d9d083c3bf085387046ef8a36f0e9e696b382ab0000000009a6ce5d906837dbca6a5ee19d6f63fe9" + "03dd01f7246f13b2050424a2b3a45ef7a029c896b4132bd895072cfeffe9d6815997069500000000" + "0d3c723b91adb0da7c4aa7e7eb5a15bc03015fb98b841fd84cc43c510385b9a4c2aac1d67a909b29" + "7c703915312e9c3cae02dfa000000000dd603bd35e7fa0f02f2f3313d8469d09a92409c0b7f0318a" + "575a4f8e061db3dd7fde25654a4059d565dbc8a91e3b4457b077ddad3108be69f9b97d05c917ad6b" + "10e693bb6e26f2ba90c8e909a9fe20e5c7a4c656482a9b0d00625009a40aeb62a42b6a62548e3c38" + "cd3c72f203000000ca82ac5180101be4f85cef468ea086ea01aafdc3a9fe1ec787bc45db7c52a52d" + "00bd39a44e8e8bc17c01ac63eca0c1cf5ff7f03a03000000c9a89192c1c8be55281a59d1fd338f35" + "0075f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d53b02239e03000000" + "24438387def0f4c6544e4b275d9b714600f810d2a9fec17647176b7c07d856e3b883efebc09dd9d6" + "1966b7ae7412041d57393c6f03000000182c0287822a272bec4501a1e27acfee018588ffa9fe6cae" + "426de59560fad65d67c624f285d7174177a47579dda0b6eaa9a84c820300000070b1646d8026e9f1" + "704f1b16286ba2da017ef082a9feed33ef60a8b540b26f66761d1f13badfad0fe8fa8f3c1aad2a82" + "fa40546c03000000df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea9fe3e7d75a2f42b50c6a363" + "40132378b95c59313bacba64dbe996206e6904f50200000047150b9b14010469823acb72bb89182f" + "00112196a9feb9153b36bc60be5b534e006527f67485ab35aca0c7ee419733853cf09e8b02000000" + "e79c10acfce165e332a62384ec04e5ba009185ada9fe0070a36dd51323b2c54200154d12f86c260a" + "9edfa7a74c1c83c1050f63f802000000443cacf59c6379a44b7892f487afa98c0221c19ca9fe942f" + "460bcea75481f25e007d0de9a7afe283bd2f22ead05ff72006c83bc0020000004bdade862c224f6f" + "36506ebd455e679c00369bb8a9fecec3f8c8fa6867a982be8a934f852cc3d4d82bc0ec7303f99f8f" + "def85b7502000000a0bef8675b29a197b7b3cceaf5f1bb120335256aa9fe6e5d58099ffc4a503a71" + "2350acbd48411f0dc15d2f0f49dad345d966279502000000e06302aba042aaa218dc091e9aa1477f" + "6fdc9830a9fec95829a8838314dff34d24c332219a1b163a732d803e0e2f4f916d06412601000000" + "98c39e7cc282208fefc57ff447036b9501adcb22a9fe793f797a3c7dadd1c86e009d0c90bc512e13" + "7dcef5e4a27985bd5cfd5ce601000000152f2b70eaef7443e0f79ab6902dde5301b3ec71a9fe9f25" + "4ac95883195580410062ed564153e17478f8c3344d89c0bbfaa100fd01000000be184524a6bdc878" + "9cf851782d895bcc03a98489a9fe8c1287e6f7bb020ffdb00012098610e52bb2a16a4008aefd545b" + "0d80684e01000000ba8110fb9733cc24904f288262e6ea77032fa5f8a9feeefa701d120523bd98f2" + "00098b43cd68be6e3f81268193fd637e9037d7a701000000c47cf0f551e96770a754ac19ef820fe0" + "0031f2d3a9fe049150b8d10ab700cc3a7cf51be0403b654ba2f56808092069af5f5b481b01000000" + "68cb3bc873b04d937a6ed8f7bc51e54066fed098a9fe048a92d3adc69a84eb47622400207799416a" + "f1f0a086fbd7e2f7dea0077a00000000c386e9c6e6a2cbfa10ee58bdc75183600085d627a9feb1cb" + "e491cbbbf9443fd6007eb3c5bf64b671d6f18dbf463f9b83f512dc1c00000000fbab244735d67c61" + "283031667b2d74a102e0b1b1a9fe2aa590a2312e17f1a35900459582f4ef43c780908872746e39ef" + "a9a89f8700000000fcdf6d9be94030b34774d1d7dddedd9802f0f627a9fe965a87041331b2834bcf" + "00b4e3ce848518c4e3f6cbf25e5e1b992231bb0200000000173c333cd03bc905b7b899afeb760e3f" + "024a2efca9fe96b89b1bc8f415bd4e77be46bae5a1b3cae76665a268abfe8a41a84e27c100000000" + "cb29efdf672d2fa57fc85ebbe276c5660364192da9fee7af5eb888e9eb37bb046686943b101e1f55" + "3215abf8fbdf17c3677e5a3a00000000608df061d45d864d09f4ecf17625f82d03c74828a9fe1e37" + "1051852c972ea7954079884af257b044fd13a6826a4c619f3d136cac000000009402a4c216772167" + "3f2b02b3256ead1f03ea9bc1a9fefca162fb81e733cff620ca7feefe1933631e8e69f6d9d6962d2c" + ), + [1] = ( + "54270e46020000006a894e387625da376feecb80ac245409c0becc271d9c2f67179bff0644399ae7" + "9c64ed0432d599eaa660ac824b7fae389861419c7a899f2d010000009bf5a5d06776e66a9d80ab13" + "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" + "c4e1966800000000b3121cd5ef51e696c816290dbaee0e7726d082e1530ff5397c9125f59577d71c" + "4b258a005116d11354edff62ceaa458fc75a91c425a5927300000000c4458d70911714f1819aa46f" + "be143934c933ae6dec0fb124f264af67eed7c9a8c38b6b8ee2614344bea73223e59bf0193432e9fa" + "4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44" + "64d210a256be75e0509c4477d19ac64b2e69220d12ea3b9501000000fb95e8332fdfff658483a2d0" + "39a7bf148ed3481e0bccc460e89f7abdb682380a62eae374835b4a49a2b980b6aba92da6409969aa" + "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359" + "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9bb0ec36f0000000064a2827b7cdd38d0314c178e" + "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" + "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226" + "d324d9a086ed27184b443181a5edc511c1507a142fea9bc10300000062fb81e733cff620ca7feefe" + "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" + "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911" + "4bdade862c224f6f36506ebd455e679cef369bb8d514573f03000000f6932f6932d1d5f5d0ce2cf6" + "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" + "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d" + "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a41e0f515601000000f57609453df7803357ae7998" + "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" + "ae8cb60b0300000038d856a40c67c3d4afa9c8649da90bd2fff2f256000000000000000000000000" + "00000001955e1a13d1111b067acbce3e3bcdf38200154d12010000009edfa7a74c1c83c18e47935e" + "8354846e34f0386a00000000000000000000000000000001ac26c7d41fd050bf8d85055bcfe3756c" + "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000" + "00000000020ffdb0e612098610e52bb2a16a40086f0e9e6903000000ec2e2924348352d715cf9d41" + "1ea012e5307294b600000000000000000000000000000000ccd2f50c30706cae3fdcc2f0ee3d5e26" + "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000" + "0000000000459582f4ef43c780908872746e39efaefd545b020000007ced4f8b362956cd46646a0e" + "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" + "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000" + "0000000069d9942f460bcea75481f25e307d0de96e91b91501000000be5b534e0a6527f67485ab35" + "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" + "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000" + "00000000b49185ad9b7d0070a36dd51323b2c542e5fe7d360100000066a3ae3939762df33a2d5506" + "0c78d551cbb110fd000000000000000000000000000000002c171ed15abbbe1cd911db7b56e8f3fe" + "9a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7246f13b2050424a2000000000000000000000000" + "00000000ffe9d6812231bb02f922259b173c333cbae87d60000000005d31e5b2de252167c1c91b3a" + "36ba0c700ee78477000000000000000000000000000000006ad0143a0554efb46b382ab0404cdf02" + "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000" + "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8" + "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" + "7666c05303000000ffa8e89871fb9510b900b2061d0c334b819f2dd1000000000000000000000000" + "00000000095a3230fde69eec3af2e6d0bd68ab7210613fc90200000016a31dc2e46a234558817151" + "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" + "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000" + "00000000b314f695bd82e9ea8891ed0a3d1b91cab56e03e0010000002f70249eefc67bce716c856e" + "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1" + "eecc89f601000000d635edea8ffe423d01883918039249f398f9b37e000000000000000000000000" + "000000001fb7c8307f06b4b29088f20d9ac676d5f90e54b501000000a779f37c30d2c5053c40ecae" + "210aeb0934cb2a2400000000000000000000000000000000df48f333ef467092818aa77d6732b678" + "bcd7be0700000000e45aaf61814f703b40125e6baf4648cbaaa37b86000000000000000000000000" + "000000005ddb05f2a84e27c18a06e2c9cb29efdf50da49bf00000000d94beb259f9f0251becc9879" + "07879cca68fec7bb000000000000000000000000000000009402a4c2167721673f2b02b3256ead1f" + "a349e1cc00000000b879a45176740744fcb6a035339d504c9726d80d000000000000000000000000" + "000000009518862bc9a89192c1c8be55281a59d1ebfdcec30000000067a982be8a934f852cc3d4d8" + "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" + "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000" + "00000002e6fbf952902383028e3b47f2111d891d536c75bb01000000720da9e07ac998b5690807d5" + "2617369ee1af4ca500000000000000000000ffff47d7b351a36b178aabc78a4a0d80684ee5dbf45b" + "17a4763102000000f9119c40b468b66331bca67a034f43340d01683c00000000000000000000ffff" + "b24a5be9b10123e6e4f15ecd1dff045298cfee069c88b02a0300000004b0595daf37deb499996bfb" + "667f072dec1e5d9cdc8a11f4409bcfb3c167090e99d90a8543961b2ccd47724a3c460ba85183f4c5" + "a7afe28302000000d05ff720b16c73761a3fcb675219061ab4c5c79489b2cc6a883c146972decb8b" + "5adac8f5e6d66df46ea139107754dee62c36d2fcc7a4c65601000000cd625009a40aeb62a42b6a62" + "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" + "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599" + "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b21cdb3455c00000000c66af76e80f062ea1a7e0b7b" + "e218d067530e1b0487b8c3b99f2b8a1a8982c42f53700a3437c5156e072b2f2fb337c9cfe07c34dd" + "c896c9a7000000000a5f6abd850b06e3d9662795ce2cc1cee06302aba042aaa218dc091e9aa1477f" + "6fdc9830d7fbc95829a8838314dff34d24c332214d4647f5000000000f88e3759a08e7a56663861e" + "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" + "7625ca4a00000000e682f80f94315c45ef817264c89a736ed55ed637b077ddad3108be69f9b97d05" + "c917ad6b10e693bb6e26f2ba90c8e909e85e20e5b0916e5d030000004a503a712350acbd48411f0d" + "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" + "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e" + "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c" + "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620" + "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2" + "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" + "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9" + "4d88189c471a1ff2f0ce3ff66e782110125ae2eddaae7d6300000000c0982b283aa9986700b2a2b3" + "ed257b8b0489f48f053ec8cac72105b327335a25a364d1015ffac03089f45539e1b0178462156cd6" + "6855676c00000000017c9148da5892bb4951c3a7ed55689d3391ce7d3fd48469845f0c233dbdd2a9" + "7835df1f1782dee88487fd0db5971b46b7a350f998c39e7c00000000efc57ff447036b9551adcb22" + "fd50793f797a3c7dadd1c86e759d0c90bc512e137dcef5e4a27985bd8d1e69c83dc21056b973972c" + "bc51e540030000006c3d048a92d3adc69a84eb47622400207799416afef0a086fbd7e2f7dea0077a" + "e9c0c0d9c386e9c6e6a2cbfa10ee58bdc75183600422ae3f03000000c43bd794c697895e5bfe47c6" + "f53a54e01b0c1d89fecd94d0e02d2ec587fc330003781b0f294a2b73c4421398f4de67e9cee64b38" + "69121aec010000000fcc00ac2daa755e5292cd32dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51" + "bbce426cfa4b861cc78592be7b14e7ba9c15acb836674cde0200000054cfe8f42bf0e9381ba2c439" + "6de60f032bc7f34dfe959871c0d4c0d4eb720c4ae3c9472e5f2da5d9c5cfd9f2343b21362c19a092" + "b2cd3dbd01000000e958e48d2ab8b0313e7f8933e315130fa9a84c82feb83f6e70b1646d8026e9f1" + "704f1b16286ba2dabc7ef0820c91ed33ef60a8b5bcfe97e1000000007ad742d3d7320a4f880cf47f" + "5dd0cf69cb22840ffeb3fe7749509cb6752b2cee30b7e7736a0afc9879ea40e69710fc9f6e8e99cd" + "1dce2f83020000003a3efc240b9977e166bee737fe73670c439a644c000000000000000000000000" + "000000015e0dfe491d1ba96742c7b5e02b227122cf844ef501000000cd743f59bd14c89b5cfd5ce6" + "e82e7854152f2b700000000000000000000000000000000127e19f254ac9588319558041fc62ed56" + "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000" + "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f" + "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" + "0436242c03000000ee3fbc164632d4f28aa28c08f80dd50c6712dfb4000000000000000000000000" + "00000000078a806d329c9b008bbfc9723107f3f52af145480300000004265f6c72923e22594f3f79" + "e208ed2e2ebb07710000000000000000000000000000000039dd8f88152a58454d9ca9d20f45dfa7" + "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000" + "000000008ae21e371051852c972ea7954079884a9a1b163a030000000e2f4f911a0dd8c052ed6b13" + "e2815a1a37a52bdd00000000000000000000000000000000bd99fcf72909ac9e7a55299e9bb4fd53" + "9f3c2c8803000000f51f44e644d7cf1d06b2b115d882549e62c12fba000000000000000000000000" + "000000004fc812bd2f8a59d96d064126666befbbf257b044030000006a4c619f9037d7a754655354" + "c47cf0f551e967700000000000000000000000000000000050b8d10ab700cc3a7cf51be0403b654b" + "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000" + "00000000d538d34574c038404923e75d0e09e2fcfc1519de010000002545666937c22a3b6e9686dc" + "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" + "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000" + "00000000b883efebc09dd9d61966b7ae7412041dd7ac5f9901000000822a272bec4501a1e27acfee" + "7a8588ffd5a06cae0000000000000000000000000000000077a47579dda0b6ead1e1b34901eaedd5" + "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000" + "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096" + "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" + "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000" + "000000005b29a197b7b3cceaf5f1bb12c535256a74993ade03000000e62112898dab2dade2ab2fc9" + "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" + "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000" + "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050" + "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f" + "bc74179403000000438a72e12ae0436a2495a609675344f7e2e3a5eb000000000000000000000000" + "0000000061eda239d9d083c3bf085387046ef8a34153e174020000004d89c0bb5408c1b7d17fb084" + "d9e1825fa638e1af000000000000000000000000000000006e08cb887464b9344ec3127c750fabdd" + "6c0fc09c02000000809829af4a9df58dbfef186d416f3a1ef170d10f000000000000000000000000" + "0000000087780281d47a32f2235376239daeaacba9a89f8701000000fcdf6d9be94030b34774d1d7" + "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" + "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000" + "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc" + "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" + "b7f0318a01000000061db3dd7fde25654a4059d565dbc8a91e3b4457000000000000000000000000" + "00000000c1b5aad487c192f08bd7a09bdd21444359747cf200000000ab2dadc5a39411fd4ff1116d" + "478987316a553fc2000000000000000000000000000000000819e3b10db116431ec6f7691539ce41" + "b95c593100000000dbe9962069e66142e22753344fda8a3e0b841cf7000000000000000000000000" + "000000008c54dda9ac3bb1b1d43e6505621b9a7f672d2fa501000000e276c5661a64192db44ce7af" + "5eb888e9eb37bb0400000000000000000000000000000002641e447514ca565fb9b68c08a5e4351e" + "9f3c39f201000000de745cb25851429b3bbfb50168dfd04edf6b3542000000000000000000000000" + "0000000218f93e742d08f0550b55726f2292362e70ccc56700000000a4c73cf5ffa4ffc8a4bab148" + "74afdf54e6aae8160000000000000000000000000000000268baf76ab08940f6fc3bbdc7f6090f75" + "4f1b134803000000449a774929e86716ec852d59f3d17232edd86ad6000000000000000000000000" + "000000027dba1ee7e143fd52599364e13468f80f40b26f6603000000badfad0fe8fa8f3c1aad2a82" + "530b7447d9c2f401000000000000000000000000000000028147507e1cd59ea1ae6da48b1eba6d16" + "dedea2030100000002a1f8e6f5657f3f9e3eb807cbad76451055edb8000000000000000000000000" + "00000002d9279fb2b8fcbac6abea74f7a6df7979f6989d2d000000006ff7add5df2c93e05459507b" + "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354" + ), + [2] = ( + "4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44" + "64d210a256be75e0509c4477d19ac64b2e69220d54270e46020000006a894e387625da376feecb80" + "ac245409c0becc271d9c2f67179bff0644399ae79c64ed0432d599eaa660ac824b7fae389861419c" + "12ea3b9501000000fb95e8332fdfff658483a2d039a7bf148ed3481e0bccc460e89f7abdb682380a" + "62eae374835b4a49a2b980b6aba92da6409969aa7a899f2d010000009bf5a5d06776e66a9d80ab13" + "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" + "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359" + "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9c4e1966800000000b3121cd5ef51e696c816290d" + "baee0e7726d082e1530ff5397c9125f59577d71c4b258a005116d11354edff62ceaa458fc75a91c4" + "25a5927300000000c4458d70911714f1819aa46fbe143934c933ae6dec0fb124f264af67eed7c9a8" + "c38b6b8ee2614344bea73223e59bf0193432e9fa2fea9bc10300000062fb81e733cff620ca7feefe" + "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" + "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911" + "4bdade862c224f6f36506ebd455e679cef369bb8bb0ec36f0000000064a2827b7cdd38d0314c178e" + "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" + "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226" + "d324d9a086ed27184b443181a5edc511c1507a14d514573f03000000f6932f6932d1d5f5d0ce2cf6" + "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" + "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d" + "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a4ae8cb60b0300000038d856a40c67c3d4afa9c864" + "9da90bd2fff2f25600000000000000000000000000000001955e1a13d1111b067acbce3e3bcdf382" + "00154d12010000009edfa7a74c1c83c18e47935e8354846e34f0386a000000000000000000000000" + "00000001ac26c7d41fd050bf8d85055bcfe3756c1e0f515601000000f57609453df7803357ae7998" + "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" + "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000" + "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8" + "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" + "6f0e9e6903000000ec2e2924348352d715cf9d411ea012e5307294b6000000000000000000000000" + "00000000ccd2f50c30706cae3fdcc2f0ee3d5e267666c05303000000ffa8e89871fb9510b900b206" + "1d0c334b819f2dd100000000000000000000000000000000095a3230fde69eec3af2e6d0bd68ab72" + "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000" + "0000000000459582f4ef43c780908872746e39ef10613fc90200000016a31dc2e46a234558817151" + "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" + "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000" + "00000000b314f695bd82e9ea8891ed0a3d1b91ca6e91b91501000000be5b534e0a6527f67485ab35" + "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" + "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000" + "00000000b49185ad9b7d0070a36dd51323b2c542b56e03e0010000002f70249eefc67bce716c856e" + "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1" + "e5fe7d360100000066a3ae3939762df33a2d55060c78d551cbb110fd000000000000000000000000" + "000000002c171ed15abbbe1cd911db7b56e8f3feeecc89f601000000d635edea8ffe423d01883918" + "039249f398f9b37e000000000000000000000000000000001fb7c8307f06b4b29088f20d9ac676d5" + "f90e54b501000000a779f37c30d2c5053c40ecae210aeb0934cb2a24000000000000000000000000" + "00000000df48f333ef467092818aa77d6732b678bcd7be0700000000e45aaf61814f703b40125e6b" + "af4648cbaaa37b86000000000000000000000000000000005ddb05f2a84e27c18a06e2c9cb29efdf" + "50da49bf00000000d94beb259f9f0251becc987907879cca68fec7bb000000000000000000000000" + "000000009402a4c2167721673f2b02b3256ead1fa349e1cc00000000b879a45176740744fcb6a035" + "339d504c9726d80d000000000000000000000000000000009518862bc9a89192c1c8be55281a59d1" + "bae87d60000000005d31e5b2de252167c1c91b3a36ba0c700ee78477000000000000000000000000" + "000000006ad0143a0554efb46b382ab0404cdf02ebfdcec30000000067a982be8a934f852cc3d4d8" + "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" + "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000" + "00000000020ffdb0e612098610e52bb2a16a4008aefd545b020000007ced4f8b362956cd46646a0e" + "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" + "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000" + "0000000069d9942f460bcea75481f25e307d0de99a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7" + "246f13b2050424a200000000000000000000000000000000ffe9d6812231bb02f922259b173c333c" + "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000" + "00000002e6fbf952902383028e3b47f2111d891d17a4763102000000f9119c40b468b66331bca67a" + "034f43340d01683c00000000000000000000ffffb24a5be9b10123e6e4f15ecd1dff045298cfee06" + "536c75bb01000000720da9e07ac998b5690807d52617369ee1af4ca500000000000000000000ffff" + "47d7b351a36b178aabc78a4a0d80684ee5dbf45bb0916e5d030000004a503a712350acbd48411f0d" + "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" + "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e" + "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c" + "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620" + "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2" + "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" + "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9" + "4d88189c471a1ff2f0ce3ff66e782110125ae2edc7a4c65601000000cd625009a40aeb62a42b6a62" + "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" + "daae7d6300000000c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8cac72105b327335a25" + "a364d1015ffac03089f45539e1b0178462156cd66855676c00000000017c9148da5892bb4951c3a7" + "ed55689d3391ce7d3fd48469845f0c233dbdd2a97835df1f1782dee88487fd0db5971b46b7a350f9" + "cdb3455c00000000c66af76e80f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a8982c42f" + "53700a3437c5156e072b2f2fb337c9cfe07c34ddc896c9a7000000000a5f6abd850b06e3d9662795" + "ce2cc1cee06302aba042aaa218dc091e9aa1477f6fdc9830d7fbc95829a8838314dff34d24c33221" + "98c39e7c00000000efc57ff447036b9551adcb22fd50793f797a3c7dadd1c86e759d0c90bc512e13" + "7dcef5e4a27985bd8d1e69c83dc21056b973972c7625ca4a00000000e682f80f94315c45ef817264" + "c89a736ed55ed637b077ddad3108be69f9b97d05c917ad6b10e693bb6e26f2ba90c8e909e85e20e5" + "9c88b02a0300000004b0595daf37deb499996bfb667f072dec1e5d9cdc8a11f4409bcfb3c167090e" + "99d90a8543961b2ccd47724a3c460ba85183f4c5a7afe28302000000d05ff720b16c73761a3fcb67" + "5219061ab4c5c79489b2cc6a883c146972decb8b5adac8f5e6d66df46ea139107754dee62c36d2fc" + "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599" + "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b214d4647f5000000000f88e3759a08e7a56663861e" + "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" + "0422ae3f03000000c43bd794c697895e5bfe47c6f53a54e01b0c1d89fecd94d0e02d2ec587fc3300" + "03781b0f294a2b73c4421398f4de67e9cee64b38bc51e540030000006c3d048a92d3adc69a84eb47" + "622400207799416afef0a086fbd7e2f7dea0077ae9c0c0d9c386e9c6e6a2cbfa10ee58bdc7518360" + "36674cde0200000054cfe8f42bf0e9381ba2c4396de60f032bc7f34dfe959871c0d4c0d4eb720c4a" + "e3c9472e5f2da5d9c5cfd9f2343b21362c19a092b2cd3dbd01000000e958e48d2ab8b0313e7f8933" + "e315130fa9a84c82feb83f6e70b1646d8026e9f1704f1b16286ba2dabc7ef0820c91ed33ef60a8b5" + "bcfe97e1000000007ad742d3d7320a4f880cf47f5dd0cf69cb22840ffeb3fe7749509cb6752b2cee" + "30b7e7736a0afc9879ea40e69710fc9f6e8e99cd69121aec010000000fcc00ac2daa755e5292cd32" + "dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51bbce426cfa4b861cc78592be7b14e7ba9c15acb8" + "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000" + "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f" + "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" + "cf844ef501000000cd743f59bd14c89b5cfd5ce6e82e7854152f2b70000000000000000000000000" + "0000000127e19f254ac9588319558041fc62ed561dce2f83020000003a3efc240b9977e166bee737" + "fe73670c439a644c000000000000000000000000000000015e0dfe491d1ba96742c7b5e02b227122" + "2af145480300000004265f6c72923e22594f3f79e208ed2e2ebb0771000000000000000000000000" + "0000000039dd8f88152a58454d9ca9d20f45dfa774993ade03000000e62112898dab2dade2ab2fc9" + "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" + "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000" + "000000008ae21e371051852c972ea7954079884a9f3c2c8803000000f51f44e644d7cf1d06b2b115" + "d882549e62c12fba000000000000000000000000000000004fc812bd2f8a59d96d064126666befbb" + "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000" + "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050" + "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f" + "f257b044030000006a4c619f9037d7a754655354c47cf0f551e96770000000000000000000000000" + "0000000050b8d10ab700cc3a7cf51be0403b654bbc74179403000000438a72e12ae0436a2495a609" + "675344f7e2e3a5eb0000000000000000000000000000000061eda239d9d083c3bf085387046ef8a3" + "4153e174020000004d89c0bb5408c1b7d17fb084d9e1825fa638e1af000000000000000000000000" + "000000006e08cb887464b9344ec3127c750fabdd6c0fc09c02000000809829af4a9df58dbfef186d" + "416f3a1ef170d10f0000000000000000000000000000000087780281d47a32f2235376239daeaacb" + "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000" + "00000000d538d34574c038404923e75d0e09e2fca9a89f8701000000fcdf6d9be94030b34774d1d7" + "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" + "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000" + "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc" + "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" + "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000" + "00000000b883efebc09dd9d61966b7ae7412041db7f0318a01000000061db3dd7fde25654a4059d5" + "65dbc8a91e3b445700000000000000000000000000000000c1b5aad487c192f08bd7a09bdd214443" + "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000" + "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096" + "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" + "59747cf200000000ab2dadc5a39411fd4ff1116d478987316a553fc2000000000000000000000000" + "000000000819e3b10db116431ec6f7691539ce41b95c593100000000dbe9962069e66142e2275334" + "4fda8a3e0b841cf7000000000000000000000000000000008c54dda9ac3bb1b1d43e6505621b9a7f" + "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000" + "000000005b29a197b7b3cceaf5f1bb12c535256a0436242c03000000ee3fbc164632d4f28aa28c08" + "f80dd50c6712dfb400000000000000000000000000000000078a806d329c9b008bbfc9723107f3f5" + "9a1b163a030000000e2f4f911a0dd8c052ed6b13e2815a1a37a52bdd000000000000000000000000" + "00000000bd99fcf72909ac9e7a55299e9bb4fd53fc1519de010000002545666937c22a3b6e9686dc" + "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" + "d7ac5f9901000000822a272bec4501a1e27acfee7a8588ffd5a06cae000000000000000000000000" + "0000000077a47579dda0b6ead1e1b34901eaedd54f1b134803000000449a774929e86716ec852d59" + "f3d17232edd86ad6000000000000000000000000000000027dba1ee7e143fd52599364e13468f80f" + "40b26f6603000000badfad0fe8fa8f3c1aad2a82530b7447d9c2f401000000000000000000000000" + "000000028147507e1cd59ea1ae6da48b1eba6d16dedea2030100000002a1f8e6f5657f3f9e3eb807" + "cbad76451055edb800000000000000000000000000000002d9279fb2b8fcbac6abea74f7a6df7979" + "672d2fa501000000e276c5661a64192db44ce7af5eb888e9eb37bb04000000000000000000000000" + "00000002641e447514ca565fb9b68c08a5e4351e9f3c39f201000000de745cb25851429b3bbfb501" + "68dfd04edf6b35420000000000000000000000000000000218f93e742d08f0550b55726f2292362e" + "70ccc56700000000a4c73cf5ffa4ffc8a4bab14874afdf54e6aae816000000000000000000000000" + "0000000268baf76ab08940f6fc3bbdc7f6090f75f6989d2d000000006ff7add5df2c93e05459507b" + "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354" + ), + }; + const int TEST_DATA_I = GPOINTER_TO_INT (test_data); + const int addr_family = (TEST_DATA_I == 0 ? AF_INET : AF_INET6); + const int IPV6_PREFER_TEMP = (TEST_DATA_I == 2); + const guint N_ADDRESSES = 100; + const gsize ELM_SIZE = addr_family == AF_INET + ? sizeof (NMPlatformIP4Address) + : sizeof (NMPlatformIP6Address); + const gboolean DO_REGENERATE = FALSE; + const gboolean PRINT_RESULT = DO_REGENERATE; + const gboolean CHECK_RESULT = !DO_REGENERATE; + gs_free guint8 *addresses = NULL; + gs_free guint64 *rand_map = NULL; + gsize i, j; + + /* + * First we create a list of addresses filled with (stable) random bytes. + * We tweak some fields explicitly (stable randomly), so that we cover all + * relevant cases. + * + * Then we sort the list of addresses, and compare that the result is + * as our EXPECTED_BUFFER. + */ + + addresses = g_malloc (ELM_SIZE * N_ADDRESSES); + rand_map = g_malloc (sizeof (rand_map[0]) * N_ADDRESSES); + nmtst_stable_rand (258829693, addresses, ELM_SIZE * N_ADDRESSES); + nmtst_stable_rand (710086081, rand_map, sizeof (rand_map[0]) * N_ADDRESSES); + + for (i = 0; i < N_ADDRESSES; i++) { + NMPlatformIPXAddress *a = (gpointer) (&addresses[i * ELM_SIZE]); + guint64 r = rand_map[i]; + struct in6_addr *a6; + +#define CONSUME_BITS(r, nbits) \ + ({ \ + guint64 _r = (r); \ + const int _nbits = (nbits); \ + \ + r >>= (_nbits); \ + (_r & (((((guint64) 1u) << (_nbits)) - 1u))); \ + }) + + if (addr_family == AF_INET) { + if (CONSUME_BITS (r, 1)) { + /* randomly create a link-local address or not. */ + g_assert ((NM_IPV4LL_NETWORK & ~NM_IPV4LL_NETMASK) == 0); + a->a4.address = (a->a4.address & ~NM_IPV4LL_NETMASK) + | NM_IPV4LL_NETWORK; + } + } else { + a6 = &a->a6.address; + switch (CONSUME_BITS (r, 4)) { + case 0: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = htonl (0xffff); + g_assert (IN6_IS_ADDR_V4MAPPED (a6)); + break; + case 1: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = 0; + a6->s6_addr32[3] = htonl (2); + g_assert (IN6_IS_ADDR_V4COMPAT (a6)); + break; + case 2: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = 0; + a6->s6_addr32[3] = 0; + g_assert (IN6_IS_ADDR_UNSPECIFIED (a6)); + break; + case 3: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = 0; + a6->s6_addr32[3] = htonl (1); + g_assert (IN6_IS_ADDR_LOOPBACK (a6)); + break; + case 4: + a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl (0xffc00000)) + | htonl (0xfe800000); + g_assert (IN6_IS_ADDR_LINKLOCAL (a6)); + break; + case 6: + a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl (0xffc00000)) + | htonl (0xfec00000); + g_assert (IN6_IS_ADDR_SITELOCAL (a6)); + break; + case 7: + case 8: + case 9: + case 10: + break; + default: + memset (a6, 0, sizeof (*a6)); + break; + } + } + + if (CONSUME_BITS (r, 5) != 0) { + /* randomly make addr-source the same (so that several addresses compare + * equal). */ + a->a4.addr_source = CONSUME_BITS (r, 2); + } + + if (addr_family == AF_INET) { + if (CONSUME_BITS (r, 1)) { + /* randomly make the label empty or not. */ + a->a4.label[0] = '\0'; + } + } + if (addr_family == AF_INET) { + if (CONSUME_BITS (r, 2) != 0) { + /* randomly make the label empty or not. */ + a->a4.plen = CONSUME_BITS (r, 2); + } + } + if (addr_family == AF_INET) { + if (CONSUME_BITS (r, 1)) { + a->a4.address = (a->a4.address & ~0xFFFFFFu) + | (CONSUME_BITS (r, 2) << 24); + } + } + } + + g_qsort_with_data (addresses, + N_ADDRESSES, + ELM_SIZE, + _address_pretty_sort_cmp, + (gpointer) test_data); + + for (i = 0; i < N_ADDRESSES; i++) { + const NMPlatformIPXAddress *a = (gconstpointer) (&addresses[i * ELM_SIZE]); + + for (j = i + 1; j < N_ADDRESSES; j++) { + const NMPlatformIPXAddress *b = (gconstpointer) (&addresses[j * ELM_SIZE]); + int c1; + int c2; + int c3; + int c4; + + if (addr_family == AF_INET) { + c1 = nm_platform_ip4_address_pretty_sort_cmp (&a->a4, &b->a4); + c2 = nm_platform_ip4_address_pretty_sort_cmp (&b->a4, &a->a4); + c3 = nmtst_ip4_config_addresses_sort_cmp (&a->a4, &b->a4); + c4 = nmtst_ip4_config_addresses_sort_cmp (&b->a4, &a->a4); + } else { + c1 = nm_platform_ip6_address_pretty_sort_cmp (&a->a6, &b->a6, IPV6_PREFER_TEMP); + c2 = nm_platform_ip6_address_pretty_sort_cmp (&b->a6, &a->a6, IPV6_PREFER_TEMP); + c3 = nmtst_ip6_config_addresses_sort_cmp (&a->a6, &b->a6, IPV6_PREFER_TEMP); + c4 = nmtst_ip6_config_addresses_sort_cmp (&b->a6, &a->a6, IPV6_PREFER_TEMP); + } + +#define _NORM(c) (((c) < 0) ? -1 : ((c) > 0)) + g_assert_cmpint (_NORM (c1), >=, -1); + g_assert_cmpint (_NORM (c1), <=, 1); + g_assert_cmpint (_NORM (c1), ==, -_NORM (c2)); + g_assert_cmpint (_NORM (c1), ==, _NORM (c3)); + g_assert_cmpint (_NORM (c1), ==, -_NORM (c4)); + } + } + + if (PRINT_RESULT) { + g_print ("\n\n\t\t[%d] = (\n", TEST_DATA_I); + for (i = 0; i < ELM_SIZE * N_ADDRESSES; ) { + g_print ("\t\t\t\""); + for (j = 0; j < 40 && i < ELM_SIZE * N_ADDRESSES; j++, i++) + g_print ("%02x", addresses[i]); + g_print ("\"\n"); + } + g_print ("\t\t),\n\n"); + return; + } + + if (CHECK_RESULT) { + gs_free guint8 *bin_arr = NULL; + gsize bin_len; + + bin_arr = nm_utils_hexstr2bin_alloc (EXPECTED_BUFFER[TEST_DATA_I], FALSE, FALSE, NULL, 0, &bin_len); + g_assert_cmpmem (addresses, ELM_SIZE * N_ADDRESSES, bin_arr, bin_len); + } +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -72,6 +727,9 @@ main (int argc, char **argv) g_test_add_func ("/general/init_linux_platform", test_init_linux_platform); g_test_add_func ("/general/link_get_all", test_link_get_all); g_test_add_func ("/general/nm_platform_link_flags2str", test_nm_platform_link_flags2str); + g_test_add_data_func ("/general/platform_ip_address_pretty_sort_cmp/4", GINT_TO_POINTER (0), test_platform_ip_address_pretty_sort_cmp); + g_test_add_data_func ("/general/platform_ip_address_pretty_sort_cmp/6/1", GINT_TO_POINTER (1), test_platform_ip_address_pretty_sort_cmp); + g_test_add_data_func ("/general/platform_ip_address_pretty_sort_cmp/6/2", GINT_TO_POINTER (2), test_platform_ip_address_pretty_sort_cmp); return g_test_run (); } From 83bc1e8d608e62ea2a602e6f0441fdfdd8e55eba Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 22:19:43 +0200 Subject: [PATCH 09/16] platform: use NM_CMP_*() macros in nm_platform_ip[46]_address_pretty_sort_cmp() They ensure to consistently return -1, 0, 1. Also, I think they are easier to understand. What is in general hard to understand, whether a comparison sorts ascending or descending. The macros maybe make that easier too, but it's still confusing. That's why we have a test. --- src/platform/nm-platform.c | 65 ++++++++-------------- src/platform/tests/test-platform-general.c | 10 ++-- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 0ab2c52b33..7b1f87f189 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -7216,25 +7216,20 @@ nm_platform_ip4_address_pretty_sort_cmp (const NMPlatformIP4Address *a1, { in_addr_t n1; in_addr_t n2; - int p1; - int p2; nm_assert (a1); nm_assert (a2); /* Sort by address type. For example link local will * be sorted *after* a global address. */ - p1 = _address_pretty_sort_get_prio_4 (a1->address); - p2 = _address_pretty_sort_get_prio_4 (a2->address); - if (p1 != p2) - return p1 > p2 ? -1 : 1; + NM_CMP_DIRECT (_address_pretty_sort_get_prio_4 (a2->address), + _address_pretty_sort_get_prio_4 (a1->address)); /* Sort the addresses based on their source. */ - if (a1->addr_source != a2->addr_source) - return a1->addr_source > a2->addr_source ? -1 : 1; + NM_CMP_DIRECT (a2->addr_source, a1->addr_source); - if ((a1->label[0] == '\0') != (a2->label[0] == '\0')) - return (a1->label[0] == '\0') ? -1 : 1; + NM_CMP_DIRECT ((a2->label[0] == '\0'), + (a1->label[0] == '\0')); /* Finally, sort addresses lexically. We compare only the * network part so that the order of addresses in the same @@ -7243,8 +7238,8 @@ nm_platform_ip4_address_pretty_sort_cmp (const NMPlatformIP4Address *a1, */ n1 = a1->address & _nm_utils_ip4_prefix_to_netmask (a1->plen); n2 = a2->address & _nm_utils_ip4_prefix_to_netmask (a2->plen); - - return memcmp (&n1, &n2, sizeof (guint32)); + NM_CMP_DIRECT_MEMCMP (&n1, &n2, sizeof (guint32)); + return 0; } static int @@ -7272,35 +7267,26 @@ nm_platform_ip6_address_pretty_sort_cmp (const NMPlatformIP6Address *a1, { gboolean ipv6_privacy1; gboolean ipv6_privacy2; - gboolean perm1; - gboolean perm2; - gboolean tent1; - gboolean tent2; - int p1; - int p2; - int c; nm_assert (a1); nm_assert (a2); /* tentative addresses are always sorted back... */ /* sort tentative addresses after non-tentative. */ - tent1 = (a1->n_ifa_flags & IFA_F_TENTATIVE); - tent2 = (a2->n_ifa_flags & IFA_F_TENTATIVE); - if (tent1 != tent2) - return tent1 ? 1 : -1; + NM_CMP_DIRECT (NM_FLAGS_HAS (a1->n_ifa_flags, IFA_F_TENTATIVE), + NM_FLAGS_HAS (a2->n_ifa_flags, IFA_F_TENTATIVE)); /* Sort by address type. For example link local will * be sorted *after* site local or global. */ - p1 = _address_pretty_sort_get_prio_6 (&a1->address); - p2 = _address_pretty_sort_get_prio_6 (&a2->address); - if (p1 != p2) - return p1 > p2 ? -1 : 1; + NM_CMP_DIRECT (_address_pretty_sort_get_prio_6 (&a2->address), + _address_pretty_sort_get_prio_6 (&a1->address)); - ipv6_privacy1 = !!(a1->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); - ipv6_privacy2 = !!(a2->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); - if (ipv6_privacy1 || ipv6_privacy2) { - gboolean public1 = TRUE, public2 = TRUE; + ipv6_privacy1 = NM_FLAGS_ANY (a1->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY); + ipv6_privacy2 = NM_FLAGS_ANY (a2->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY); + if ( ipv6_privacy1 + || ipv6_privacy2) { + gboolean public1 = TRUE; + gboolean public2 = TRUE; if (ipv6_privacy1) { if (a1->n_ifa_flags & IFA_F_TEMPORARY) @@ -7315,23 +7301,20 @@ nm_platform_ip6_address_pretty_sort_cmp (const NMPlatformIP6Address *a1, public2 = !prefer_temp; } - if (public1 != public2) - return public1 ? -1 : 1; + NM_CMP_DIRECT (public2, public1); } /* Sort the addresses based on their source. */ - if (a1->addr_source != a2->addr_source) - return a1->addr_source > a2->addr_source ? -1 : 1; + NM_CMP_DIRECT (a2->addr_source, a1->addr_source); /* sort permanent addresses before non-permanent. */ - perm1 = (a1->n_ifa_flags & IFA_F_PERMANENT); - perm2 = (a2->n_ifa_flags & IFA_F_PERMANENT); - if (perm1 != perm2) - return perm1 ? -1 : 1; + NM_CMP_DIRECT (NM_FLAGS_HAS (a2->n_ifa_flags, IFA_F_PERMANENT), + NM_FLAGS_HAS (a1->n_ifa_flags, IFA_F_PERMANENT)); /* finally sort addresses lexically */ - c = memcmp (&a1->address, &a2->address, sizeof (a2->address)); - return c != 0 ? c : memcmp (a1, a2, sizeof (*a1)); + NM_CMP_DIRECT_IN6ADDR (&a1->address, &a2->address); + NM_CMP_DIRECT_MEMCMP (a1, a2, sizeof (*a1)); + return 0; } void diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c index a5efdb399e..4991eda9e9 100644 --- a/src/platform/tests/test-platform-general.c +++ b/src/platform/tests/test-platform-general.c @@ -686,11 +686,11 @@ test_platform_ip_address_pretty_sort_cmp (gconstpointer test_data) } #define _NORM(c) (((c) < 0) ? -1 : ((c) > 0)) - g_assert_cmpint (_NORM (c1), >=, -1); - g_assert_cmpint (_NORM (c1), <=, 1); - g_assert_cmpint (_NORM (c1), ==, -_NORM (c2)); - g_assert_cmpint (_NORM (c1), ==, _NORM (c3)); - g_assert_cmpint (_NORM (c1), ==, -_NORM (c4)); + g_assert_cmpint (c1, >=, -1); + g_assert_cmpint (c1, <=, 1); + g_assert_cmpint (c1, ==, -c2); + g_assert_cmpint (c1, ==, _NORM (c3)); + g_assert_cmpint (c1, ==, -_NORM (c4)); } } From 67bfcb49c9b217b60c3ca1e37144d4846e341fcd Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 15:40:45 +0200 Subject: [PATCH 10/16] core: use nm_platform_ip[46]_address_pretty_sort_cmp() in "nm-ip[46]-config.c" --- src/nm-ip4-config.c | 56 +---------- src/nm-ip4-config.h | 2 - src/nm-ip6-config.c | 103 ++------------------- src/nm-ip6-config.h | 2 - src/platform/tests/test-platform-general.c | 10 -- 5 files changed, 8 insertions(+), 165 deletions(-) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index c247ffc92a..0f5bd5c1a9 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -505,63 +505,11 @@ _notify_routes (NMIP4Config *self) /*****************************************************************************/ -static int -_addresses_sort_cmp_get_prio (in_addr_t addr) -{ - if (nm_utils_ip4_address_is_link_local (addr)) - return 0; - return 1; -} - static int _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data) { - int p1, p2; - const NMPlatformIP4Address *a1 = NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) a)); - const NMPlatformIP4Address *a2 = NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) b)); - guint32 n1, n2; - - nm_assert (a1); - nm_assert (a2); - - /* Sort by address type. For example link local will - * be sorted *after* a global address. */ - p1 = _addresses_sort_cmp_get_prio (a1->address); - p2 = _addresses_sort_cmp_get_prio (a2->address); - if (p1 != p2) - return p1 > p2 ? -1 : 1; - - /* Sort the addresses based on their source. */ - if (a1->addr_source != a2->addr_source) - return a1->addr_source > a2->addr_source ? -1 : 1; - - if ((a1->label[0] == '\0') != (a2->label[0] == '\0')) - return (a1->label[0] == '\0') ? -1 : 1; - - /* Finally, sort addresses lexically. We compare only the - * network part so that the order of addresses in the same - * subnet (and thus also the primary/secondary role) is - * preserved. - */ - n1 = a1->address & _nm_utils_ip4_prefix_to_netmask (a1->plen); - n2 = a2->address & _nm_utils_ip4_prefix_to_netmask (a2->plen); - - return memcmp (&n1, &n2, sizeof (guint32)); -} - -int -nmtst_ip4_config_addresses_sort_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) -{ - NMPObject o_a; - NMPObject o_b; - NMPObject *p_o_a = &o_a; - NMPObject *p_o_b = &o_b; - - g_assert (a); - g_assert (b); - nmp_object_stackinit (&o_a, NMP_OBJECT_TYPE_IP4_ADDRESS, a); - nmp_object_stackinit (&o_b, NMP_OBJECT_TYPE_IP4_ADDRESS, b); - return _addresses_sort_cmp (&p_o_a, &p_o_b, NULL); + return nm_platform_ip4_address_pretty_sort_cmp (NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) a)), + NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) b))); } /*****************************************************************************/ diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 0d1a67b1bf..f1c4a57e85 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -603,6 +603,4 @@ nm_ip_config_intersect_alloc (const NMIPConfig *a, } } -int nmtst_ip4_config_addresses_sort_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); - #endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index cfe63431f0..ab7edf8424 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -212,111 +212,20 @@ _notify_routes (NMIP6Config *self) /*****************************************************************************/ -static int -_addresses_sort_cmp_get_prio (const struct in6_addr *addr) -{ - if (IN6_IS_ADDR_V4MAPPED (addr)) - return 0; - if (IN6_IS_ADDR_V4COMPAT (addr)) - return 1; - if (IN6_IS_ADDR_UNSPECIFIED (addr)) - return 2; - if (IN6_IS_ADDR_LOOPBACK (addr)) - return 3; - if (IN6_IS_ADDR_LINKLOCAL (addr)) - return 4; - if (IN6_IS_ADDR_SITELOCAL (addr)) - return 5; - return 6; -} - -static int -_addresses_sort_cmp (const NMPlatformIP6Address *a1, - const NMPlatformIP6Address *a2, - gboolean prefer_temp) -{ - int p1, p2, c; - gboolean perm1, perm2, tent1, tent2; - gboolean ipv6_privacy1, ipv6_privacy2; - - /* tentative addresses are always sorted back... */ - /* sort tentative addresses after non-tentative. */ - tent1 = (a1->n_ifa_flags & IFA_F_TENTATIVE); - tent2 = (a2->n_ifa_flags & IFA_F_TENTATIVE); - if (tent1 != tent2) - return tent1 ? 1 : -1; - - /* Sort by address type. For example link local will - * be sorted *after* site local or global. */ - p1 = _addresses_sort_cmp_get_prio (&a1->address); - p2 = _addresses_sort_cmp_get_prio (&a2->address); - if (p1 != p2) - return p1 > p2 ? -1 : 1; - - ipv6_privacy1 = !!(a1->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); - ipv6_privacy2 = !!(a2->n_ifa_flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); - if (ipv6_privacy1 || ipv6_privacy2) { - gboolean public1 = TRUE, public2 = TRUE; - - if (ipv6_privacy1) { - if (a1->n_ifa_flags & IFA_F_TEMPORARY) - public1 = prefer_temp; - else - public1 = !prefer_temp; - } - if (ipv6_privacy2) { - if (a2->n_ifa_flags & IFA_F_TEMPORARY) - public2 = prefer_temp; - else - public2 = !prefer_temp; - } - - if (public1 != public2) - return public1 ? -1 : 1; - } - - /* Sort the addresses based on their source. */ - if (a1->addr_source != a2->addr_source) - return a1->addr_source > a2->addr_source ? -1 : 1; - - /* sort permanent addresses before non-permanent. */ - perm1 = (a1->n_ifa_flags & IFA_F_PERMANENT); - perm2 = (a2->n_ifa_flags & IFA_F_PERMANENT); - if (perm1 != perm2) - return perm1 ? -1 : 1; - - /* finally sort addresses lexically */ - c = memcmp (&a1->address, &a2->address, sizeof (a2->address)); - return c != 0 ? c : memcmp (a1, a2, sizeof (*a1)); -} - -int -nmtst_ip6_config_addresses_sort_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean prefer_temp) -{ - g_assert (a); - g_assert (b); - return _addresses_sort_cmp (a, b, prefer_temp); -} - static int _addresses_sort_cmp_prop (gconstpointer a, gconstpointer b, gpointer user_data) { - return _addresses_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); + 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) { - const NMPlatformIP6Address *addr_a = NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj); - const NMPlatformIP6Address *addr_b = NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_b, NMDedupMultiEntry, lst_entries)->obj); - - nm_assert (addr_a); - nm_assert (addr_b); - - return _addresses_sort_cmp (addr_a, addr_b, - ((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT (user_data)) == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); + return nm_platform_ip6_address_pretty_sort_cmp (NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj), + NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_b, NMDedupMultiEntry, lst_entries)->obj), + (((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT (user_data)) == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR)); } gboolean diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index ae1b8c0a46..4c21768ad8 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -220,6 +220,4 @@ void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self, void nm_ip6_config_update_routes_metric (NMIP6Config *self, gint64 metric); -int nmtst_ip6_config_addresses_sort_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean prefer_temp); - #endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */ diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c index 4991eda9e9..86ffdbedcf 100644 --- a/src/platform/tests/test-platform-general.c +++ b/src/platform/tests/test-platform-general.c @@ -9,7 +9,6 @@ #include "platform/nm-platform-utils.h" #include "platform/nm-linux-platform.h" -#include "nm-ip4-config.h" #include "nm-test-utils-core.h" @@ -670,27 +669,18 @@ test_platform_ip_address_pretty_sort_cmp (gconstpointer test_data) const NMPlatformIPXAddress *b = (gconstpointer) (&addresses[j * ELM_SIZE]); int c1; int c2; - int c3; - int c4; if (addr_family == AF_INET) { c1 = nm_platform_ip4_address_pretty_sort_cmp (&a->a4, &b->a4); c2 = nm_platform_ip4_address_pretty_sort_cmp (&b->a4, &a->a4); - c3 = nmtst_ip4_config_addresses_sort_cmp (&a->a4, &b->a4); - c4 = nmtst_ip4_config_addresses_sort_cmp (&b->a4, &a->a4); } else { c1 = nm_platform_ip6_address_pretty_sort_cmp (&a->a6, &b->a6, IPV6_PREFER_TEMP); c2 = nm_platform_ip6_address_pretty_sort_cmp (&b->a6, &a->a6, IPV6_PREFER_TEMP); - c3 = nmtst_ip6_config_addresses_sort_cmp (&a->a6, &b->a6, IPV6_PREFER_TEMP); - c4 = nmtst_ip6_config_addresses_sort_cmp (&b->a6, &a->a6, IPV6_PREFER_TEMP); } -#define _NORM(c) (((c) < 0) ? -1 : ((c) > 0)) g_assert_cmpint (c1, >=, -1); g_assert_cmpint (c1, <=, 1); g_assert_cmpint (c1, ==, -c2); - g_assert_cmpint (c1, ==, _NORM (c3)); - g_assert_cmpint (c1, ==, -_NORM (c4)); } } From b44f7dce40433032c95f280a92c0dc6e46f61546 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 12:19:15 +0200 Subject: [PATCH 11/16] core: add nm_platform_dedup_multi_iter_next_*() helpers to "nmp-object.h" This code is not specific to "nm-ip4-config.h"/"nm-ip6-config.h". It applies to everybody who wants to iterate over a dedup-multi-index of certain NMPObjects. Move it. --- src/nm-ip4-config.c | 8 +++---- src/nm-ip4-config.h | 26 ++-------------------- src/nm-ip6-config.c | 8 +++---- src/nm-ip6-config.h | 26 ++-------------------- src/platform/nmp-object.h | 46 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 56 deletions(-) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 0f5bd5c1a9..4a9026cdb3 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -1657,8 +1657,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev const NMPlatformIP4Address *r_src = NULL; const NMPlatformIP4Address *r_dst = NULL; - has = nm_ip_config_iter_ip4_address_next (&ipconf_iter_src, &r_src); - if (has != nm_ip_config_iter_ip4_address_next (&ipconf_iter_dst, &r_dst)) { + has = nm_platform_dedup_multi_iter_next_ip4_address (&ipconf_iter_src, &r_src); + if (has != nm_platform_dedup_multi_iter_next_ip4_address (&ipconf_iter_dst, &r_dst)) { are_equal = FALSE; has_relevant_changes = TRUE; break; @@ -1704,8 +1704,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev const NMPlatformIP4Route *r_src = NULL; const NMPlatformIP4Route *r_dst = NULL; - has = nm_ip_config_iter_ip4_route_next (&ipconf_iter_src, &r_src); - if (has != nm_ip_config_iter_ip4_route_next (&ipconf_iter_dst, &r_dst)) { + has = nm_platform_dedup_multi_iter_next_ip4_route (&ipconf_iter_src, &r_src); + if (has != nm_platform_dedup_multi_iter_next_ip4_route (&ipconf_iter_dst, &r_dst)) { are_equal = FALSE; has_relevant_changes = TRUE; break; diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index f1c4a57e85..04a0cfa5fe 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -35,36 +35,14 @@ void nm_ip_config_dedup_multi_idx_type_init (NMIPConfigDedupMultiIdxType *idx_ty void nm_ip_config_iter_ip4_address_init (NMDedupMultiIter *iter, const NMIP4Config *self); void nm_ip_config_iter_ip4_route_init (NMDedupMultiIter *iter, const NMIP4Config *self); -static inline gboolean -nm_ip_config_iter_ip4_address_next (NMDedupMultiIter *ipconf_iter, const NMPlatformIP4Address **out_address) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next (ipconf_iter); - if (out_address) - *out_address = has_next ? NMP_OBJECT_CAST_IP4_ADDRESS (ipconf_iter->current->obj) : NULL; - return has_next; -} - -static inline gboolean -nm_ip_config_iter_ip4_route_next (NMDedupMultiIter *ipconf_iter, const NMPlatformIP4Route **out_route) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next (ipconf_iter); - if (out_route) - *out_route = has_next ? NMP_OBJECT_CAST_IP4_ROUTE (ipconf_iter->current->obj) : NULL; - return has_next; -} - #define nm_ip_config_iter_ip4_address_for_each(iter, self, address) \ for (nm_ip_config_iter_ip4_address_init ((iter), (self)); \ - nm_ip_config_iter_ip4_address_next ((iter), (address)); \ + nm_platform_dedup_multi_iter_next_ip4_address ((iter), (address)); \ ) #define nm_ip_config_iter_ip4_route_for_each(iter, self, route) \ for (nm_ip_config_iter_ip4_route_init ((iter), (self)); \ - nm_ip_config_iter_ip4_route_next ((iter), (route)); \ + nm_platform_dedup_multi_iter_next_ip4_route ((iter), (route)); \ ) /*****************************************************************************/ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index ab7edf8424..00865734c5 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -1296,8 +1296,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev const NMPlatformIP6Address *r_src = NULL; const NMPlatformIP6Address *r_dst = NULL; - has = nm_ip_config_iter_ip6_address_next (&ipconf_iter_src, &r_src); - if (has != nm_ip_config_iter_ip6_address_next (&ipconf_iter_dst, &r_dst)) { + has = nm_platform_dedup_multi_iter_next_ip6_address (&ipconf_iter_src, &r_src); + if (has != nm_platform_dedup_multi_iter_next_ip6_address (&ipconf_iter_dst, &r_dst)) { are_equal = FALSE; has_relevant_changes = TRUE; break; @@ -1344,8 +1344,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev const NMPlatformIP6Route *r_src = NULL; const NMPlatformIP6Route *r_dst = NULL; - has = nm_ip_config_iter_ip6_route_next (&ipconf_iter_src, &r_src); - if (has != nm_ip_config_iter_ip6_route_next (&ipconf_iter_dst, &r_dst)) { + has = nm_platform_dedup_multi_iter_next_ip6_route (&ipconf_iter_src, &r_src); + if (has != nm_platform_dedup_multi_iter_next_ip6_route (&ipconf_iter_dst, &r_dst)) { are_equal = FALSE; has_relevant_changes = TRUE; break; diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 4c21768ad8..079005e477 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -18,36 +18,14 @@ void nm_ip_config_iter_ip6_address_init (NMDedupMultiIter *iter, const NMIP6Config *self); void nm_ip_config_iter_ip6_route_init (NMDedupMultiIter *iter, const NMIP6Config *self); -static inline gboolean -nm_ip_config_iter_ip6_address_next (NMDedupMultiIter *ipconf_iter, const NMPlatformIP6Address **out_address) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next (ipconf_iter); - if (out_address) - *out_address = has_next ? NMP_OBJECT_CAST_IP6_ADDRESS (ipconf_iter->current->obj) : NULL; - return has_next; -} - -static inline gboolean -nm_ip_config_iter_ip6_route_next (NMDedupMultiIter *ipconf_iter, const NMPlatformIP6Route **out_route) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next (ipconf_iter); - if (out_route) - *out_route = has_next ? NMP_OBJECT_CAST_IP6_ROUTE (ipconf_iter->current->obj) : NULL; - return has_next; -} - #define nm_ip_config_iter_ip6_address_for_each(iter, self, address) \ for (nm_ip_config_iter_ip6_address_init ((iter), (self)); \ - nm_ip_config_iter_ip6_address_next ((iter), (address)); \ + nm_platform_dedup_multi_iter_next_ip6_address ((iter), (address)); \ ) #define nm_ip_config_iter_ip6_route_for_each(iter, self, route) \ for (nm_ip_config_iter_ip6_route_init ((iter), (self)); \ - nm_ip_config_iter_ip6_route_next ((iter), (route)); \ + nm_platform_dedup_multi_iter_next_ip6_route ((iter), (route)); \ ) /*****************************************************************************/ diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index dd00522064..36c9ad6982 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -1057,4 +1057,50 @@ nmp_object_ip_route_is_best_defaut_route (const NMPObject *obj) && r->type_coerced == nm_platform_route_type_coerce (1 /* RTN_UNICAST */); } +/*****************************************************************************/ + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip4_address (NMDedupMultiIter *ipconf_iter, const NMPlatformIP4Address **out_address) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next (ipconf_iter); + if (out_address) + *out_address = has_next ? NMP_OBJECT_CAST_IP4_ADDRESS (ipconf_iter->current->obj) : NULL; + return has_next; +} + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip4_route (NMDedupMultiIter *ipconf_iter, const NMPlatformIP4Route **out_route) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next (ipconf_iter); + if (out_route) + *out_route = has_next ? NMP_OBJECT_CAST_IP4_ROUTE (ipconf_iter->current->obj) : NULL; + return has_next; +} + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip6_address (NMDedupMultiIter *ipconf_iter, const NMPlatformIP6Address **out_address) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next (ipconf_iter); + if (out_address) + *out_address = has_next ? NMP_OBJECT_CAST_IP6_ADDRESS (ipconf_iter->current->obj) : NULL; + return has_next; +} + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip6_route (NMDedupMultiIter *ipconf_iter, const NMPlatformIP6Route **out_route) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next (ipconf_iter); + if (out_route) + *out_route = has_next ? NMP_OBJECT_CAST_IP6_ROUTE (ipconf_iter->current->obj) : NULL; + return has_next; +} + #endif /* __NMP_OBJECT_H__ */ From 5f23d691bfa3f371a6000cefcb01bd6649cdfbeb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 13:52:40 +0200 Subject: [PATCH 12/16] l3cfg: add nm_l3_config_data_new_from_platform() for capturing settings It basically does what nm_ip4_config_capture() and nm_ip6_config_capture() does. --- src/nm-l3-config-data.c | 108 +++++++++++++++++++++++++++++++++++++++- src/nm-l3-config-data.h | 8 ++- 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c index d20df9dc36..3445faf835 100644 --- a/src/nm-l3-config-data.c +++ b/src/nm-l3-config-data.c @@ -4,6 +4,9 @@ #include "nm-l3-config-data.h" +#include +#include + #include "nm-core-internal.h" #include "platform/nm-platform.h" #include "platform/nmp-object.h" @@ -846,7 +849,7 @@ _init_from_connection_ip (NML3ConfigData *self, } NML3ConfigData * -nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_index, +nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_idx, int ifindex, NMConnection *connection, NMSettingConnectionMdns mdns, @@ -856,7 +859,7 @@ nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_index, { NML3ConfigData *self; - self = nm_l3_config_data_new (multi_index); + self = nm_l3_config_data_new (multi_idx); _init_from_connection_ip (self, AF_INET, ifindex, connection, route_table, route_metric); _init_from_connection_ip (self, AF_INET6, ifindex, connection, route_table, route_metric); @@ -866,3 +869,104 @@ nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_index, return self; } + +static int +sort_captured_addresses_4 (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); + const NMPlatformIP4Address *addr_b = NMP_OBJECT_CAST_IP4_ADDRESS (c_list_entry (lst_b, NMDedupMultiEntry, lst_entries)->obj); + + nm_assert (addr_a); + nm_assert (addr_b); + + /* Primary addresses first */ + return NM_FLAGS_HAS (addr_a->n_ifa_flags, IFA_F_SECONDARY) - + NM_FLAGS_HAS (addr_b->n_ifa_flags, IFA_F_SECONDARY); +} + +static int +sort_captured_addresses_6 (const CList *lst_a, const CList *lst_b, gconstpointer user_data) +{ + NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941 = GPOINTER_TO_INT (user_data); + const NMPlatformIP6Address *addr_a = NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj); + const NMPlatformIP6Address *addr_b = NMP_OBJECT_CAST_IP6_ADDRESS (c_list_entry (lst_b, NMDedupMultiEntry, lst_entries)->obj); + + return nm_platform_ip6_address_pretty_sort_cmp (addr_a, + addr_b, + ipv6_privacy_rfc4941 == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); +} + +static void +_init_from_platform (NML3ConfigData *self, + int addr_family, + int ifindex, + NMPlatform *platform, + NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941) +{ + const gboolean IS_IPv4 = NM_IS_IPv4 (addr_family); + const NMDedupMultiHeadEntry *head_entry; + const NMPObject *plobj = NULL; + NMDedupMultiIter iter; + + nm_assert_addr_family (addr_family); + nm_assert (ifindex > 0); + + head_entry = nm_platform_lookup_object (platform, + IS_IPv4 + ? NMP_OBJECT_TYPE_IP4_ADDRESS + : NMP_OBJECT_TYPE_IP6_ADDRESS, + ifindex); + if (head_entry) { + nmp_cache_iter_for_each (&iter, head_entry, &plobj) { + if (!_l3_config_data_add_obj (self->multi_idx, + &self->idx_addresses_x[IS_IPv4], + ifindex, + plobj, + NULL, + FALSE, + TRUE, + NULL, + NULL)) + nm_assert_not_reached (); + } + head_entry = nm_l3_config_data_lookup_addresses (self, addr_family); + nm_assert (head_entry); + nm_dedup_multi_head_entry_sort (head_entry, + IS_IPv4 + ? sort_captured_addresses_4 + : sort_captured_addresses_6, + GINT_TO_POINTER (ipv6_privacy_rfc4941)); + } + + head_entry = nm_platform_lookup_object (platform, + IS_IPv4 + ? NMP_OBJECT_TYPE_IP4_ROUTE + : NMP_OBJECT_TYPE_IP6_ROUTE, + ifindex); + nmp_cache_iter_for_each (&iter, head_entry, &plobj) + _nm_l3_config_data_add_route (self, addr_family, ifindex, plobj, NULL, NULL, NULL); +} + +NML3ConfigData * +nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_idx, + int ifindex, + NMPlatform *platform, + NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941) +{ + + NML3ConfigData *self; + + nm_assert (NM_IS_PLATFORM (platform)); + nm_assert (ifindex > 0); + + /* Slaves have no IP configuration */ + if (nm_platform_link_get_master (platform, ifindex) > 0) + return NULL; + + self = nm_l3_config_data_new (multi_idx); + + _init_from_platform (self, AF_INET, ifindex, platform, ipv6_privacy_rfc4941); + _init_from_platform (self, AF_INET6, ifindex, platform, ipv6_privacy_rfc4941); + + return self; +} diff --git a/src/nm-l3-config-data.h b/src/nm-l3-config-data.h index f7b87d7d16..5c8122a979 100644 --- a/src/nm-l3-config-data.h +++ b/src/nm-l3-config-data.h @@ -5,6 +5,7 @@ #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-setting-connection.h" +#include "nm-setting-ip6-config.h" #include "platform/nm-platform.h" typedef struct _NML3ConfigData NML3ConfigData; @@ -20,7 +21,7 @@ gboolean nm_l3_config_data_is_sealed (NML3ConfigData *self); const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_addresses (const NML3ConfigData *self, int addr_family); const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_routes (const NML3ConfigData *self, int addr_family); -NML3ConfigData *nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_index, +NML3ConfigData *nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_idx, int ifindex, NMConnection *connection, NMSettingConnectionMdns mdns, @@ -28,6 +29,11 @@ NML3ConfigData *nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_ guint32 route_table, guint32 route_metric); +NML3ConfigData *nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_idx, + int ifindex, + NMPlatform *platform, + NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941); + /*****************************************************************************/ gboolean _nm_l3_config_data_add_address (NML3ConfigData *self, From 6aa338edd40315ae5d39d4a466d28fe433afb6f4 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 10:25:36 +0200 Subject: [PATCH 13/16] l3cfg: tie NML3ConfigData to an ifindex NML3ConfigData tracks IP addresses and routes. In their current form, these types (NMPObject) always have an ifindex and there is no sensible way to have an NMPObject (for routes or addresses) that have a wildcard ifindex. Honor that by also tying NML3ConfigData to an ifindex. In most cases, the user knows the ifindex before and can create it. On the unlikely case where the user doesn't know the ifindex, we should add a new nm_l3_config_data_clone() function, which allows migrating the setting from one ifindex to another. --- src/nm-l3-config-data.c | 62 ++++++++++++++++++++++++----------------- src/nm-l3-config-data.h | 15 ++++++---- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c index 3445faf835..e4202c7e20 100644 --- a/src/nm-l3-config-data.c +++ b/src/nm-l3-config-data.c @@ -89,6 +89,8 @@ struct _NML3ConfigData { NMSettingConnectionMdns mdns; NMSettingConnectionLlmnr llmnr; + int ifindex; + int ref_count; bool is_sealed:1; @@ -129,6 +131,10 @@ _route_valid (int addr_family, gconstpointer r) static gboolean NM_IS_L3_CONFIG_DATA (const NML3ConfigData *self, gboolean allow_sealed) { + nm_assert ( !self + || ( self->ifindex > 0 + && self->multi_idx + && self->ref_count > 0)); return self && self->ref_count > 0 && ( allow_sealed @@ -181,15 +187,18 @@ _idx_type_init (DedupMultiIdxType *idx_type, } NML3ConfigData * -nm_l3_config_data_new (NMDedupMultiIndex *multi_idx) +nm_l3_config_data_new (NMDedupMultiIndex *multi_idx, + int ifindex) { NML3ConfigData *self; nm_assert (multi_idx); + nm_assert (ifindex > 0); self = g_slice_new (NML3ConfigData); *self = (NML3ConfigData) { .ref_count = 1, + .ifindex = ifindex, .multi_idx = nm_dedup_multi_index_ref (multi_idx), .mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT, .llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT, @@ -296,6 +305,14 @@ nm_l3_config_data_lookup_routes (const NML3ConfigData *self, NULL); } +int +nm_l3_config_data_get_ifindex (const NML3ConfigData *self) +{ + nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); + + return self->ifindex; +} + /*****************************************************************************/ static gboolean @@ -315,12 +332,11 @@ _l3_config_data_add_obj (NMDedupMultiIndex *multi_idx, nm_assert (multi_idx); nm_assert (idx_type); + nm_assert (ifindex > 0); nm_assert (NM_IN_SET (idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ADDRESS, NMP_OBJECT_TYPE_IP6_ROUTE)); - nm_assert (ifindex > 0); - /* we go through extra lengths to accept a full obj_new object. That one, * can be reused by increasing the ref-count. */ if (!obj_new) { @@ -488,7 +504,6 @@ _l3_config_best_default_route_merge (const NMPObject **best_default_route, const gboolean _nm_l3_config_data_add_route (NML3ConfigData *self, int addr_family, - int ifindex, const NMPObject *obj_new, const NMPlatformIPRoute *pl_new, const NMPObject **out_obj_new, @@ -500,8 +515,8 @@ _nm_l3_config_data_add_route (NML3ConfigData *self, gboolean changed = FALSE; gboolean changed_best_default_route = FALSE; + nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); nm_assert_addr_family (addr_family); - nm_assert (ifindex > 0); nm_assert ((!pl_new) != (!obj_new)); nm_assert ( !pl_new || _route_valid (addr_family, pl_new)); @@ -513,7 +528,7 @@ _nm_l3_config_data_add_route (NML3ConfigData *self, addr_family == AF_INET ? &self->idx_routes_4 : &self->idx_routes_6, - ifindex, + self->ifindex, obj_new, (const NMPlatformObject *) pl_new, TRUE, @@ -542,13 +557,11 @@ _nm_l3_config_data_add_route (NML3ConfigData *self, gboolean _nm_l3_config_data_add_address (NML3ConfigData *self, int addr_family, - int ifindex, const NMPObject *obj_new, const NMPlatformIPAddress *pl_new) { nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); nm_assert_addr_family (addr_family); - nm_assert (ifindex > 0); nm_assert ((!pl_new) != (!obj_new)); nm_assert ( !obj_new || NMP_OBJECT_GET_ADDR_FAMILY (obj_new) == addr_family); @@ -557,7 +570,7 @@ _nm_l3_config_data_add_address (NML3ConfigData *self, addr_family == AF_INET ? &self->idx_addresses_4 : &self->idx_addresses_6, - ifindex, + self->ifindex, obj_new, (const NMPlatformObject *) pl_new, TRUE, @@ -668,7 +681,6 @@ _nm_l3_config_data_set_dns_priority (NML3ConfigData *self, static void _init_from_connection_ip (NML3ConfigData *self, int addr_family, - int ifindex, NMConnection *connection, guint32 route_table, guint32 route_metric) @@ -685,7 +697,6 @@ _init_from_connection_ip (NML3ConfigData *self, int idx; nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); - nm_assert (ifindex > 0); nm_assert_addr_family (addr_family); nm_assert (!connection || NM_IS_CONNECTION (connection)); @@ -718,7 +729,7 @@ _init_from_connection_ip (NML3ConfigData *self, }; } - _nm_l3_config_data_add_route (self, addr_family, ifindex, NULL, &r.rx, NULL, NULL); + _nm_l3_config_data_add_route (self, addr_family, NULL, &r.rx, NULL, NULL); } naddresses = nm_setting_ip_config_get_num_addresses (s_ip); @@ -758,7 +769,7 @@ _init_from_connection_ip (NML3ConfigData *self, nm_assert (a.a6.plen <= 128); } - _nm_l3_config_data_add_address (self, addr_family, ifindex, NULL, &a.ax); + _nm_l3_config_data_add_address (self, addr_family, NULL, &a.ax); } nroutes = nm_setting_ip_config_get_num_routes (s_ip); @@ -812,7 +823,7 @@ _init_from_connection_ip (NML3ConfigData *self, &r.rx, route_table); - _nm_l3_config_data_add_route (self, addr_family, ifindex, NULL, &r.rx, NULL, NULL); + _nm_l3_config_data_add_route (self, addr_family, NULL, &r.rx, NULL, NULL); } nnameservers = nm_setting_ip_config_get_num_dns (s_ip); @@ -859,10 +870,10 @@ nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_idx, { NML3ConfigData *self; - self = nm_l3_config_data_new (multi_idx); + self = nm_l3_config_data_new (multi_idx, ifindex); - _init_from_connection_ip (self, AF_INET, ifindex, connection, route_table, route_metric); - _init_from_connection_ip (self, AF_INET6, ifindex, connection, route_table, route_metric); + _init_from_connection_ip (self, AF_INET, connection, route_table, route_metric); + _init_from_connection_ip (self, AF_INET6, connection, route_table, route_metric); self->mdns = mdns; self->llmnr = llmnr; @@ -899,7 +910,6 @@ sort_captured_addresses_6 (const CList *lst_a, const CList *lst_b, gconstpointer static void _init_from_platform (NML3ConfigData *self, int addr_family, - int ifindex, NMPlatform *platform, NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941) { @@ -908,19 +918,19 @@ _init_from_platform (NML3ConfigData *self, const NMPObject *plobj = NULL; NMDedupMultiIter iter; + nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); nm_assert_addr_family (addr_family); - nm_assert (ifindex > 0); head_entry = nm_platform_lookup_object (platform, IS_IPv4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, - ifindex); + self->ifindex); if (head_entry) { nmp_cache_iter_for_each (&iter, head_entry, &plobj) { if (!_l3_config_data_add_obj (self->multi_idx, &self->idx_addresses_x[IS_IPv4], - ifindex, + self->ifindex, plobj, NULL, FALSE, @@ -942,9 +952,9 @@ _init_from_platform (NML3ConfigData *self, IS_IPv4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, - ifindex); + self->ifindex); nmp_cache_iter_for_each (&iter, head_entry, &plobj) - _nm_l3_config_data_add_route (self, addr_family, ifindex, plobj, NULL, NULL, NULL); + _nm_l3_config_data_add_route (self, addr_family, plobj, NULL, NULL, NULL); } NML3ConfigData * @@ -963,10 +973,10 @@ nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_idx, if (nm_platform_link_get_master (platform, ifindex) > 0) return NULL; - self = nm_l3_config_data_new (multi_idx); + self = nm_l3_config_data_new (multi_idx, ifindex); - _init_from_platform (self, AF_INET, ifindex, platform, ipv6_privacy_rfc4941); - _init_from_platform (self, AF_INET6, ifindex, platform, ipv6_privacy_rfc4941); + _init_from_platform (self, AF_INET, platform, ipv6_privacy_rfc4941); + _init_from_platform (self, AF_INET6, platform, ipv6_privacy_rfc4941); return self; } diff --git a/src/nm-l3-config-data.h b/src/nm-l3-config-data.h index 5c8122a979..e559d11af6 100644 --- a/src/nm-l3-config-data.h +++ b/src/nm-l3-config-data.h @@ -10,7 +10,8 @@ typedef struct _NML3ConfigData NML3ConfigData; -NML3ConfigData *nm_l3_config_data_new (NMDedupMultiIndex *multi_idx); +NML3ConfigData *nm_l3_config_data_new (NMDedupMultiIndex *multi_idx, + int ifindex); NML3ConfigData *nm_l3_config_data_ref (NML3ConfigData *self); NML3ConfigData *nm_l3_config_data_ref_and_seal (NML3ConfigData *self); NML3ConfigData *nm_l3_config_data_seal (NML3ConfigData *self); @@ -18,9 +19,6 @@ void nm_l3_config_data_unref (NML3ConfigData *self); gboolean nm_l3_config_data_is_sealed (NML3ConfigData *self); -const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_addresses (const NML3ConfigData *self, int addr_family); -const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_routes (const NML3ConfigData *self, int addr_family); - NML3ConfigData *nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_idx, int ifindex, NMConnection *connection, @@ -36,15 +34,20 @@ NML3ConfigData *nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_id /*****************************************************************************/ +const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_addresses (const NML3ConfigData *self, int addr_family); +const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_routes (const NML3ConfigData *self, int addr_family); + +int nm_l3_config_data_get_ifindex (const NML3ConfigData *self); + +/*****************************************************************************/ + gboolean _nm_l3_config_data_add_address (NML3ConfigData *self, int addr_family, - int ifindex, const NMPObject *obj_new, const NMPlatformIPAddress *pl_new); gboolean _nm_l3_config_data_add_route (NML3ConfigData *self, int addr_family, - int ifindex, const NMPObject *obj_new, const NMPlatformIPRoute *pl_new, const NMPObject **out_obj_new, From a2a69a2dabe6c5090316410240de2caf20c73fe9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 10:35:49 +0200 Subject: [PATCH 14/16] l3cfg: add more API to NML3ConfigData --- src/nm-l3-config-data.c | 342 +++++++++++++++++++++++++++----------- src/nm-l3-config-data.h | 134 ++++++++++++--- src/platform/nmp-object.h | 13 ++ 3 files changed, 371 insertions(+), 118 deletions(-) diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c index e4202c7e20..a8427576aa 100644 --- a/src/nm-l3-config-data.c +++ b/src/nm-l3-config-data.c @@ -46,6 +46,8 @@ struct _NML3ConfigData { const NMPObject *best_default_route_x[2]; }; + GArray *wins_4; + union { struct { GArray *nameservers_6; @@ -98,6 +100,89 @@ struct _NML3ConfigData { /*****************************************************************************/ +static GArray * +_garray_inaddr_ensure (GArray **p_arr, + int addr_family) +{ + nm_assert (p_arr); + nm_assert_addr_family (addr_family); + + if (G_UNLIKELY (!*p_arr)) { + *p_arr = g_array_new (FALSE, + FALSE, + nm_utils_addr_family_to_size (addr_family)); + } + return *p_arr; +} + +static GArray * +_garray_inaddr_clone (GArray *src, + int addr_family) +{ + const gsize elt_size = nm_utils_addr_family_to_size (addr_family); + GArray *dst; + + nm_assert_addr_family (addr_family); + + if ( !src + || src->len == 0) + return NULL; + + dst = g_array_sized_new (FALSE, FALSE, elt_size, src->len); + g_array_set_size (dst, src->len); + memcpy (dst->data, src->data, src->len * elt_size); + return dst; +} + +static gssize +_garray_inaddr_find (GArray *arr, + int addr_family, + gconstpointer needle, + /* (const NMIPAddr **) */ gpointer out_addr) +{ + guint i; + + nm_assert_addr_family (addr_family); + nm_assert (needle); + + if (arr) { + const gsize elt_size = nm_utils_addr_family_to_size (addr_family); + const char *p; + + p = arr->data; + for (i = 0; i < arr->len; i++, p += elt_size) { + if (memcmp (p, needle, elt_size) == 0) { + NM_SET_OUT ((gconstpointer *) out_addr, p); + return i; + } + } + } + NM_SET_OUT ((gconstpointer *) out_addr, NULL); + return -1; +} + +static gboolean +_garray_inaddr_add (GArray **p_arr, + int addr_family, + gconstpointer addr) +{ + nm_assert (p_arr); + nm_assert_addr_family (addr_family); + nm_assert (addr); + + if (!*p_arr) + _garray_inaddr_ensure (p_arr, addr_family); + else { + if (_garray_inaddr_find (*p_arr, addr_family, addr, NULL) >= 0) + return FALSE; + } + + g_array_append_vals (*p_arr, addr, 1); + return TRUE; +} + +/*****************************************************************************/ + static gboolean _route_valid_4 (const NMPlatformIP4Route *r) { @@ -141,21 +226,6 @@ NM_IS_L3_CONFIG_DATA (const NML3ConfigData *self, gboolean allow_sealed) || !self->is_sealed); } -static GArray * -_garray_ensure_for_addrbin (GArray **p_arr, - int addr_family) -{ - nm_assert (p_arr); - nm_assert_addr_family (addr_family); - - if (G_UNLIKELY (!*p_arr)) { - *p_arr = g_array_new (FALSE, - FALSE, - nm_utils_addr_family_to_size (addr_family)); - } - return *p_arr; -} - static void _idx_obj_id_hash_update (const NMDedupMultiIdxType *idx_type, const NMDedupMultiObj *obj, @@ -262,6 +332,8 @@ nm_l3_config_data_unref (NML3ConfigData *self) nmp_object_unref (self->best_default_route_4); nmp_object_unref (self->best_default_route_6); + nm_clear_pointer (&self->wins_4, g_array_unref); + nm_clear_pointer (&self->nameservers_4, g_array_unref); nm_clear_pointer (&self->nameservers_6, g_array_unref); @@ -282,27 +354,31 @@ nm_l3_config_data_unref (NML3ConfigData *self) /*****************************************************************************/ const NMDedupMultiHeadEntry * -nm_l3_config_data_lookup_addresses (const NML3ConfigData *self, - int addr_family) +nm_l3_config_data_lookup_objs (const NML3ConfigData *self, NMPObjectType obj_type) { + const DedupMultiIdxType *idx; + nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); - nm_assert_addr_family (addr_family); - return nm_dedup_multi_index_lookup_head (self->multi_idx, - &self->idx_addresses_x[NM_IS_IPv4 (addr_family)].parent, - NULL); -} + switch (obj_type) { + case NMP_OBJECT_TYPE_IP4_ADDRESS: + idx = &self->idx_addresses_4; + break; + case NMP_OBJECT_TYPE_IP6_ADDRESS: + idx = &self->idx_addresses_6; + break; + case NMP_OBJECT_TYPE_IP4_ROUTE: + idx = &self->idx_routes_4; + break; + case NMP_OBJECT_TYPE_IP6_ROUTE: + idx = &self->idx_routes_6; + break; + default: + nm_assert_not_reached (); + return NULL; + } -const NMDedupMultiHeadEntry * -nm_l3_config_data_lookup_routes (const NML3ConfigData *self, - int addr_family) -{ - nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); - nm_assert_addr_family (addr_family); - - return nm_dedup_multi_index_lookup_head (self->multi_idx, - &self->idx_routes_x[NM_IS_IPv4 (addr_family)].parent, - NULL); + return nm_dedup_multi_index_lookup_head (self->multi_idx, &idx->parent, NULL); } int @@ -493,6 +569,37 @@ _l3_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPOb return obj_cur; } +gboolean +nm_l3_config_data_add_address (NML3ConfigData *self, + int addr_family, + const NMPObject *obj_new, + const NMPlatformIPAddress *pl_new, + const NMPObject **out_obj_new) +{ + const NMPObject *new; + gboolean changed; + + nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); + nm_assert_addr_family (addr_family); + nm_assert ((!pl_new) != (!obj_new)); + nm_assert ( !obj_new + || NMP_OBJECT_GET_ADDR_FAMILY (obj_new) == addr_family); + + changed = _l3_config_data_add_obj (self->multi_idx, + addr_family == AF_INET + ? &self->idx_addresses_4 + : &self->idx_addresses_6, + self->ifindex, + obj_new, + (const NMPlatformObject *) pl_new, + TRUE, + FALSE, + NULL, + &new); + NM_SET_OUT (out_obj_new, nmp_object_ref (new)); + return changed; +} + static gboolean _l3_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate) { @@ -502,12 +609,12 @@ _l3_config_best_default_route_merge (const NMPObject **best_default_route, const } gboolean -_nm_l3_config_data_add_route (NML3ConfigData *self, - int addr_family, - const NMPObject *obj_new, - const NMPlatformIPRoute *pl_new, - const NMPObject **out_obj_new, - gboolean *out_changed_best_default_route) +nm_l3_config_data_add_route (NML3ConfigData *self, + int addr_family, + const NMPObject *obj_new, + const NMPlatformIPRoute *pl_new, + const NMPObject **out_obj_new, + gboolean *out_changed_best_default_route) { const gboolean IS_IPv4 = NM_IS_IPv4 (addr_family); nm_auto_nmpobj const NMPObject *obj_old = NULL; @@ -554,31 +661,6 @@ _nm_l3_config_data_add_route (NML3ConfigData *self, return changed; } -gboolean -_nm_l3_config_data_add_address (NML3ConfigData *self, - int addr_family, - const NMPObject *obj_new, - const NMPlatformIPAddress *pl_new) -{ - nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); - nm_assert_addr_family (addr_family); - nm_assert ((!pl_new) != (!obj_new)); - nm_assert ( !obj_new - || NMP_OBJECT_GET_ADDR_FAMILY (obj_new) == addr_family); - - return _l3_config_data_add_obj (self->multi_idx, - addr_family == AF_INET - ? &self->idx_addresses_4 - : &self->idx_addresses_6, - self->ifindex, - obj_new, - (const NMPlatformObject *) pl_new, - TRUE, - FALSE, - NULL, - NULL); -} - /*****************************************************************************/ static gboolean @@ -591,7 +673,7 @@ _check_and_add_domain (GPtrArray **p_arr, const char *domain) g_return_val_if_fail (domain, FALSE); if (domain[0] == '\0') - g_return_val_if_reached (FALSE); + return FALSE; if (domain[0] == '.' || strstr (domain, "..")) return FALSE; @@ -612,9 +694,34 @@ _check_and_add_domain (GPtrArray **p_arr, const char *domain) } gboolean -_nm_l3_config_data_add_domain (NML3ConfigData *self, - int addr_family, - const char *domain) +nm_l3_config_data_add_nameserver (NML3ConfigData *self, + int addr_family, + gconstpointer /* (const NMIPAddr *) */ nameserver) +{ + nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); + nm_assert_addr_family (addr_family); + nm_assert (nameserver); + + return _garray_inaddr_add (&self->nameservers_x[NM_IS_IPv4 (addr_family)], + addr_family, + nameserver); +} + +gboolean +nm_l3_config_data_add_wins (NML3ConfigData *self, + in_addr_t wins) +{ + nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); + + return _garray_inaddr_add (&self->wins_4, + AF_INET, + &wins); +} + +gboolean +nm_l3_config_data_add_domain (NML3ConfigData *self, + int addr_family, + const char *domain) { nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); nm_assert_addr_family (addr_family); @@ -623,9 +730,9 @@ _nm_l3_config_data_add_domain (NML3ConfigData *self, } gboolean -_nm_l3_config_data_add_search (NML3ConfigData *self, - int addr_family, - const char *search) +nm_l3_config_data_add_search (NML3ConfigData *self, + int addr_family, + const char *search) { nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); nm_assert_addr_family (addr_family); @@ -634,9 +741,9 @@ _nm_l3_config_data_add_search (NML3ConfigData *self, } gboolean -_nm_l3_config_data_add_dns_option (NML3ConfigData *self, - int addr_family, - const char *dns_option) +nm_l3_config_data_add_dns_option (NML3ConfigData *self, + int addr_family, + const char *dns_option) { GPtrArray **p_arr; @@ -645,8 +752,8 @@ _nm_l3_config_data_add_dns_option (NML3ConfigData *self, g_return_val_if_fail (dns_option, FALSE); - if (!dns_option[0]) - g_return_val_if_reached (FALSE); + if (dns_option[0] == '\0') + return FALSE; p_arr = &self->dns_options_x[NM_IS_IPv4 (addr_family)]; @@ -659,9 +766,9 @@ _nm_l3_config_data_add_dns_option (NML3ConfigData *self, } gboolean -_nm_l3_config_data_set_dns_priority (NML3ConfigData *self, - int addr_family, - int dns_priority) +nm_l3_config_data_set_dns_priority (NML3ConfigData *self, + int addr_family, + int dns_priority) { int *p_val; @@ -729,7 +836,7 @@ _init_from_connection_ip (NML3ConfigData *self, }; } - _nm_l3_config_data_add_route (self, addr_family, NULL, &r.rx, NULL, NULL); + nm_l3_config_data_add_route (self, addr_family, NULL, &r.rx, NULL, NULL); } naddresses = nm_setting_ip_config_get_num_addresses (s_ip); @@ -769,7 +876,7 @@ _init_from_connection_ip (NML3ConfigData *self, nm_assert (a.a6.plen <= 128); } - _nm_l3_config_data_add_address (self, addr_family, NULL, &a.ax); + nm_l3_config_data_add_address (self, addr_family, NULL, &a.ax, NULL); } nroutes = nm_setting_ip_config_get_num_routes (s_ip); @@ -823,7 +930,7 @@ _init_from_connection_ip (NML3ConfigData *self, &r.rx, route_table); - _nm_l3_config_data_add_route (self, addr_family, NULL, &r.rx, NULL, NULL); + nm_l3_config_data_add_route (self, addr_family, NULL, &r.rx, NULL, NULL); } nnameservers = nm_setting_ip_config_get_num_dns (s_ip); @@ -834,29 +941,27 @@ _init_from_connection_ip (NML3ConfigData *self, s = nm_setting_ip_config_get_dns (s_ip, i); if (!nm_utils_parse_inaddr_bin (addr_family, s, NULL, &ip)) continue; - g_array_append_vals (_garray_ensure_for_addrbin (&self->nameservers_x[IS_IPv4], addr_family), - &ip, - 1); + nm_l3_config_data_add_nameserver (self, addr_family, &ip); } nsearches = nm_setting_ip_config_get_num_dns_searches (s_ip); for (i = 0; i < nsearches; i++) { - _nm_l3_config_data_add_search (self, - addr_family, - nm_setting_ip_config_get_dns_search (s_ip, i)); + nm_l3_config_data_add_search (self, + addr_family, + nm_setting_ip_config_get_dns_search (s_ip, i)); } idx = 0; while ((idx = nm_setting_ip_config_next_valid_dns_option (s_ip, i)) >= 0) { - _nm_l3_config_data_add_dns_option (self, - addr_family, - nm_setting_ip_config_get_dns_option (s_ip, i)); + nm_l3_config_data_add_dns_option (self, + addr_family, + nm_setting_ip_config_get_dns_option (s_ip, i)); idx++; } - _nm_l3_config_data_set_dns_priority (self, - addr_family, - nm_setting_ip_config_get_dns_priority (s_ip)); + nm_l3_config_data_set_dns_priority (self, + addr_family, + nm_setting_ip_config_get_dns_priority (s_ip)); } NML3ConfigData * @@ -954,7 +1059,7 @@ _init_from_platform (NML3ConfigData *self, : NMP_OBJECT_TYPE_IP6_ROUTE, self->ifindex); nmp_cache_iter_for_each (&iter, head_entry, &plobj) - _nm_l3_config_data_add_route (self, addr_family, plobj, NULL, NULL, NULL); + nm_l3_config_data_add_route (self, addr_family, plobj, NULL, NULL, NULL); } NML3ConfigData * @@ -980,3 +1085,52 @@ nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_idx, return self; } + +/*****************************************************************************/ + +NML3ConfigData * +nm_l3_config_data_new_clone (const NML3ConfigData *src, + int ifindex) +{ + NML3ConfigData *self; + NMDedupMultiIter iter; + const NMPObject *obj; + + nm_assert (NM_IS_L3_CONFIG_DATA (src, TRUE)); + + /* pass 0, to use the original ifindex. You can also use this function to + * copy the configuration for a different ifindex. */ + nm_assert (ifindex >= 0); + if (ifindex <= 0) + ifindex = src->ifindex; + + self = nm_l3_config_data_new (src->multi_idx, ifindex); + + nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP4_ADDRESS) + nm_l3_config_data_add_address (self, AF_INET, obj, NULL, NULL); + nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP6_ADDRESS) + nm_l3_config_data_add_address (self, AF_INET6, obj, NULL, NULL); + nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP4_ROUTE) + nm_l3_config_data_add_route (self, AF_INET, obj, NULL, NULL, NULL); + nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP6_ROUTE) + nm_l3_config_data_add_route (self, AF_INET6, obj, NULL, NULL, NULL); + + nm_assert (self->best_default_route_4 == src->best_default_route_4); + nm_assert (self->best_default_route_6 == src->best_default_route_6); + + self->wins_4 = _garray_inaddr_clone (src->wins_4, AF_INET); + self->nameservers_4 = _garray_inaddr_clone (src->nameservers_4, AF_INET); + self->nameservers_6 = _garray_inaddr_clone (src->nameservers_6, AF_INET6); + self->domains_4 = nm_strv_ptrarray_clone (src->domains_4, TRUE); + self->domains_6 = nm_strv_ptrarray_clone (src->domains_6, TRUE); + self->searches_4 = nm_strv_ptrarray_clone (src->searches_4, TRUE); + self->searches_6 = nm_strv_ptrarray_clone (src->searches_6, TRUE); + self->dns_options_4 = nm_strv_ptrarray_clone (src->dns_options_4, TRUE); + self->dns_options_6 = nm_strv_ptrarray_clone (src->dns_options_6, TRUE); + self->dns_priority_4 = src->dns_priority_4; + self->dns_priority_6 = src->dns_priority_6; + self->mdns = src->mdns; + self->llmnr = src->llmnr; + + return self; +} diff --git a/src/nm-l3-config-data.h b/src/nm-l3-config-data.h index e559d11af6..02136b8267 100644 --- a/src/nm-l3-config-data.h +++ b/src/nm-l3-config-data.h @@ -17,8 +17,14 @@ NML3ConfigData *nm_l3_config_data_ref_and_seal (NML3ConfigData *self); NML3ConfigData *nm_l3_config_data_seal (NML3ConfigData *self); void nm_l3_config_data_unref (NML3ConfigData *self); +NM_AUTO_DEFINE_FCN0 (NML3ConfigData *, _nm_auto_unref_l3cfg, nm_l3_config_data_unref); +#define nm_auto_unref_l3cfg nm_auto (_nm_auto_unref_l3cfg) + gboolean nm_l3_config_data_is_sealed (NML3ConfigData *self); +NML3ConfigData *nm_l3_config_data_new_clone (const NML3ConfigData *src, + int ifindex); + NML3ConfigData *nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_idx, int ifindex, NMConnection *connection, @@ -34,39 +40,119 @@ NML3ConfigData *nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_id /*****************************************************************************/ -const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_addresses (const NML3ConfigData *self, int addr_family); -const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_routes (const NML3ConfigData *self, int addr_family); +const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_objs (const NML3ConfigData *self, NMPObjectType obj_type); + +static inline const NMDedupMultiHeadEntry * +nm_l3_config_data_lookup_addresses (const NML3ConfigData *self, int addr_family) +{ + nm_assert_addr_family (addr_family); + + return nm_l3_config_data_lookup_objs (self, + addr_family == AF_INET + ? NMP_OBJECT_TYPE_IP4_ADDRESS + : NMP_OBJECT_TYPE_IP6_ADDRESS); +} + +static inline const NMDedupMultiHeadEntry * +nm_l3_config_data_lookup_routes (const NML3ConfigData *self, int addr_family) +{ + nm_assert_addr_family (addr_family); + + return nm_l3_config_data_lookup_objs (self, + addr_family == AF_INET + ? NMP_OBJECT_TYPE_IP4_ROUTE + : NMP_OBJECT_TYPE_IP6_ROUTE); +} + +#define nm_l3_config_data_iter_obj_for_each(iter, self, obj, type) \ + for (nm_dedup_multi_iter_init (&(iter), nm_l3_config_data_lookup_objs ((self), (type))); \ + nm_platform_dedup_multi_iter_next_obj (&(iter), &(obj), (type)); \ + ) + +#define nm_l3_config_data_iter_ip4_address_for_each(iter, self, address) \ + for (nm_dedup_multi_iter_init (&(iter), nm_l3_config_data_lookup_addresses ((self), AF_INET)); \ + nm_platform_dedup_multi_iter_next_ip4_address (&(iter), &(address)); \ + ) + +#define nm_l3_config_data_iter_ip6_address_for_each(iter, self, address) \ + for (nm_dedup_multi_iter_init (&(iter), nm_l3_config_data_lookup_addresses ((self), AF_INET6)); \ + nm_platform_dedup_multi_iter_next_ip6_address (&(iter), &(address)); \ + ) + +#define nm_l3_config_data_iter_ip4_route_for_each(iter, self, route) \ + for (nm_dedup_multi_iter_init (&(iter), nm_l3_config_data_lookup_routes ((self), AF_INET)); \ + nm_platform_dedup_multi_iter_next_ip4_route (&(iter), &(route)); \ + ) + +#define nm_l3_config_data_iter_ip6_route_for_each(iter, self, route) \ + for (nm_dedup_multi_iter_init (&(iter), nm_l3_config_data_lookup_routes ((self), AF_INET6)); \ + nm_platform_dedup_multi_iter_next_ip6_route (&(iter), &(route)); \ + ) + +/*****************************************************************************/ int nm_l3_config_data_get_ifindex (const NML3ConfigData *self); /*****************************************************************************/ -gboolean _nm_l3_config_data_add_address (NML3ConfigData *self, - int addr_family, - const NMPObject *obj_new, - const NMPlatformIPAddress *pl_new); +gboolean nm_l3_config_data_add_address (NML3ConfigData *self, + int addr_family, + const NMPObject *obj_new, + const NMPlatformIPAddress *pl_new, + const NMPObject **out_obj_new); -gboolean _nm_l3_config_data_add_route (NML3ConfigData *self, +static inline gboolean +nm_l3_config_data_add_address_4 (NML3ConfigData *self, const NMPlatformIP4Address *addr) +{ + return nm_l3_config_data_add_address (self, AF_INET, NULL, NM_PLATFORM_IP_ADDRESS_CAST (addr), NULL); +} + +static inline gboolean +nm_l3_config_data_add_address_6 (NML3ConfigData *self, const NMPlatformIP6Address *addr) +{ + return nm_l3_config_data_add_address (self, AF_INET6, NULL, NM_PLATFORM_IP_ADDRESS_CAST (addr), NULL); +} + +gboolean nm_l3_config_data_add_route (NML3ConfigData *self, + int addr_family, + const NMPObject *obj_new, + const NMPlatformIPRoute *pl_new, + const NMPObject **out_obj_new, + gboolean *out_changed_best_default_route); + +static inline gboolean +nm_l3_config_data_add_route_4 (NML3ConfigData *self, const NMPlatformIP4Route *rt) +{ + return nm_l3_config_data_add_route (self, AF_INET, NULL, NM_PLATFORM_IP_ROUTE_CAST (rt), NULL, NULL); +} + +static inline gboolean +nm_l3_config_data_add_route_6 (NML3ConfigData *self, const NMPlatformIP6Route *rt) +{ + return nm_l3_config_data_add_route (self, AF_INET6, NULL, NM_PLATFORM_IP_ROUTE_CAST (rt), NULL, NULL); +} + +gboolean nm_l3_config_data_add_nameserver (NML3ConfigData *self, + int addr_family, + gconstpointer /* (const NMIPAddr *) */ nameserver); + +gboolean nm_l3_config_data_add_wins (NML3ConfigData *self, + in_addr_t wins); + +gboolean nm_l3_config_data_add_domain (NML3ConfigData *self, int addr_family, - const NMPObject *obj_new, - const NMPlatformIPRoute *pl_new, - const NMPObject **out_obj_new, - gboolean *out_changed_best_default_route); + const char *domain); -gboolean _nm_l3_config_data_add_domain (NML3ConfigData *self, - int addr_family, - const char *domain); +gboolean nm_l3_config_data_add_search (NML3ConfigData *self, + int addr_family, + const char *search); -gboolean _nm_l3_config_data_add_search (NML3ConfigData *self, - int addr_family, - const char *search); +gboolean nm_l3_config_data_add_dns_option (NML3ConfigData *self, + int addr_family, + const char *dns_option); -gboolean _nm_l3_config_data_add_dns_option (NML3ConfigData *self, - int addr_family, - const char *dns_option); - -gboolean _nm_l3_config_data_set_dns_priority (NML3ConfigData *self, - int addr_family, - int dns_priority); +gboolean nm_l3_config_data_set_dns_priority (NML3ConfigData *self, + int addr_family, + int dns_priority); #endif /* __NM_L3_CONFIG_DATA_H__ */ diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 36c9ad6982..c31548cb18 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -1059,6 +1059,19 @@ nmp_object_ip_route_is_best_defaut_route (const NMPObject *obj) /*****************************************************************************/ +static inline gboolean +nm_platform_dedup_multi_iter_next_obj (NMDedupMultiIter *ipconf_iter, const NMPObject **out_obj, NMPObjectType assert_obj_type) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next (ipconf_iter); + nm_assert ( assert_obj_type == NMP_OBJECT_TYPE_UNKNOWN + || !has_next + || NMP_OBJECT_GET_TYPE (ipconf_iter->current->obj) == assert_obj_type); + NM_SET_OUT (out_obj, has_next ? ipconf_iter->current->obj : NULL); + return has_next; +} + static inline gboolean nm_platform_dedup_multi_iter_next_ip4_address (NMDedupMultiIter *ipconf_iter, const NMPlatformIP4Address **out_address) { From d9547e845215a23163c25379de31a17b25db3b30 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 16:14:47 +0200 Subject: [PATCH 15/16] l3cfg: make NML3ConfigData ref/unref functions const NML3ConfigData is supposed to be used as immutable, ref-counted type. You create it once, initialize it, seal it, and pass (immutable) references around. In such a scheme, having ref/unref functions not operate on const pointers is a major inconvenience. --- src/nm-l3-config-data.c | 71 ++++++++++++++++++++++++----------------- src/nm-l3-config-data.h | 15 +++++---- 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c index a8427576aa..5f66602444 100644 --- a/src/nm-l3-config-data.c +++ b/src/nm-l3-config-data.c @@ -282,73 +282,84 @@ nm_l3_config_data_new (NMDedupMultiIndex *multi_idx, return self; } -NML3ConfigData * -nm_l3_config_data_ref (NML3ConfigData *self) +const NML3ConfigData * +nm_l3_config_data_ref (const NML3ConfigData *self) { nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); - self->ref_count++; + ((NML3ConfigData *) self)->ref_count++; return self; } -NML3ConfigData * -nm_l3_config_data_ref_and_seal (NML3ConfigData *self) +const NML3ConfigData * +nm_l3_config_data_ref_and_seal (const NML3ConfigData *self) { nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); - self->is_sealed = TRUE; - self->ref_count++; + ((NML3ConfigData *) self)->is_sealed = TRUE; + ((NML3ConfigData *) self)->ref_count++; return self; } -NML3ConfigData * -nm_l3_config_data_seal (NML3ConfigData *self) +const NML3ConfigData * +nm_l3_config_data_seal (const NML3ConfigData *self) { nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); - self->is_sealed = TRUE; + ((NML3ConfigData *) self)->is_sealed = TRUE; return self; } gboolean -nm_l3_config_data_is_sealed (NML3ConfigData *self) +nm_l3_config_data_is_sealed (const NML3ConfigData *self) { nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); return self->is_sealed; } void -nm_l3_config_data_unref (NML3ConfigData *self) +nm_l3_config_data_unref (const NML3ConfigData *self) { + NML3ConfigData *mutable; + if (!self) return; nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); - if (--self->ref_count > 0) + + /* NML3ConfigData aims to be an immutable, ref-counted type. The mode of operation + * is to create/initialize the instance once, then seal it and pass around the reference. + * + * That means, also ref/unref operate on const pointers (otherwise, you'd have to cast all + * the time). Hence, we cast away the constness during ref/unref/seal operations. */ + + mutable = (NML3ConfigData *) self; + + if (--mutable->ref_count > 0) return; - nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_addresses_4.parent); - nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_addresses_6.parent); - nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_routes_4.parent); - nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_routes_6.parent); + nm_dedup_multi_index_remove_idx (mutable->multi_idx, &mutable->idx_addresses_4.parent); + nm_dedup_multi_index_remove_idx (mutable->multi_idx, &mutable->idx_addresses_6.parent); + nm_dedup_multi_index_remove_idx (mutable->multi_idx, &mutable->idx_routes_4.parent); + nm_dedup_multi_index_remove_idx (mutable->multi_idx, &mutable->idx_routes_6.parent); - nmp_object_unref (self->best_default_route_4); - nmp_object_unref (self->best_default_route_6); + nmp_object_unref (mutable->best_default_route_4); + nmp_object_unref (mutable->best_default_route_6); - nm_clear_pointer (&self->wins_4, g_array_unref); + nm_clear_pointer (&mutable->wins_4, g_array_unref); - nm_clear_pointer (&self->nameservers_4, g_array_unref); - nm_clear_pointer (&self->nameservers_6, g_array_unref); + nm_clear_pointer (&mutable->nameservers_4, g_array_unref); + nm_clear_pointer (&mutable->nameservers_6, g_array_unref); - nm_clear_pointer (&self->domains_4, g_ptr_array_unref); - nm_clear_pointer (&self->domains_6, g_ptr_array_unref); + nm_clear_pointer (&mutable->domains_4, g_ptr_array_unref); + nm_clear_pointer (&mutable->domains_6, g_ptr_array_unref); - nm_clear_pointer (&self->searches_4, g_ptr_array_unref); - nm_clear_pointer (&self->searches_6, g_ptr_array_unref); + nm_clear_pointer (&mutable->searches_4, g_ptr_array_unref); + nm_clear_pointer (&mutable->searches_6, g_ptr_array_unref); - nm_clear_pointer (&self->dns_options_4, g_ptr_array_unref); - nm_clear_pointer (&self->dns_options_6, g_ptr_array_unref); + nm_clear_pointer (&mutable->dns_options_4, g_ptr_array_unref); + nm_clear_pointer (&mutable->dns_options_6, g_ptr_array_unref); - nm_dedup_multi_index_unref (self->multi_idx); + nm_dedup_multi_index_unref (mutable->multi_idx); - nm_g_slice_free (self); + nm_g_slice_free (mutable); } /*****************************************************************************/ diff --git a/src/nm-l3-config-data.h b/src/nm-l3-config-data.h index 02136b8267..bafba1aec3 100644 --- a/src/nm-l3-config-data.h +++ b/src/nm-l3-config-data.h @@ -12,15 +12,18 @@ typedef struct _NML3ConfigData NML3ConfigData; NML3ConfigData *nm_l3_config_data_new (NMDedupMultiIndex *multi_idx, int ifindex); -NML3ConfigData *nm_l3_config_data_ref (NML3ConfigData *self); -NML3ConfigData *nm_l3_config_data_ref_and_seal (NML3ConfigData *self); -NML3ConfigData *nm_l3_config_data_seal (NML3ConfigData *self); -void nm_l3_config_data_unref (NML3ConfigData *self); +const NML3ConfigData *nm_l3_config_data_ref (const NML3ConfigData *self); +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 (NML3ConfigData *, _nm_auto_unref_l3cfg, nm_l3_config_data_unref); +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) -gboolean nm_l3_config_data_is_sealed (NML3ConfigData *self); +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) + +gboolean nm_l3_config_data_is_sealed (const NML3ConfigData *self); NML3ConfigData *nm_l3_config_data_new_clone (const NML3ConfigData *src, int ifindex); From 99f096577c387a432ede0a0462f312f28220a39d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 23 Jul 2020 17:51:01 +0200 Subject: [PATCH 16/16] l3cfg: add flags for NML3ConfigData Add a flags parameter. That is useful to bundle multiple simple boolean properties, without need to implement individual accessors. --- src/nm-l3-config-data.c | 27 +++++++++++++++++++++++++++ src/nm-l3-config-data.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c index 5f66602444..23d2dd0fae 100644 --- a/src/nm-l3-config-data.c +++ b/src/nm-l3-config-data.c @@ -95,6 +95,8 @@ struct _NML3ConfigData { int ref_count; + NML3ConfigDatFlags flags; + bool is_sealed:1; }; @@ -272,6 +274,7 @@ nm_l3_config_data_new (NMDedupMultiIndex *multi_idx, .multi_idx = nm_dedup_multi_index_ref (multi_idx), .mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT, .llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT, + .flags = NM_L3_CONFIG_DAT_FLAGS_NONE, }; _idx_type_init (&self->idx_addresses_4, NMP_OBJECT_TYPE_IP4_ADDRESS); @@ -392,6 +395,8 @@ nm_l3_config_data_lookup_objs (const NML3ConfigData *self, NMPObjectType obj_typ return nm_dedup_multi_index_lookup_head (self->multi_idx, &idx->parent, NULL); } +/*****************************************************************************/ + int nm_l3_config_data_get_ifindex (const NML3ConfigData *self) { @@ -402,6 +407,28 @@ nm_l3_config_data_get_ifindex (const NML3ConfigData *self) /*****************************************************************************/ +NML3ConfigDatFlags +nm_l3_config_data_get_flags (const NML3ConfigData *self) +{ + nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE)); + + return self->flags; +} + +void +nm_l3_config_data_set_flags_full (NML3ConfigData *self, + NML3ConfigDatFlags flags, + NML3ConfigDatFlags mask) +{ + nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE)); + nm_assert (!NM_FLAGS_ANY (flags, ~mask)); + + self->flags = (self->flags & ~mask) + | (flags & mask); +} + +/*****************************************************************************/ + static gboolean _l3_config_data_add_obj (NMDedupMultiIndex *multi_idx, DedupMultiIdxType *idx_type, diff --git a/src/nm-l3-config-data.h b/src/nm-l3-config-data.h index bafba1aec3..5b81b57e19 100644 --- a/src/nm-l3-config-data.h +++ b/src/nm-l3-config-data.h @@ -8,6 +8,14 @@ #include "nm-setting-ip6-config.h" #include "platform/nm-platform.h" +typedef enum { + NM_L3_CONFIG_DAT_FLAGS_NONE = 0, + + /* if set, then the merge flag NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES gets + * ignored during merge. */ + NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES = (1ull << 0), +} NML3ConfigDatFlags; + typedef struct _NML3ConfigData NML3ConfigData; NML3ConfigData *nm_l3_config_data_new (NMDedupMultiIndex *multi_idx, @@ -98,6 +106,28 @@ int nm_l3_config_data_get_ifindex (const NML3ConfigData *self); /*****************************************************************************/ +NML3ConfigDatFlags nm_l3_config_data_get_flags (const NML3ConfigData *self); + +void nm_l3_config_data_set_flags_full (NML3ConfigData *self, + NML3ConfigDatFlags flags, + NML3ConfigDatFlags mask); + +static inline void +nm_l3_config_data_set_flags (NML3ConfigData *self, + NML3ConfigDatFlags flags) +{ + nm_l3_config_data_set_flags_full (self, flags, flags); +} + +static inline void +nm_l3_config_data_unset_flags (NML3ConfigData *self, + NML3ConfigDatFlags flags) +{ + nm_l3_config_data_set_flags_full (self, NM_L3_CONFIG_DAT_FLAGS_NONE, flags); +} + +/*****************************************************************************/ + gboolean nm_l3_config_data_add_address (NML3ConfigData *self, int addr_family, const NMPObject *obj_new,