From 057744b7229d792585d4efe6b4049947da03468c Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 20 Nov 2017 11:21:58 +0100 Subject: core: drop unused macro argument --- src/nm-ip4-config.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 7c345d2052..93a254b8c6 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -338,7 +338,7 @@ nm_ip_config_get_addr_family (const NMIPConfig *config) g_return_val_if_reached (AF_UNSPEC); } -#define _NM_IP_CONFIG_DISPATCH(config, v4_func, v6_func, dflt, ...) \ +#define _NM_IP_CONFIG_DISPATCH(config, v4_func, v6_func, ...) \ G_STMT_START { \ gconstpointer _config = (config); \ \ @@ -353,55 +353,55 @@ nm_ip_config_get_addr_family (const NMIPConfig *config) static inline int nm_ip_config_get_dns_priority (const NMIPConfig *self) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_dns_priority, nm_ip6_config_get_dns_priority, 0); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_dns_priority, nm_ip6_config_get_dns_priority); } static inline guint nm_ip_config_get_num_nameservers (const NMIPConfig *self) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_nameservers, nm_ip6_config_get_num_nameservers, 0); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_nameservers, nm_ip6_config_get_num_nameservers); } static inline gconstpointer nm_ip_config_get_nameserver (const NMIPConfig *self, guint i) { - _NM_IP_CONFIG_DISPATCH (self, _nm_ip4_config_get_nameserver, nm_ip6_config_get_nameserver, 0, i); + _NM_IP_CONFIG_DISPATCH (self, _nm_ip4_config_get_nameserver, nm_ip6_config_get_nameserver, i); } static inline guint nm_ip_config_get_num_domains (const NMIPConfig *self) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_domains, nm_ip6_config_get_num_domains, 0); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_domains, nm_ip6_config_get_num_domains); } static inline const char * nm_ip_config_get_domain (const NMIPConfig *self, guint i) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_domain, nm_ip6_config_get_domain, NULL, i); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_domain, nm_ip6_config_get_domain, i); } static inline guint nm_ip_config_get_num_searches (const NMIPConfig *self) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_searches, nm_ip6_config_get_num_searches, 0); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_searches, nm_ip6_config_get_num_searches); } static inline const char * nm_ip_config_get_search (const NMIPConfig *self, guint i) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_search, nm_ip6_config_get_search, NULL, i); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_search, nm_ip6_config_get_search, i); } static inline guint nm_ip_config_get_num_dns_options (const NMIPConfig *self) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_dns_options, nm_ip6_config_get_num_dns_options, 0); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_num_dns_options, nm_ip6_config_get_num_dns_options); } static inline const char * nm_ip_config_get_dns_option (const NMIPConfig *self, guint i) { - _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_dns_option, nm_ip6_config_get_dns_option, NULL, i); + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_dns_option, nm_ip6_config_get_dns_option, i); } #endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */ -- cgit v1.2.1 From 4cbf5947796c6d3776e8481644e992558a4b452a Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 20 Nov 2017 11:36:47 +0100 Subject: core: add nm_ipX_config_clone() --- src/nm-ip4-config.c | 11 +++++++++++ src/nm-ip4-config.h | 1 + src/nm-ip6-config.c | 11 +++++++++++ src/nm-ip6-config.h | 1 + src/nm-test-utils-core.h | 24 ------------------------ src/tests/test-ip6-config.c | 6 ++++-- 6 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 499cd9e40e..cbf8ebb447 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -581,6 +581,17 @@ sort_captured_addresses (const CList *lst_a, const CList *lst_b, gconstpointer u NM_FLAGS_HAS (addr_b->n_ifa_flags, IFA_F_SECONDARY); } +NMIP4Config * +nm_ip4_config_clone (const NMIP4Config *self) +{ + NMIP4Config *copy; + + copy = nm_ip4_config_new (nm_ip4_config_get_multi_idx (self), -1); + nm_ip4_config_replace (copy, self, NULL); + + return copy; +} + NMIP4Config * nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex, gboolean capture_resolv_conf) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 93a254b8c6..174ea5113a 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -154,6 +154,7 @@ GType nm_ip4_config_get_type (void); NMIP4Config * nm_ip4_config_new (NMDedupMultiIndex *multi_idx, int ifindex); +NMIP4Config *nm_ip4_config_clone (const NMIP4Config *self); int nm_ip4_config_get_ifindex (const NMIP4Config *self); NMDedupMultiIndex *nm_ip4_config_get_multi_idx (const NMIP4Config *self); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 2cb34968ac..36901ce7a8 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -365,6 +365,17 @@ _nmtst_ip6_config_addresses_sort (NMIP6Config *self) return FALSE; } +NMIP6Config * +nm_ip6_config_clone (const NMIP6Config *self) +{ + NMIP6Config *copy; + + copy = nm_ip6_config_new (nm_ip6_config_get_multi_idx (self), -1); + nm_ip6_config_replace (copy, self, NULL); + + return copy; +} + NMIP6Config * nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary) { diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 2fb8b8a4ad..509a42d68f 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -101,6 +101,7 @@ GType nm_ip6_config_get_type (void); NMIP6Config * nm_ip6_config_new (struct _NMDedupMultiIndex *multi_idx, int ifindex); NMIP6Config * nm_ip6_config_new_cloned (const NMIP6Config *src); +NMIP6Config *nm_ip6_config_clone (const NMIP6Config *self); int nm_ip6_config_get_ifindex (const NMIP6Config *self); struct _NMDedupMultiIndex *nm_ip6_config_get_multi_idx (const NMIP6Config *self); diff --git a/src/nm-test-utils-core.h b/src/nm-test-utils-core.h index 58beadcdf1..a3d9f2a36d 100644 --- a/src/nm-test-utils-core.h +++ b/src/nm-test-utils-core.h @@ -313,18 +313,6 @@ nmtst_ip4_config_new (int ifindex) return nm_ip4_config_new (multi_idx, ifindex); } -static inline NMIP4Config * -nmtst_ip4_config_clone (NMIP4Config *config) -{ - NMIP4Config *copy; - - g_assert (config); - copy = nm_ip4_config_new (nm_ip4_config_get_multi_idx (config), -1); - g_assert (copy); - nm_ip4_config_replace (copy, config, NULL); - return copy; -} - #endif @@ -340,18 +328,6 @@ nmtst_ip6_config_new (int ifindex) return nm_ip6_config_new (multi_idx, ifindex); } -static inline NMIP6Config * -nmtst_ip6_config_clone (NMIP6Config *config) -{ - NMIP6Config *copy; - - g_assert (config); - copy = nm_ip6_config_new (nm_ip6_config_get_multi_idx (config), -1); - g_assert (copy); - nm_ip6_config_replace (copy, config, NULL); - return copy; -} - #endif #endif /* __NM_TEST_UTILS_CORE_H__ */ diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c index bcbeee3e10..5a34547278 100644 --- a/src/tests/test-ip6-config.c +++ b/src/tests/test-ip6-config.c @@ -246,8 +246,10 @@ test_nm_ip6_config_addresses_sort_check (NMIP6Config *config, NMSettingIP6Config int *idx = g_new (int, addr_count); nm_ip6_config_set_privacy (config, use_tempaddr); - copy = nmtst_ip6_config_clone (config); - copy2 = nmtst_ip6_config_clone (config); + copy = nm_ip6_config_clone (config); + g_assert (copy); + copy2 = nm_ip6_config_clone (config); + g_assert (copy2); /* initialize the array of indeces, and keep shuffling them for every @repeat iteration. */ for (i = 0; i < addr_count; i++) -- cgit v1.2.1 From eae63475d9e3ec11bec93ac7d6c5cf2d48de133f Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 30 Nov 2017 11:22:34 +0100 Subject: core: add generic functions for set operations --- src/nm-ip4-config.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 174ea5113a..f53ba02007 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -405,4 +405,54 @@ nm_ip_config_get_dns_option (const NMIPConfig *self, guint i) _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_dns_option, nm_ip6_config_get_dns_option, i); } +#define _NM_IP_CONFIG_DISPATCH_SET_OP(dst, src, v4_func, v6_func, ...) \ + G_STMT_START { \ + gpointer _dst = (dst); \ + gconstpointer _src = (src); \ + int family = nm_ip_config_get_addr_family (_dst); \ + \ + nm_assert (family == nm_ip_config_get_addr_family (_src)); \ + if (family == AF_INET) { \ + v4_func ((NMIP4Config *) _dst, (const NMIP4Config *) _src, ##__VA_ARGS__); \ + } else { \ + nm_assert (family == AF_INET6); \ + v6_func ((NMIP6Config *) _dst, (const NMIP6Config *) _src, ##__VA_ARGS__); \ + } \ + } G_STMT_END + +static inline void +nm_ip_config_intersect (NMIPConfig *dst, + const NMIPConfig *src, + guint32 default_route_metric_penalty) +{ + _NM_IP_CONFIG_DISPATCH_SET_OP (dst, src, + nm_ip4_config_intersect, + nm_ip6_config_intersect, + default_route_metric_penalty); +} + +static inline void +nm_ip_config_subtract (NMIPConfig *dst, + const NMIPConfig *src, + guint32 default_route_metric_penalty) +{ + _NM_IP_CONFIG_DISPATCH_SET_OP (dst, src, + nm_ip4_config_subtract, + nm_ip6_config_subtract, + default_route_metric_penalty); +} + +static inline void +nm_ip_config_merge (NMIPConfig *dst, + const NMIPConfig *src, + NMIPConfigMergeFlags merge_flags, + guint32 default_route_metric_penalty) +{ + _NM_IP_CONFIG_DISPATCH_SET_OP (dst, src, + nm_ip4_config_merge, + nm_ip6_config_merge, + merge_flags, + default_route_metric_penalty); +} + #endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */ -- cgit v1.2.1 From e5a8aba225ff77a8b02a2772c09ae537bea64a8a Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 20 Nov 2017 14:59:32 +0100 Subject: core: add non-destructive ip config intersect function Add a new function to compute the intersection between 2 IP configurations without modifying them. --- src/nm-ip4-config.c | 84 +++++++++++++++++++++++++++++++++++++++++++++------- src/nm-ip4-config.h | 22 ++++++++++++++ src/nm-ip6-config.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++------- src/nm-ip6-config.h | 3 ++ 4 files changed, 172 insertions(+), 22 deletions(-) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index cbf8ebb447..5d3ed94247 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -1477,10 +1477,11 @@ nm_ip4_config_subtract (NMIP4Config *dst, g_object_thaw_notify (G_OBJECT (dst)); } -void -nm_ip4_config_intersect (NMIP4Config *dst, - const NMIP4Config *src, - guint32 default_route_metric_penalty) +static gboolean +_nm_ip4_config_intersect_helper (NMIP4Config *dst, + const NMIP4Config *src, + guint32 default_route_metric_penalty, + gboolean update_dst) { NMIP4ConfigPrivate *dst_priv; const NMIP4ConfigPrivate *src_priv; @@ -1488,15 +1489,16 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMPlatformIP4Address *a; const NMPlatformIP4Route *r; const NMPObject *new_best_default_route; - gboolean changed; + gboolean changed, result = FALSE; - g_return_if_fail (src); - g_return_if_fail (dst); + g_return_val_if_fail (src, FALSE); + g_return_val_if_fail (dst, FALSE); dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst); src_priv = NM_IP4_CONFIG_GET_PRIVATE (src); - g_object_freeze_notify (G_OBJECT (dst)); + if (update_dst) + g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ changed = FALSE; @@ -1506,13 +1508,18 @@ nm_ip4_config_intersect (NMIP4Config *dst, NMP_OBJECT_UP_CAST (a))) continue; + if (!update_dst) + return TRUE; + if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, ipconf_iter.current) != 1) nm_assert_not_reached (); changed = TRUE; } - if (changed) + if (changed) { _notify_addresses (dst); + result = TRUE; + } /* ignore nameservers */ @@ -1544,6 +1551,9 @@ nm_ip4_config_intersect (NMIP4Config *dst, continue; } + if (!update_dst) + return TRUE; + if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, ipconf_iter.current) != 1) nm_assert_not_reached (); @@ -1553,8 +1563,11 @@ nm_ip4_config_intersect (NMIP4Config *dst, nm_assert (changed); _notify (dst, PROP_GATEWAY); } - if (changed) + + if (changed) { _notify_routes (dst); + result = TRUE; + } /* ignore domains */ /* ignore dns searches */ @@ -1562,9 +1575,58 @@ nm_ip4_config_intersect (NMIP4Config *dst, /* ignore NIS */ /* ignore WINS */ - g_object_thaw_notify (G_OBJECT (dst)); + if (update_dst) + g_object_thaw_notify (G_OBJECT (dst)); + return result; } +/** + * nm_ip4_config_intersect: + * @dst: a configuration to be updated + * @src: another configuration + * @default_route_metric_penalty: the default route metric penalty + * + * Computes the intersection between @src and @dst and updates @dst in place + * with the result. + */ +void +nm_ip4_config_intersect (NMIP4Config *dst, + const NMIP4Config *src, + guint32 default_route_metric_penalty) +{ + _nm_ip4_config_intersect_helper (dst, src, default_route_metric_penalty, TRUE); +} + +/** + * nm_ip4_config_intersect_alloc: + * @a: a configuration + * @b: another configuration + * @default_route_metric_penalty: the default route metric penalty + * + * Computes the intersection between @a and @b and returns the result in a newly + * allocated configuration. As a special case, if @a and @b are identical (with + * respect to the only properties considered - addresses and routes) the + * functions returns NULL so that one of existing configuration can be reused + * without allocation. + * + * Returns: the intersection between @a and @b, or %NULL if the result is equal + * to @a and @b. + */ +NMIP4Config * +nm_ip4_config_intersect_alloc (const NMIP4Config *a, + const NMIP4Config *b, + guint32 default_route_metric_penalty) +{ + NMIP4Config *a_copy; + + if (_nm_ip4_config_intersect_helper ((NMIP4Config *) a, b, + default_route_metric_penalty, FALSE)) { + a_copy = nm_ip4_config_clone (a); + _nm_ip4_config_intersect_helper (a_copy, b, default_route_metric_penalty, TRUE); + return a_copy; + } else + return NULL; +} /** * nm_ip4_config_replace: diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index f53ba02007..c614863d03 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -187,6 +187,9 @@ void nm_ip4_config_subtract (NMIP4Config *dst, void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src, guint32 default_route_metric_penalty); +NMIP4Config *nm_ip4_config_intersect_alloc (const NMIP4Config *a, + const NMIP4Config *b, + guint32 default_route_metric_penalty); gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes); void nm_ip4_config_dump (const NMIP4Config *self, const char *detail); @@ -455,4 +458,23 @@ nm_ip_config_merge (NMIPConfig *dst, default_route_metric_penalty); } +static inline NMIPConfig * +nm_ip_config_intersect_alloc (const NMIPConfig *a, + const NMIPConfig *b, + guint32 default_route_metric_penalty) +{ + int family; + + family = nm_ip_config_get_addr_family (a); + nm_assert (family == nm_ip_config_get_addr_family (b)); + + if (family == AF_INET) + return (NMIPConfig *) nm_ip4_config_intersect_alloc ((const NMIP4Config *) a, + (const NMIP4Config *) b, + default_route_metric_penalty); + else + return (NMIPConfig *) nm_ip6_config_intersect_alloc ((const NMIP6Config *) a, + (const NMIP6Config *) b, + default_route_metric_penalty); +} #endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 36901ce7a8..d3c963aab2 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -1081,26 +1081,28 @@ nm_ip6_config_subtract (NMIP6Config *dst, g_object_thaw_notify (G_OBJECT (dst)); } -void -nm_ip6_config_intersect (NMIP6Config *dst, - const NMIP6Config *src, - guint32 default_route_metric_penalty) +static gboolean +_nm_ip6_config_intersect_helper (NMIP6Config *dst, + const NMIP6Config *src, + guint32 default_route_metric_penalty, + gboolean update_dst) { NMIP6ConfigPrivate *dst_priv; const NMIP6ConfigPrivate *src_priv; NMDedupMultiIter ipconf_iter; const NMPlatformIP6Address *a; const NMPlatformIP6Route *r; - gboolean changed; + gboolean changed, result = FALSE; const NMPObject *new_best_default_route; - g_return_if_fail (src); - g_return_if_fail (dst); + g_return_val_if_fail (src, FALSE); + g_return_val_if_fail (dst, FALSE); dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst); src_priv = NM_IP6_CONFIG_GET_PRIVATE (src); - g_object_freeze_notify (G_OBJECT (dst)); + if (update_dst) + g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ changed = FALSE; @@ -1110,13 +1112,18 @@ nm_ip6_config_intersect (NMIP6Config *dst, NMP_OBJECT_UP_CAST (a))) continue; + if (!update_dst) + return TRUE; + if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, ipconf_iter.current) != 1) nm_assert_not_reached (); changed = TRUE; } - if (changed) + if (changed) { _notify_addresses (dst); + result = TRUE; + } /* ignore nameservers */ @@ -1148,6 +1155,9 @@ nm_ip6_config_intersect (NMIP6Config *dst, continue; } + if (!update_dst) + return TRUE; + if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, ipconf_iter.current) != 1) nm_assert_not_reached (); @@ -1157,14 +1167,67 @@ nm_ip6_config_intersect (NMIP6Config *dst, nm_assert (changed); _notify (dst, PROP_GATEWAY); } - if (changed) + if (changed) { _notify_routes (dst); + result = TRUE; + } /* ignore domains */ /* ignore dns searches */ /* ignore dns options */ - g_object_thaw_notify (G_OBJECT (dst)); + if (update_dst) + g_object_thaw_notify (G_OBJECT (dst)); + + return result; +} + +/** + * nm_ip6_config_intersect: + * @dst: a configuration to be updated + * @src: another configuration + * @default_route_metric_penalty: the default route metric penalty + * + * Computes the intersection between @src and @dst and updates @dst in place + * with the result. + */ +void +nm_ip6_config_intersect (NMIP6Config *dst, + const NMIP6Config *src, + guint32 default_route_metric_penalty) +{ + _nm_ip6_config_intersect_helper (dst, src, default_route_metric_penalty, TRUE); +} + +/** + * nm_ip6_config_intersect_alloc: + * @a: a configuration + * @b: another configuration + * @default_route_metric_penalty: the default route metric penalty + * + * Computes the intersection between @a and @b and returns the result in a newly + * allocated configuration. As a special case, if @a and @b are identical (with + * respect to the only properties considered - addresses and routes) the + * functions returns NULL so that one of existing configuration can be reused + * without allocation. + * + * Returns: the intersection between @a and @b, or %NULL if the result is equal + * to @a and @b. + */ +NMIP6Config * +nm_ip6_config_intersect_alloc (const NMIP6Config *a, + const NMIP6Config *b, + guint32 default_route_metric_penalty) +{ + NMIP6Config *a_copy; + + if (_nm_ip6_config_intersect_helper ((NMIP6Config *) a, b, + default_route_metric_penalty, FALSE)) { + a_copy = nm_ip6_config_clone (a); + _nm_ip6_config_intersect_helper (a_copy, b, default_route_metric_penalty, TRUE); + return a_copy; + } else + return NULL; } /** diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 509a42d68f..34d98b034a 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -134,6 +134,9 @@ void nm_ip6_config_subtract (NMIP6Config *dst, void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src, guint32 default_route_metric_penalty); +NMIP6Config *nm_ip6_config_intersect_alloc (const NMIP6Config *a, + const NMIP6Config *b, + guint32 default_route_metric_penalty); gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes); void nm_ip6_config_dump (const NMIP6Config *self, const char *detail); -- cgit v1.2.1 From f4cbed3d4ff4e91e83f42c63b3602efa014ed72f Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 15 Nov 2017 21:42:52 +0100 Subject: device: don't force a restart of IP configuration on reapply Restarting the IP configuration removes addresses and routes for a short time breaking connectivity. The reapply process should have the minimal impact possible. https://bugzilla.gnome.org/show_bug.cgi?id=790061 --- src/devices/nm-device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index f79b85e8c2..a8fd6cace7 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -9416,8 +9416,8 @@ check_and_reapply_connection (NMDevice *self, s_ip6_old = nm_connection_get_setting_ip6_config (con_old); s_ip6_new = nm_connection_get_setting_ip6_config (con_new); - nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new, TRUE); - nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new, TRUE); + nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new, FALSE); + nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new, FALSE); reactivate_proxy_config (self); -- cgit v1.2.1 From 898b978e365a94b5c5caf2ab17b014fbc0b1cb33 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 15 Nov 2017 21:47:13 +0100 Subject: device: remove 'force_restart' argument from reactivate functions It is now unused. https://bugzilla.gnome.org/show_bug.cgi?id=790061 --- src/devices/nm-device-vlan.c | 2 +- src/devices/nm-device.c | 44 ++++++++++++++++++-------------------------- src/devices/nm-device.h | 6 ++---- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 81512335c7..21d433eb38 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -134,7 +134,7 @@ parent_hwaddr_maybe_changed (NMDevice *parent, */ s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) - nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6, FALSE); + nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6); } } diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index a8fd6cace7..beda3b518d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -9096,8 +9096,7 @@ _nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, void nm_device_reactivate_ip4_config (NMDevice *self, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new, - gboolean force_restart) + NMSettingIPConfig *s_ip4_new) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -9114,17 +9113,14 @@ nm_device_reactivate_ip4_config (NMDevice *self, nm_device_get_route_table (self, AF_INET, TRUE), nm_device_get_route_metric (self, AF_INET)); - if (!force_restart) { - method_old = s_ip4_old - ? nm_setting_ip_config_get_method (s_ip4_old) - : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - method_new = s_ip4_new - ? nm_setting_ip_config_get_method (s_ip4_new) - : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - force_restart = !nm_streq0 (method_old, method_new); - } + method_old = s_ip4_old + ? nm_setting_ip_config_get_method (s_ip4_old) + : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + method_new = s_ip4_new + ? nm_setting_ip_config_get_method (s_ip4_new) + : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - if (force_restart) { + if (!nm_streq0 (method_old, method_new)) { _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET, IP_WAIT); if (!nm_device_activate_stage3_ip4_start (self)) @@ -9139,8 +9135,7 @@ nm_device_reactivate_ip4_config (NMDevice *self, void nm_device_reactivate_ip6_config (NMDevice *self, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new, - gboolean force_restart) + NMSettingIPConfig *s_ip6_new) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -9157,17 +9152,14 @@ nm_device_reactivate_ip6_config (NMDevice *self, nm_device_get_route_table (self, AF_INET6, TRUE), nm_device_get_route_metric (self, AF_INET6)); - if (!force_restart) { - method_old = s_ip6_old - ? nm_setting_ip_config_get_method (s_ip6_old) - : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - method_new = s_ip6_new - ? nm_setting_ip_config_get_method (s_ip6_new) - : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - force_restart = !nm_streq0 (method_old, method_new); - } + method_old = s_ip6_old + ? nm_setting_ip_config_get_method (s_ip6_old) + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + method_new = s_ip6_new + ? nm_setting_ip_config_get_method (s_ip6_new) + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - if (force_restart) { + if (!nm_streq0 (method_old, method_new)) { _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET6, IP_WAIT); if (!nm_device_activate_stage3_ip6_start (self)) @@ -9416,8 +9408,8 @@ check_and_reapply_connection (NMDevice *self, s_ip6_old = nm_connection_get_setting_ip6_config (con_old); s_ip6_new = nm_connection_get_setting_ip6_config (con_new); - nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new, FALSE); - nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new, FALSE); + nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); + nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); reactivate_proxy_config (self); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 810a613dde..42107ce481 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -752,12 +752,10 @@ void nm_device_update_firewall_zone (NMDevice *self); void nm_device_update_metered (NMDevice *self); void nm_device_reactivate_ip4_config (NMDevice *device, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new, - gboolean force_restart); + NMSettingIPConfig *s_ip4_new); void nm_device_reactivate_ip6_config (NMDevice *device, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new, - gboolean force_restart); + NMSettingIPConfig *s_ip6_new); gboolean nm_device_update_hw_address (NMDevice *self); void nm_device_update_initial_hw_address (NMDevice *self); -- cgit v1.2.1 From 7217ec09e34324e14a0a9d8b519e9cc1aa2b98b4 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Fri, 17 Nov 2017 16:39:40 +0100 Subject: device: restore original dynamic IPv4 configuration on reapply The dynamic IPv4 configuration from DHCP/PPP/... and WWAN is stored in priv->{dev,wwan}_ip4_config; when the user removes externally an address or a route, we prune it from those configurations. Therefore such addresses and routes can't be restored on a device reapply. Introduce an AppliedConfig structure that stores both the original and the current (after external changes) configuration so that we can restore the original one on reapply. --- src/devices/nm-device.c | 131 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 43 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index beda3b518d..d24d02765c 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -152,6 +152,12 @@ typedef enum { FIREWALL_STATE_WAIT_IP_CONFIG, } FirewallState; +typedef struct { + NMIPConfig *orig; /* the original configuration applied to the device */ + NMIPConfig *current; /* configuration after external changes. NULL means + that the original configuration didn't change. */ +} AppliedConfig; + /*****************************************************************************/ enum { @@ -373,9 +379,9 @@ typedef struct _NMDevicePrivate { IpState ip4_state_; }; NMIP4Config * con_ip4_config; /* config from the setting */ - NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ + AppliedConfig dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ + AppliedConfig wwan_ip4_config; /* WWAN configuration */ NMIP4Config * ext_ip4_config; /* Stuff added outside NM */ - NMIP4Config * wwan_ip4_config; /* WWAN configuration */ GSList * vpn4_configs; /* VPNs which use this device */ bool v4_has_shadowed_routes; @@ -695,6 +701,27 @@ _ip6_config_new (NMDevice *self) nm_device_get_ip_ifindex (self)); } +static void +applied_config_clear (AppliedConfig *config) +{ + g_clear_object (&config->current); + g_clear_object (&config->orig); +} + +static void +applied_config_init (AppliedConfig *config, gpointer ip_config) +{ + nm_g_object_ref (ip_config); + applied_config_clear (config); + config->orig = ip_config; +} + +static NMIPConfig * +applied_config_get_current (AppliedConfig *config) +{ + return config->current ?: config->orig; +} + /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_sys_iface_state_to_str, NMDeviceSysIfaceState, @@ -5625,8 +5652,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) nm_clear_g_source (&priv->ipv4ll_timeout); nm_device_activate_schedule_ip4_config_result (self, config); } else if (priv->ip4_state == IP_DONE) { - g_clear_object (&priv->dev_ip4_config); - priv->dev_ip4_config = g_object_ref (config); + applied_config_init (&priv->dev_ip4_config, config); if (!ip4_config_merge_and_apply (self, TRUE)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); @@ -5811,7 +5837,7 @@ ip4_config_merge_and_apply (NMDevice *self, NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; gboolean success; - NMIP4Config *composite; + NMIP4Config *composite, *config; gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; gboolean ignore_default_routes = FALSE; @@ -5849,8 +5875,9 @@ ip4_config_merge_and_apply (NMDevice *self, if (commit) priv->default_route_metric_penalty_ip4_has = default_route_metric_penalty_detect (self); - if (priv->dev_ip4_config) { - nm_ip4_config_merge (composite, priv->dev_ip4_config, + config = (NMIP4Config *) applied_config_get_current (&priv->dev_ip4_config); + if (config) { + nm_ip4_config_merge (composite, config, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), @@ -5866,8 +5893,9 @@ ip4_config_merge_and_apply (NMDevice *self, /* Merge WWAN config *last* to ensure modem-given settings overwrite * any external stuff set by pppd or other scripts. */ - if (priv->wwan_ip4_config) { - nm_ip4_config_merge (composite, priv->wwan_ip4_config, + config = (NMIP4Config *) applied_config_get_current (&priv->wwan_ip4_config); + if (config) { + nm_ip4_config_merge (composite, config, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), @@ -5908,8 +5936,7 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) g_return_val_if_fail (config, FALSE); - g_clear_object (&priv->dev_ip4_config); - priv->dev_ip4_config = g_object_ref (config); + applied_config_init (&priv->dev_ip4_config, config); if (!ip4_config_merge_and_apply (self, TRUE)) { _LOGW (LOGD_DHCP4, "failed to update IPv4 config for DHCP change."); @@ -8578,7 +8605,6 @@ activate_stage5_ip4_config_result (NMDevice *self) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); } - /* NULL to use the existing priv->dev_ip4_config */ if (!ip4_config_merge_and_apply (self, TRUE)) { _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED); @@ -8627,10 +8653,7 @@ nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *conf g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - g_clear_object (&priv->dev_ip4_config); - if (config) - priv->dev_ip4_config = g_object_ref (config); - + applied_config_init (&priv->dev_ip4_config, config); activation_source_schedule (self, activate_stage5_ip4_config_result, AF_INET); } @@ -9107,6 +9130,8 @@ nm_device_reactivate_ip4_config (NMDevice *self, if (priv->ip4_state != IP_NONE) { g_clear_object (&priv->con_ip4_config); g_clear_object (&priv->ext_ip4_config); + g_clear_object (&priv->dev_ip4_config.current); + g_clear_object (&priv->wwan_ip4_config.current); priv->con_ip4_config = _ip4_config_new (self); nm_ip4_config_merge_setting (priv->con_ip4_config, s_ip4_new, @@ -10144,7 +10169,7 @@ nm_device_set_ip4_config (NMDevice *self, _LOGD (LOGD_IP4, "ip4-config: clear IP4Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); /* Device config is invalid if combined config is invalid */ - g_clear_object (&priv->dev_ip4_config); + applied_config_clear (&priv->dev_ip4_config); } concheck_periodic_update (self); @@ -10242,14 +10267,7 @@ nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->wwan_ip4_config == config) - return; - - g_clear_object (&priv->wwan_ip4_config); - if (config) - priv->wwan_ip4_config = g_object_ref (config); - - /* NULL to use existing configs */ + applied_config_init (&priv->wwan_ip4_config, config); if (!ip4_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "failed to set WWAN IPv4 configuration"); } @@ -10970,6 +10988,32 @@ capture_lease_config (NMDevice *self, } } +static void +intersect_ext_config (NMDevice *self, AppliedConfig *config) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMIPConfig *ext; + guint32 penalty; + int family; + + if (!config->orig) + return; + + family = nm_ip_config_get_addr_family (config->orig); + penalty = default_route_metric_penalty_get (self, family); + ext = family == AF_INET + ? (NMIPConfig *) priv->ext_ip4_config + : (NMIPConfig *) priv->ext_ip6_config; + + if (config->current) + nm_ip_config_intersect (config->current, ext, penalty); + else { + config->current = nm_ip_config_intersect_alloc (config->orig, + ext, + penalty); + } +} + static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs) { @@ -10996,8 +11040,11 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea capture_resolv_conf); if (priv->ext_ip4_config) { if (initial) { - g_clear_object (&priv->dev_ip4_config); - capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL); + applied_config_clear (&priv->dev_ip4_config); + capture_lease_config (self, + priv->ext_ip4_config, + (NMIP4Config **) &priv->dev_ip4_config.orig, + NULL, NULL); } if (intersect_configs) { @@ -11009,14 +11056,10 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config, default_route_metric_penalty_get (self, AF_INET)); } - if (priv->dev_ip4_config) { - nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config, - default_route_metric_penalty_get (self, AF_INET)); - } - if (priv->wwan_ip4_config) { - nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config, - default_route_metric_penalty_get (self, AF_INET)); - } + + intersect_ext_config (self, &priv->dev_ip4_config); + intersect_ext_config (self, &priv->wwan_ip4_config); + for (iter = priv->vpn4_configs; iter; iter = iter->next) nm_ip4_config_intersect (iter->data, priv->ext_ip4_config, 0); } @@ -11028,13 +11071,15 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config, default_route_metric_penalty_get (self, AF_INET)); } - if (priv->dev_ip4_config) { - nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config, - default_route_metric_penalty_get (self, AF_INET)); + if (applied_config_get_current (&priv->dev_ip4_config)) { + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip4_config, + applied_config_get_current (&priv->dev_ip4_config), + default_route_metric_penalty_get (self, AF_INET)); } - if (priv->wwan_ip4_config) { - nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config, - default_route_metric_penalty_get (self, AF_INET)); + if (applied_config_get_current (&priv->wwan_ip4_config)) { + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip4_config, + applied_config_get_current (&priv->wwan_ip4_config), + default_route_metric_penalty_get (self, AF_INET)); } for (iter = priv->vpn4_configs; iter; iter = iter->next) nm_ip4_config_subtract (priv->ext_ip4_config, iter->data, 0); @@ -12429,9 +12474,9 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) nm_device_set_ip6_config (self, NULL, TRUE); g_clear_object (&priv->proxy_config); g_clear_object (&priv->con_ip4_config); - g_clear_object (&priv->dev_ip4_config); + applied_config_clear (&priv->dev_ip4_config); + applied_config_clear (&priv->wwan_ip4_config); g_clear_object (&priv->ext_ip4_config); - g_clear_object (&priv->wwan_ip4_config); g_clear_object (&priv->ip4_config); g_clear_object (&priv->con_ip6_config); g_clear_object (&priv->ac_ip6_config); -- cgit v1.2.1 From 0decb9eac614a9a98b3fc5a48307a2e2b63ae36e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 30 Nov 2017 14:11:04 +0100 Subject: device: restore original dynamic IPv6 configuration on reapply --- src/devices/nm-device.c | 253 ++++++++++++++++++++++++++++++--------------- src/nm-ip4-config.h | 49 +++++++++ src/platform/nm-platform.h | 2 + 3 files changed, 222 insertions(+), 82 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index d24d02765c..200cc42e77 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -435,7 +435,8 @@ typedef struct _NMDevicePrivate { IpState ip6_state_; }; NMIP6Config * con_ip6_config; /* config from the setting */ - NMIP6Config * wwan_ip6_config; + AppliedConfig wwan_ip6_config; + AppliedConfig ac_ip6_config; /* config from IPv6 autoconfiguration */ NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */ GSList * vpn6_configs; /* VPNs which use this device */ @@ -448,8 +449,6 @@ typedef struct _NMDevicePrivate { gulong ndisc_changed_id; gulong ndisc_timeout_id; NMSettingIP6ConfigPrivacy ndisc_use_tempaddr; - /* IP6 config from autoconf */ - NMIP6Config * ac_ip6_config; guint linklocal6_timeout_id; guint8 linklocal6_dad_counter; @@ -463,7 +462,7 @@ typedef struct _NMDevicePrivate { gulong prefix_sigid; NMDhcp6Config * config; /* IP6 config from DHCP */ - NMIP6Config * ip6_config; + AppliedConfig ip6_config; /* Event ID of the current IP6 config from DHCP */ char * event_id; guint restart_id; @@ -701,6 +700,16 @@ _ip6_config_new (NMDevice *self) nm_device_get_ip_ifindex (self)); } +static NMIPConfig * +_ip_config_new (NMDevice *self, int addr_family) +{ + nm_assert_addr_family (addr_family); + + return addr_family == AF_INET + ? (gpointer) _ip4_config_new (self) + : (gpointer) _ip6_config_new (self); +} + static void applied_config_clear (AppliedConfig *config) { @@ -716,12 +725,80 @@ applied_config_init (AppliedConfig *config, gpointer ip_config) config->orig = ip_config; } +static void +applied_config_init_new (AppliedConfig *config, NMDevice *self, int addr_family) +{ + gs_unref_object NMIPConfig *c = _ip_config_new (self, addr_family); + + applied_config_init (config, c); +} + static NMIPConfig * applied_config_get_current (AppliedConfig *config) { return config->current ?: config->orig; } +static void +applied_config_add_address (AppliedConfig *config, const NMPlatformIPAddress *address) +{ + if (config->orig) + nm_ip_config_add_address (config->orig, address); + else + nm_assert (!config->current); + + if (config->current) + nm_ip_config_add_address (config->current, address); +} + +static void +applied_config_add_nameserver (AppliedConfig *config, const NMIPAddr *ns) +{ + if (config->orig) + nm_ip_config_add_nameserver (config->orig, ns); + else + nm_assert (!config->current); + + if (config->current) + nm_ip_config_add_nameserver (config->current, ns); +} + +static void +applied_config_add_search (AppliedConfig *config, const char *new) +{ + if (config->orig) + nm_ip_config_add_search (config->orig, new); + else + nm_assert (!config->current); + + if (config->current) + nm_ip_config_add_search (config->current, new); +} + +static void +applied_config_reset_searches (AppliedConfig *config) +{ + if (config->orig) + nm_ip_config_reset_searches (config->orig); + else + nm_assert (!config->current); + + if (config->current) + nm_ip_config_reset_searches (config->current); +} + +static void +applied_config_reset_nameservers (AppliedConfig *config) +{ + if (config->orig) + nm_ip_config_reset_nameservers (config->orig); + else + nm_assert (!config->current); + + if (config->current) + nm_ip_config_reset_nameservers (config->current); +} + /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_sys_iface_state_to_str, NMDeviceSysIfaceState, @@ -6474,7 +6551,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE; - g_clear_object (&priv->dhcp6.ip6_config); + applied_config_clear (&priv->dhcp6.ip6_config); g_clear_pointer (&priv->dhcp6.event_id, g_free); nm_clear_g_source (&priv->dhcp6.restart_id); @@ -6504,7 +6581,7 @@ ip6_config_merge_and_apply (NMDevice *self, NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; gboolean success; - NMIP6Config *composite; + NMIP6Config *composite, *config; gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; gboolean ignore_default_routes = FALSE; @@ -6552,15 +6629,18 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route_metric_penalty_ip6_has = default_route_metric_penalty_detect (self); /* Merge all the IP configs into the composite config */ - if (priv->ac_ip6_config) { - nm_ip6_config_merge (composite, priv->ac_ip6_config, + config = (NMIP6Config *) applied_config_get_current (&priv->ac_ip6_config); + if (config) { + nm_ip6_config_merge (composite, config, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), default_route_metric_penalty_get (self, AF_INET6)); } - if (priv->dhcp6.ip6_config) { - nm_ip6_config_merge (composite, priv->dhcp6.ip6_config, + + config = (NMIP6Config *) applied_config_get_current (&priv->dhcp6.ip6_config); + if (config) { + nm_ip6_config_merge (composite, config, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), @@ -6576,8 +6656,9 @@ ip6_config_merge_and_apply (NMDevice *self, /* Merge WWAN config *last* to ensure modem-given settings overwrite * any external stuff set by pppd or other scripts. */ - if (priv->wwan_ip6_config) { - nm_ip6_config_merge (composite, priv->wwan_ip6_config, + config = (NMIP6Config *) applied_config_get_current (&priv->wwan_ip6_config); + if (config) { + nm_ip6_config_merge (composite, config, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), @@ -6633,7 +6714,7 @@ dhcp6_lease_change (NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; - if (priv->dhcp6.ip6_config == NULL) { + if (!applied_config_get_current (&priv->dhcp6.ip6_config)) { _LOGW (LOGD_DHCP6, "failed to get DHCPv6 config for rebind"); return FALSE; } @@ -6797,22 +6878,22 @@ dhcp6_state_changed (NMDhcpClient *client, const NMPlatformIP6Address *a; nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6_config, &a) - nm_ip6_config_add_address (priv->dhcp6.ip6_config, a); + applied_config_add_address (&priv->dhcp6.ip6_config, NM_PLATFORM_IP_ADDRESS_CAST (a)); } else { - g_clear_object (&priv->dhcp6.ip6_config); g_clear_pointer (&priv->dhcp6.event_id, g_free); if (ip6_config) { - priv->dhcp6.ip6_config = g_object_ref (ip6_config); + applied_config_init (&priv->dhcp6.ip6_config, ip6_config); priv->dhcp6.event_id = g_strdup (event_id); nm_dhcp6_config_set_options (priv->dhcp6.config, options); _notify (self, PROP_DHCP6_CONFIG); - } + } else + applied_config_clear (&priv->dhcp6.ip6_config); } priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX; if (priv->ip6_state == IP_CONF) { - if (priv->dhcp6.ip6_config == NULL) { + if (!applied_config_get_current (&priv->dhcp6.ip6_config)) { nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED); break; } @@ -6932,8 +7013,8 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll) nm_exported_object_clear_and_unexport (&priv->dhcp6.config); priv->dhcp6.config = nm_dhcp6_config_new (); - g_warn_if_fail (priv->dhcp6.ip6_config == NULL); - g_clear_object (&priv->dhcp6.ip6_config); + nm_assert (!applied_config_get_current (&priv->dhcp6.ip6_config)); + applied_config_clear (&priv->dhcp6.ip6_config); g_clear_pointer (&priv->dhcp6.event_id, g_free); connection = nm_device_get_applied_connection (self); @@ -7016,12 +7097,12 @@ nm_device_use_ip6_subnet (NMDevice *self, const NMPlatformIP6Address *subnet) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMPlatformIP6Address address = *subnet; - if (!priv->ac_ip6_config) - priv->ac_ip6_config = _ip6_config_new (self); + if (!applied_config_get_current (&priv->ac_ip6_config)) + applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6); /* Assign a ::1 address in the subnet for us. */ address.address.s6_addr32[3] |= htonl (1); - nm_ip6_config_add_address (priv->ac_ip6_config, &address); + applied_config_add_address (&priv->ac_ip6_config, NM_PLATFORM_IP_ADDRESS_CAST (&address)); _LOGD (LOGD_IP6, "ipv6-pd: using %s address (preferred for %u seconds)", nm_utils_inet6_ntop (&address.address, NULL), @@ -7043,11 +7124,11 @@ nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device) NMIP6Config *from_config = NULL; guint i, len; - if (priv->ac_ip6_config) { - nm_ip6_config_reset_nameservers (priv->ac_ip6_config); - nm_ip6_config_reset_searches (priv->ac_ip6_config); + if (applied_config_get_current (&priv->ac_ip6_config)) { + applied_config_reset_nameservers (&priv->ac_ip6_config); + applied_config_reset_searches (&priv->ac_ip6_config); } else - priv->ac_ip6_config = _ip6_config_new (self); + applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6); if (from_device) from_config = nm_device_get_ip6_config (from_device); @@ -7056,14 +7137,14 @@ nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device) len = nm_ip6_config_get_num_nameservers (from_config); for (i = 0; i < len; i++) { - nm_ip6_config_add_nameserver (priv->ac_ip6_config, - nm_ip6_config_get_nameserver (from_config, i)); + applied_config_add_nameserver (&priv->ac_ip6_config, + (const NMIPAddr *) nm_ip6_config_get_nameserver (from_config, i)); } len = nm_ip6_config_get_num_searches (from_config); for (i = 0; i < len; i++) { - nm_ip6_config_add_search (priv->ac_ip6_config, - nm_ip6_config_get_search (from_config, i)); + applied_config_add_search (&priv->ac_ip6_config, + nm_ip6_config_get_search (from_config, i)); } if (!ip6_config_merge_and_apply (self, TRUE)) @@ -7503,8 +7584,8 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in g_return_if_fail (priv->act_request); - if (!priv->ac_ip6_config) - priv->ac_ip6_config = _ip6_config_new (self); + if (!applied_config_get_current (&priv->ac_ip6_config)) + applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6); if (changed & NM_NDISC_CONFIG_ADDRESSES) { guint8 plen; @@ -7525,16 +7606,23 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in } else plen = 128; - nm_ip6_config_reset_addresses_ndisc (priv->ac_ip6_config, + nm_ip6_config_reset_addresses_ndisc ((NMIP6Config *) priv->ac_ip6_config.orig, rdata->addresses, rdata->addresses_n, plen, ifa_flags); + if (priv->ac_ip6_config.current) { + nm_ip6_config_reset_addresses_ndisc ((NMIP6Config *) priv->ac_ip6_config.current, + rdata->addresses, + rdata->addresses_n, + plen, + ifa_flags); + } } if (NM_FLAGS_ANY (changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) { - nm_ip6_config_reset_routes_ndisc (priv->ac_ip6_config, + nm_ip6_config_reset_routes_ndisc ((NMIP6Config *) priv->ac_ip6_config.orig, rdata->gateways, rdata->gateways_n, rdata->routes, @@ -7543,22 +7631,34 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in nm_device_get_route_metric (self, AF_INET6), nm_platform_check_kernel_support (nm_device_get_platform (self), NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF)); + if (priv->ac_ip6_config.current) { + nm_ip6_config_reset_routes_ndisc ((NMIP6Config *) priv->ac_ip6_config.current, + rdata->gateways, + rdata->gateways_n, + rdata->routes, + rdata->routes_n, + nm_device_get_route_table (self, AF_INET6, TRUE), + nm_device_get_route_metric (self, AF_INET6), + nm_platform_check_kernel_support (nm_device_get_platform (self), + NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF)); + } + } if (changed & NM_NDISC_CONFIG_DNS_SERVERS) { /* Rebuild DNS server list from neighbor discovery cache. */ - nm_ip6_config_reset_nameservers (priv->ac_ip6_config); + applied_config_reset_nameservers (&priv->ac_ip6_config); for (i = 0; i < rdata->dns_servers_n; i++) - nm_ip6_config_add_nameserver (priv->ac_ip6_config, &rdata->dns_servers[i].address); + applied_config_add_nameserver (&priv->ac_ip6_config, (const NMIPAddr *) &rdata->dns_servers[i].address); } if (changed & NM_NDISC_CONFIG_DNS_DOMAINS) { /* Rebuild domain list from neighbor discovery cache. */ - nm_ip6_config_reset_searches (priv->ac_ip6_config); + applied_config_reset_searches (&priv->ac_ip6_config); for (i = 0; i < rdata->dns_domains_n; i++) - nm_ip6_config_add_search (priv->ac_ip6_config, rdata->dns_domains[i].domain); + applied_config_add_search (&priv->ac_ip6_config, rdata->dns_domains[i].domain); } if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) { @@ -7703,11 +7803,8 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) connection = nm_device_get_applied_connection (self); g_assert (connection); - g_warn_if_fail (priv->ac_ip6_config == NULL); - if (priv->ac_ip6_config) { - g_object_unref (priv->ac_ip6_config); - priv->ac_ip6_config = NULL; - } + nm_assert (!applied_config_get_current (&priv->ac_ip6_config)); + applied_config_clear (&priv->ac_ip6_config); g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); @@ -7765,7 +7862,7 @@ addrconf6_cleanup (NMDevice *self) nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE); - g_clear_object (&priv->ac_ip6_config); + applied_config_clear (&priv->ac_ip6_config); g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); g_clear_object (&priv->ndisc); @@ -8145,8 +8242,8 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) /* Here we get a static IPv6 config, like for Shared where it's * autogenerated or from modems where it comes from ModemManager. */ - g_warn_if_fail (priv->ac_ip6_config == NULL); - priv->ac_ip6_config = ip6_config; + nm_assert (!applied_config_get_current (&priv->ac_ip6_config)); + applied_config_init (&priv->ac_ip6_config, ip6_config); nm_device_activate_schedule_ip6_config_result (self); } else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) { _set_ip_state (self, AF_INET6, IP_DONE); @@ -8686,10 +8783,10 @@ static NMIP6Config * dad6_get_pending_addresses (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMIP6Config *confs[] = { priv->ac_ip6_config, - priv->dhcp6.ip6_config, + NMIP6Config *confs[] = { (NMIP6Config *) applied_config_get_current (&priv->ac_ip6_config), + (NMIP6Config *) applied_config_get_current (&priv->dhcp6.ip6_config), priv->con_ip6_config, - priv->wwan_ip6_config }; + (NMIP6Config *) applied_config_get_current (&priv->wwan_ip6_config) }; const NMPlatformIP6Address *addr, *pl_addr; NMIP6Config *dad6_config = NULL; NMDedupMultiIter ipconf_iter; @@ -8756,7 +8853,7 @@ activate_stage5_ip6_config_commit (NMDevice *self) if (ip6_config_merge_and_apply (self, TRUE)) { if ( priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE && priv->ip6_state == IP_CONF) { - if (priv->dhcp6.ip6_config) { + if (applied_config_get_current (&priv->dhcp6.ip6_config)) { /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ @@ -9171,6 +9268,9 @@ nm_device_reactivate_ip6_config (NMDevice *self, if (priv->ip6_state != IP_NONE) { g_clear_object (&priv->con_ip6_config); g_clear_object (&priv->ext_ip6_config); + g_clear_object (&priv->ac_ip6_config.current); + g_clear_object (&priv->dhcp6.ip6_config.current); + g_clear_object (&priv->wwan_ip6_config.current); priv->con_ip6_config = _ip6_config_new (self); nm_ip6_config_merge_setting (priv->con_ip6_config, s_ip6_new, @@ -10402,14 +10502,7 @@ nm_device_set_wwan_ip6_config (NMDevice *self, NMIP6Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->wwan_ip6_config == config) - return; - - g_clear_object (&priv->wwan_ip6_config); - if (config) - priv->wwan_ip6_config = g_object_ref (config); - - /* NULL to use existing configs */ + applied_config_init (&priv->wwan_ip6_config, config); if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed to set WWAN IPv6 configuration"); } @@ -11108,18 +11201,11 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config, default_route_metric_penalty_get (self, AF_INET6)); } - if (priv->ac_ip6_config) { - nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config, - default_route_metric_penalty_get (self, AF_INET6)); - } - if (priv->dhcp6.ip6_config) { - nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config, - default_route_metric_penalty_get (self, AF_INET6)); - } - if (priv->wwan_ip6_config) { - nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config, - default_route_metric_penalty_get (self, AF_INET6)); - } + + intersect_ext_config (self, &priv->ac_ip6_config); + intersect_ext_config (self, &priv->dhcp6.ip6_config); + intersect_ext_config (self, &priv->wwan_ip6_config); + for (iter = priv->vpn6_configs; iter; iter = iter->next) nm_ip6_config_intersect (iter->data, priv->ext_ip6_config, 0); } @@ -11131,17 +11217,20 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config, default_route_metric_penalty_get (self, AF_INET6)); } - if (priv->ac_ip6_config) { - nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config, - default_route_metric_penalty_get (self, AF_INET6)); + if (applied_config_get_current (&priv->ac_ip6_config)) { + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip6_config, + applied_config_get_current (&priv->ac_ip6_config), + default_route_metric_penalty_get (self, AF_INET6)); } - if (priv->dhcp6.ip6_config) { - nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config, - default_route_metric_penalty_get (self, AF_INET6)); + if (applied_config_get_current (&priv->dhcp6.ip6_config)) { + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip6_config, + applied_config_get_current (&priv->dhcp6.ip6_config), + default_route_metric_penalty_get (self, AF_INET6)); } - if (priv->wwan_ip6_config) { - nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config, - default_route_metric_penalty_get (self, AF_INET6)); + if (applied_config_get_current (&priv->wwan_ip6_config)) { + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip6_config, + applied_config_get_current (&priv->wwan_ip6_config), + default_route_metric_penalty_get (self, AF_INET6)); } for (iter = priv->vpn6_configs; iter; iter = iter->next) nm_ip6_config_subtract (priv->ext_ip6_config, iter->data, 0); @@ -12479,10 +12568,10 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) g_clear_object (&priv->ext_ip4_config); g_clear_object (&priv->ip4_config); g_clear_object (&priv->con_ip6_config); - g_clear_object (&priv->ac_ip6_config); + applied_config_clear (&priv->ac_ip6_config); g_clear_object (&priv->ext_ip6_config); g_clear_object (&priv->ext_ip6_config_captured); - g_clear_object (&priv->wwan_ip6_config); + applied_config_clear (&priv->wwan_ip6_config); g_clear_object (&priv->ip6_config); g_clear_object (&priv->dad6_ip6_config); diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index c614863d03..59581b87bd 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -222,6 +222,13 @@ const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Co void nm_ip4_config_reset_nameservers (NMIP4Config *self); void nm_ip4_config_add_nameserver (NMIP4Config *self, guint32 nameserver); + +static inline void +_nm_ip4_config_add_nameserver (NMIP4Config *self, const guint32 *nameserver) +{ + nm_ip4_config_add_nameserver (self, *nameserver); +} + void nm_ip4_config_del_nameserver (NMIP4Config *self, guint i); guint nm_ip4_config_get_num_nameservers (const NMIP4Config *self); guint32 nm_ip4_config_get_nameserver (const NMIP4Config *self, guint i); @@ -354,12 +361,42 @@ nm_ip_config_get_addr_family (const NMIPConfig *config) } \ } G_STMT_END +#define _NM_IP_CONFIG_DISPATCH_VOID(config, v4_func, v6_func, ...) \ + G_STMT_START { \ + gconstpointer _config = (config); \ + \ + if (NM_IS_IP4_CONFIG (_config)) { \ + v4_func ((NMIP4Config *) _config, ##__VA_ARGS__); \ + } else { \ + nm_assert (NM_IS_IP6_CONFIG (_config)); \ + v6_func ((NMIP6Config *) _config, ##__VA_ARGS__); \ + } \ + } G_STMT_END + +static inline void +nm_ip_config_add_address (NMIPConfig *self, const NMPlatformIPAddress *address) +{ + _NM_IP_CONFIG_DISPATCH_VOID (self, nm_ip4_config_add_address, nm_ip6_config_add_address, (gconstpointer) address); +} + static inline int nm_ip_config_get_dns_priority (const NMIPConfig *self) { _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_dns_priority, nm_ip6_config_get_dns_priority); } +static inline void +nm_ip_config_add_nameserver (NMIPConfig *self, const NMIPAddr *ns) +{ + _NM_IP_CONFIG_DISPATCH_VOID (self, _nm_ip4_config_add_nameserver, nm_ip6_config_add_nameserver, (gconstpointer) ns); +} + +static inline void +nm_ip_config_reset_nameservers (const NMIPConfig *self) +{ + _NM_IP_CONFIG_DISPATCH_VOID (self, nm_ip4_config_reset_nameservers, nm_ip6_config_reset_nameservers); +} + static inline guint nm_ip_config_get_num_nameservers (const NMIPConfig *self) { @@ -384,6 +421,18 @@ nm_ip_config_get_domain (const NMIPConfig *self, guint i) _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_domain, nm_ip6_config_get_domain, i); } +static inline void +nm_ip_config_reset_searches (const NMIPConfig *self) +{ + _NM_IP_CONFIG_DISPATCH_VOID (self, nm_ip4_config_reset_searches, nm_ip6_config_reset_searches); +} + +static inline void +nm_ip_config_add_search (const NMIPConfig *self, const char *new) +{ + _NM_IP_CONFIG_DISPATCH_VOID (self, nm_ip4_config_add_search, nm_ip6_config_add_search, new); +} + static inline guint nm_ip_config_get_num_searches (const NMIPConfig *self) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 3336642b8b..bd2e4516fb 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -252,6 +252,8 @@ struct _NMPlatformObject { __NMPlatformObject_COMMON; }; +#define NM_PLATFORM_IP_ADDRESS_CAST(address) \ + NM_CONSTCAST (NMPlatformIPAddress, (address), NMPlatformIPXAddress, NMPlatformIP4Address, NMPlatformIP6Address) #define __NMPlatformIPAddress_COMMON \ __NMPlatformObject_COMMON; \ -- cgit v1.2.1