diff options
author | Thomas Haller <thaller@redhat.com> | 2013-09-06 11:02:03 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2013-09-25 23:12:37 +0200 |
commit | f0fccd99a55cecc4288ddba5c314b86579a27192 (patch) | |
tree | 87c4835c3098fc08d96721adc9cfe07356247313 | |
parent | b1113a0a596afb5de4b24a6de3abd390fa769356 (diff) | |
download | NetworkManager-f0fccd99a55cecc4288ddba5c314b86579a27192.tar.gz |
core: add nm_ip[46]_config_replace functions
This new function copies the entire configuration of an existing
NMIP[46]Config object (src) and replaces the configuration in the destination
object (dst) in-place.
Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r-- | src/nm-ip4-config.c | 254 | ||||
-rw-r--r-- | src/nm-ip4-config.h | 1 | ||||
-rw-r--r-- | src/nm-ip6-config.c | 200 | ||||
-rw-r--r-- | src/nm-ip6-config.h | 1 |
4 files changed, 430 insertions, 26 deletions
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 1943532b75..79ec2d481f 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -104,6 +104,19 @@ same_prefix (guint32 address1, guint32 address2, int plen) /******************************************************************/ +static gboolean +addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b, gboolean consider_plen) +{ + return a->address == b->address && (!consider_plen || a->plen == b->plen); +} + +static gboolean +routes_are_duplicate (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gboolean consider_gateway_and_metric) +{ + return a->network == b->network && a->plen == b->plen && + (!consider_gateway_and_metric || (a->gateway == b->gateway && a->metric == b->metric)); +} + NMIP4Config * nm_ip4_config_capture (int ifindex) { @@ -376,12 +389,11 @@ nm_ip4_config_merge (NMIP4Config *dst, NMIP4Config *src) } /** - * nm_ip4_config_subtract() + * nm_ip4_config_subtract: * @dst: config from which to remove everything in @src * @src: config to remove from @dst * * Removes everything in @src from @dst. - * */ void nm_ip4_config_subtract (NMIP4Config *dst, NMIP4Config *src) @@ -505,6 +517,228 @@ nm_ip4_config_subtract (NMIP4Config *dst, NMIP4Config *src) } } + +/** + * nm_ip4_config_replace: + * @dst: config from which to remove everything in @src + * @src: config to remove from @dst + * @relevant_changes: return whether there are changes to the + * destination object that are relevant. This is equal to + * nm_ip4_config_equal() showing any difference. + * + * Replaces everything in @dst with @src so that the two configurations + * contain the same content -- with the exception of the dbus path. + * + * Returns: whether the @dst instance changed in any way (including minor changes, + * that are not signaled by the output parameter @relevant_changes). + */ +gboolean +nm_ip4_config_replace (NMIP4Config *dst, NMIP4Config *src, gboolean *relevant_changes) +{ +#ifndef G_DISABLE_ASSERT + gboolean config_equal; +#endif + gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; + guint i, num; + NMIP4ConfigPrivate *dst_priv, *src_priv; + const NMPlatformIP4Address *dst_addr, *src_addr; + const NMPlatformIP4Route *dst_route, *src_route; + + g_return_val_if_fail (src != NULL, FALSE); + g_return_val_if_fail (dst != NULL, FALSE); + g_return_val_if_fail (src != dst, FALSE); + +#ifndef G_DISABLE_ASSERT + config_equal = nm_ip4_config_equal (dst, src); +#endif + + dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst); + src_priv = NM_IP4_CONFIG_GET_PRIVATE (src); + + /* never_default */ + if (src_priv->never_default != dst_priv->never_default) { + dst_priv->never_default = src_priv->never_default; + has_relevant_changes = TRUE; + } + + /* default gateway */ + if (src_priv->gateway != dst_priv->gateway) { + nm_ip4_config_set_gateway (dst, src_priv->gateway); + has_relevant_changes = TRUE; + } + + /* addresses */ + num = nm_ip4_config_get_num_addresses (src); + are_equal = num == nm_ip4_config_get_num_addresses (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip4_address_cmp (src_addr = nm_ip4_config_get_address (src, i), + dst_addr = nm_ip4_config_get_address (dst, i))) { + are_equal = FALSE; + if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip4_config_reset_addresses (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i)); + has_minor_changes = TRUE; + } + + /* routes */ + num = nm_ip4_config_get_num_routes (src); + are_equal = num == nm_ip4_config_get_num_routes (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip4_route_cmp (src_route = nm_ip4_config_get_route (src, i), + dst_route = nm_ip4_config_get_route (dst, i))) { + are_equal = FALSE; + if (!routes_are_duplicate (src_route, dst_route, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip4_config_reset_routes (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i)); + has_minor_changes = TRUE; + } + + /* nameservers */ + num = nm_ip4_config_get_num_nameservers (src); + are_equal = num == nm_ip4_config_get_num_nameservers (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_ip4_config_get_nameserver (src, i) != nm_ip4_config_get_nameserver (dst, i)) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_nameservers (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i)); + has_relevant_changes = TRUE; + } + + /* domains */ + num = nm_ip4_config_get_num_domains (src); + are_equal = num == nm_ip4_config_get_num_domains (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip4_config_get_domain (src, i), + nm_ip4_config_get_domain (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_domains (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i)); + has_relevant_changes = TRUE; + } + + /* dns searches */ + num = nm_ip4_config_get_num_searches (src); + are_equal = num == nm_ip4_config_get_num_searches (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip4_config_get_search (src, i), + nm_ip4_config_get_search (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_searches (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); + has_relevant_changes = TRUE; + } + + /* mss */ + if (src_priv->mss != dst_priv->mss) { + nm_ip4_config_set_mss (dst, src_priv->mss); + has_minor_changes = TRUE; + } + + /* ptp address */ + if (src_priv->ptp_address != dst_priv->ptp_address) { + dst_priv->ptp_address = src_priv->ptp_address; + has_relevant_changes = TRUE; + } + + /* nis */ + num = nm_ip4_config_get_num_nis_servers (src); + are_equal = num == nm_ip4_config_get_num_nis_servers (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_ip4_config_get_nis_server (src, i) != nm_ip4_config_get_nis_server (dst, i)) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_nis_servers (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i)); + has_relevant_changes = TRUE; + } + + /* nis_domain */ + if (g_strcmp0 (src_priv->nis_domain, dst_priv->nis_domain)) { + nm_ip4_config_set_nis_domain (dst, src_priv->nis_domain); + has_relevant_changes = TRUE; + } + + /* wins */ + num = nm_ip4_config_get_num_wins (src); + are_equal = num == nm_ip4_config_get_num_wins (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_ip4_config_get_wins (src, i) != nm_ip4_config_get_wins (dst, i)) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_wins (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i)); + has_relevant_changes = TRUE; + } + + /* mtu */ + if (src_priv->mtu != dst_priv->mtu) { + nm_ip4_config_set_mtu (dst, src_priv->mtu); + has_minor_changes = TRUE; + } + + /* 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. */ + g_assert (config_equal == !has_relevant_changes); + + if (relevant_changes) + *relevant_changes = has_relevant_changes; + + return has_relevant_changes || has_minor_changes; +} + void nm_ip4_config_dump (NMIP4Config *config, const char *detail) { @@ -643,12 +877,6 @@ nm_ip4_config_reset_addresses (NMIP4Config *config) g_array_set_size (priv->addresses, 0); } -static gboolean -addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) -{ - return a->address == b->address; -} - void nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new) { @@ -660,7 +888,7 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new) for (i = 0; i < priv->addresses->len; i++ ) { NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i); - if (addresses_are_duplicate (item, new)) { + if (addresses_are_duplicate (item, new, FALSE)) { memcpy (item, new, sizeof (*item)); return; } @@ -705,12 +933,6 @@ nm_ip4_config_reset_routes (NMIP4Config *config) g_array_set_size (priv->routes, 0); } -static gboolean -routes_are_duplicate (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b) -{ - return a->network == b->network && a->plen == b->plen; -} - void nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new) { @@ -722,7 +944,7 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new) for (i = 0; i < priv->routes->len; i++ ) { NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i); - if (routes_are_duplicate (item, new)) { + if (routes_are_duplicate (item, new, FALSE)) { memcpy (item, new, sizeof (*item)); return; } diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index b37b97f0e8..5c8a4552d8 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -65,6 +65,7 @@ void nm_ip4_config_update_setting (NMIP4Config *config, NMSettingIP4Config *sett /* Utility functions */ void nm_ip4_config_merge (NMIP4Config *dst, NMIP4Config *src); void nm_ip4_config_subtract (NMIP4Config *dst, NMIP4Config *src); +gboolean nm_ip4_config_replace (NMIP4Config *dst, NMIP4Config *src, gboolean *relevant_changes); gboolean nm_ip4_config_destination_is_direct (NMIP4Config *config, guint32 dest, int plen); void nm_ip4_config_dump (NMIP4Config *config, const char *detail); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 9829fe0249..159d5fec5f 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -107,6 +107,19 @@ same_prefix (const struct in6_addr *address1, const struct in6_addr *address2, i /******************************************************************/ +static gboolean +addresses_are_duplicate (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean consider_plen) +{ + return IN6_ARE_ADDR_EQUAL (&a->address, &b->address) && (!consider_plen || a->plen == b->plen); +} + +static gboolean +routes_are_duplicate (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gboolean consider_gateway_and_metric) +{ + return IN6_ARE_ADDR_EQUAL (&a->network, &b->network) && a->plen == b->plen && + (!consider_gateway_and_metric || (IN6_ARE_ADDR_EQUAL (&a->gateway, &b->gateway) && a->metric == b->metric)); +} + NMIP6Config * nm_ip6_config_capture (int ifindex) { @@ -380,19 +393,12 @@ nm_ip6_config_destination_is_direct (NMIP6Config *config, const struct in6_addr return FALSE; } -static gboolean -routes_are_duplicate (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b) -{ - return IN6_ARE_ADDR_EQUAL (&a->network, &b->network) && a->plen == b->plen; -} - /** - * nm_ip6_config_subtract() + * nm_ip6_config_subtract: * @dst: config from which to remove everything in @src * @src: config to remove from @dst * * Removes everything in @src from @dst. - * */ void nm_ip6_config_subtract (NMIP6Config *dst, NMIP6Config *src) @@ -450,7 +456,7 @@ nm_ip6_config_subtract (NMIP6Config *dst, NMIP6Config *src) for (j = 0; j < nm_ip6_config_get_num_routes (dst); j++) { const NMPlatformIP6Route *dst_route = nm_ip6_config_get_route (dst, j); - if (routes_are_duplicate (src_route, dst_route)) { + if (routes_are_duplicate (src_route, dst_route, FALSE)) { nm_ip6_config_del_route (dst, j); break; } @@ -489,6 +495,180 @@ nm_ip6_config_subtract (NMIP6Config *dst, NMIP6Config *src) nm_ip6_config_set_mss (dst, 0); } +/** + * nm_ip6_config_replace: + * @dst: config which will be replaced with everything in @src + * @src: config to copy over to @dst + * @relevant_changes: return whether there are changes to the + * destination object that are relevant. This is equal to + * nm_ip6_config_equal() showing any difference. + * + * Replaces everything in @dst with @src so that the two configurations + * contain the same content -- with the exception of the dbus path. + * + * Returns: whether the @dst instance changed in any way (including minor changes, + * that are not signaled by the output parameter @relevant_changes). + */ +gboolean +nm_ip6_config_replace (NMIP6Config *dst, NMIP6Config *src, gboolean *relevant_changes) +{ +#ifndef G_DISABLE_ASSERT + gboolean config_equal; +#endif + gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; + guint i, num; + NMIP6ConfigPrivate *dst_priv, *src_priv; + const NMPlatformIP6Address *dst_addr, *src_addr; + const NMPlatformIP6Route *dst_route, *src_route; + + g_return_val_if_fail (src != NULL, FALSE); + g_return_val_if_fail (dst != NULL, FALSE); + g_return_val_if_fail (src != dst, FALSE); + +#ifndef G_DISABLE_ASSERT + config_equal = nm_ip6_config_equal (dst, src); +#endif + + dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst); + src_priv = NM_IP6_CONFIG_GET_PRIVATE (src); + + /* never_default */ + if (src_priv->never_default != dst_priv->never_default) { + dst_priv->never_default = src_priv->never_default; + has_minor_changes = TRUE; + } + + /* default gateway */ + if (!IN6_ARE_ADDR_EQUAL (&src_priv->gateway, &dst_priv->gateway)) { + nm_ip6_config_set_gateway (dst, &src_priv->gateway); + has_relevant_changes = TRUE; + } + + /* addresses */ + num = nm_ip6_config_get_num_addresses (src); + are_equal = num == nm_ip6_config_get_num_addresses (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip6_address_cmp (src_addr = nm_ip6_config_get_address (src, i), + dst_addr = nm_ip6_config_get_address (dst, i))) { + are_equal = FALSE; + if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip6_config_reset_addresses (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i)); + has_minor_changes = TRUE; + } + + /* routes */ + num = nm_ip6_config_get_num_routes (src); + are_equal = num == nm_ip6_config_get_num_routes (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip6_route_cmp (src_route = nm_ip6_config_get_route (src, i), + dst_route = nm_ip6_config_get_route (dst, i))) { + are_equal = FALSE; + if (!routes_are_duplicate (src_route, dst_route, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip6_config_reset_routes (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i)); + has_minor_changes = TRUE; + } + + /* nameservers */ + num = nm_ip6_config_get_num_nameservers (src); + are_equal = num == nm_ip6_config_get_num_nameservers (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (IN6_ARE_ADDR_EQUAL (nm_ip6_config_get_nameserver (src, i), + nm_ip6_config_get_nameserver (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip6_config_reset_nameservers (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i)); + has_relevant_changes = TRUE; + } + + /* domains */ + num = nm_ip6_config_get_num_domains (src); + are_equal = num == nm_ip6_config_get_num_domains (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip6_config_get_domain (src, i), + nm_ip6_config_get_domain (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip6_config_reset_domains (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i)); + has_relevant_changes = TRUE; + } + + /* dns searches */ + num = nm_ip6_config_get_num_searches (src); + are_equal = num == nm_ip6_config_get_num_searches (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip6_config_get_search (src, i), + nm_ip6_config_get_search (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip6_config_reset_searches (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i)); + has_relevant_changes = TRUE; + } + + /* mss */ + if (src_priv->mss != dst_priv->mss) { + nm_ip6_config_set_mss (dst, src_priv->mss); + has_minor_changes = TRUE; + } + + /* ptp address */ + if (!IN6_ARE_ADDR_EQUAL (&src_priv->ptp_address, &dst_priv->ptp_address)) { + nm_ip6_config_set_ptp_address (dst, &src_priv->ptp_address); + has_relevant_changes = TRUE; + } + + /* 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. */ + g_assert (config_equal == !has_relevant_changes); + + if (relevant_changes) + *relevant_changes = has_relevant_changes; + + return has_relevant_changes || has_minor_changes; +} + /******************************************************************/ void @@ -604,7 +784,7 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new) for (i = 0; i < priv->routes->len; i++ ) { NMPlatformIP6Route *item = &g_array_index (priv->routes, NMPlatformIP6Route, i); - if (routes_are_duplicate (item, new)) { + if (routes_are_duplicate (item, new, FALSE)) { memcpy (item, new, sizeof (*item)); return; } diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 69e2ddaece..d0994e26cc 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -64,6 +64,7 @@ void nm_ip6_config_update_setting (NMIP6Config *config, NMSettingIP6Config *sett /* Utility functions */ void nm_ip6_config_merge (NMIP6Config *dst, NMIP6Config *src); void nm_ip6_config_subtract (NMIP6Config *dst, NMIP6Config *src); +gboolean nm_ip6_config_replace (NMIP6Config *dst, NMIP6Config *src, gboolean *relevant_changes); int nm_ip6_config_destination_is_direct (NMIP6Config *config, const struct in6_addr *dest, int plen); /* Gateways */ |