summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2013-09-06 11:02:03 +0200
committerThomas Haller <thaller@redhat.com>2013-09-25 23:12:37 +0200
commitf0fccd99a55cecc4288ddba5c314b86579a27192 (patch)
tree87c4835c3098fc08d96721adc9cfe07356247313
parentb1113a0a596afb5de4b24a6de3abd390fa769356 (diff)
downloadNetworkManager-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.c254
-rw-r--r--src/nm-ip4-config.h1
-rw-r--r--src/nm-ip6-config.c200
-rw-r--r--src/nm-ip6-config.h1
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 */