summaryrefslogtreecommitdiff
path: root/src/nm-ip6-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-ip6-config.c')
-rw-r--r--src/nm-ip6-config.c217
1 files changed, 166 insertions, 51 deletions
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index db64e72618..a148d826e6 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -653,6 +653,85 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6
return FALSE;
}
+/*******************************************************************************/
+
+static int
+_addresses_get_index (const NMIP6Config *self, const NMPlatformIP6Address *addr)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+ guint i;
+
+ for (i = 0; i < priv->addresses->len; i++) {
+ const NMPlatformIP6Address *a = &g_array_index (priv->addresses, NMPlatformIP6Address, i);
+
+ if (IN6_ARE_ADDR_EQUAL (&addr->address, &a->address))
+ return (int) i;
+ }
+ return -1;
+}
+
+static int
+_nameservers_get_index (const NMIP6Config *self, const struct in6_addr *ns)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+ guint i;
+
+ for (i = 0; i < priv->nameservers->len; i++) {
+ const struct in6_addr *n = &g_array_index (priv->nameservers, struct in6_addr, i);
+
+ if (IN6_ARE_ADDR_EQUAL (ns, n))
+ return (int) i;
+ }
+ return -1;
+}
+
+static int
+_routes_get_index (const NMIP6Config *self, const NMPlatformIP6Route *route)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+ guint i;
+
+ for (i = 0; i < priv->routes->len; i++) {
+ const NMPlatformIP6Route *r = &g_array_index (priv->routes, NMPlatformIP6Route, i);
+
+ if (routes_are_duplicate (route, r, FALSE))
+ return (int) i;
+ }
+ return -1;
+}
+
+static int
+_domains_get_index (const NMIP6Config *self, const char *domain)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+ guint i;
+
+ for (i = 0; i < priv->domains->len; i++) {
+ const char *d = g_ptr_array_index (priv->domains, i);
+
+ if (g_strcmp0 (domain, d) == 0)
+ return (int) i;
+ }
+ return -1;
+}
+
+static int
+_searches_get_index (const NMIP6Config *self, const char *search)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+ guint i;
+
+ for (i = 0; i < priv->searches->len; i++) {
+ const char *s = g_ptr_array_index (priv->searches, i);
+
+ if (g_strcmp0 (search, s) == 0)
+ return (int) i;
+ }
+ return -1;
+}
+
+/*******************************************************************************/
+
/**
* nm_ip6_config_subtract:
* @dst: config from which to remove everything in @src
@@ -663,7 +742,8 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6
void
nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
{
- guint32 i, j;
+ guint i;
+ gint idx;
const struct in6_addr *dst_tmp, *src_tmp;
g_return_if_fail (src != NULL);
@@ -673,30 +753,16 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
/* addresses */
for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) {
- const NMPlatformIP6Address *src_addr = nm_ip6_config_get_address (src, i);
-
- for (j = 0; j < nm_ip6_config_get_num_addresses (dst); j++) {
- const NMPlatformIP6Address *dst_addr = nm_ip6_config_get_address (dst, j);
-
- if (IN6_ARE_ADDR_EQUAL (&src_addr->address, &dst_addr->address)) {
- nm_ip6_config_del_address (dst, j);
- break;
- }
- }
+ idx = _addresses_get_index (dst, nm_ip6_config_get_address (src, i));
+ if (idx >= 0)
+ nm_ip6_config_del_address (dst, idx);
}
/* nameservers */
for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) {
- const struct in6_addr *src_ns = nm_ip6_config_get_nameserver (src, i);
-
- for (j = 0; j < nm_ip6_config_get_num_nameservers (dst); j++) {
- const struct in6_addr *dst_ns = nm_ip6_config_get_nameserver (dst, j);
-
- if (IN6_ARE_ADDR_EQUAL (src_ns, dst_ns)) {
- nm_ip6_config_del_nameserver (dst, j);
- break;
- }
- }
+ idx = _nameservers_get_index (dst, nm_ip6_config_get_nameserver (src, i));
+ if (idx >= 0)
+ nm_ip6_config_del_nameserver (dst, idx);
}
/* default gateway */
@@ -710,44 +776,23 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
/* routes */
for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) {
- const NMPlatformIP6Route *src_route = nm_ip6_config_get_route (src, i);
-
- 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, FALSE)) {
- nm_ip6_config_del_route (dst, j);
- break;
- }
- }
+ idx = _routes_get_index (dst, nm_ip6_config_get_route (src, i));
+ if (idx >= 0)
+ nm_ip6_config_del_route (dst, idx);
}
/* domains */
for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) {
- const char *src_domain = nm_ip6_config_get_domain (src, i);
-
- for (j = 0; j < nm_ip6_config_get_num_domains (dst); j++) {
- const char *dst_domain = nm_ip6_config_get_domain (dst, j);
-
- if (g_strcmp0 (src_domain, dst_domain) == 0) {
- nm_ip6_config_del_domain (dst, j);
- break;
- }
- }
+ idx = _domains_get_index (dst, nm_ip6_config_get_domain (src, i));
+ if (idx >= 0)
+ nm_ip6_config_del_domain (dst, idx);
}
/* dns searches */
for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) {
- const char *src_search = nm_ip6_config_get_search (src, i);
-
- for (j = 0; j < nm_ip6_config_get_num_searches (dst); j++) {
- const char *dst_search = nm_ip6_config_get_search (dst, j);
-
- if (g_strcmp0 (src_search, dst_search) == 0) {
- nm_ip6_config_del_search (dst, j);
- break;
- }
- }
+ idx = _searches_get_index (dst, nm_ip6_config_get_search (src, i));
+ if (idx >= 0)
+ nm_ip6_config_del_search (dst, idx);
}
if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst))
@@ -756,6 +801,76 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
g_object_thaw_notify (G_OBJECT (dst));
}
+void
+nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
+{
+ guint i;
+ gint idx;
+ const struct in6_addr *dst_tmp, *src_tmp;
+
+ g_return_if_fail (src != NULL);
+ g_return_if_fail (dst != NULL);
+
+ g_object_freeze_notify (G_OBJECT (dst));
+
+ /* addresses */
+ for (i = 0; i < nm_ip6_config_get_num_addresses (dst); ) {
+ idx = _addresses_get_index (src, nm_ip6_config_get_address (dst, i));
+ if (idx < 0)
+ nm_ip6_config_del_address (dst, i);
+ else
+ i++;
+ }
+
+ /* nameservers */
+ for (i = 0; i < nm_ip6_config_get_num_nameservers (dst); ) {
+ idx = _nameservers_get_index (src, nm_ip6_config_get_nameserver (dst, i));
+ if (idx < 0)
+ nm_ip6_config_del_nameserver (dst, i);
+ else
+ i++;
+ }
+
+ /* default gateway */
+ dst_tmp = nm_ip6_config_get_gateway (dst);
+ if (dst_tmp) {
+ src_tmp = nm_ip6_config_get_gateway (src);
+ if ( !nm_ip6_config_get_num_addresses (dst)
+ || !src_tmp
+ || !IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp))
+ nm_ip6_config_set_gateway (dst, NULL);
+ }
+
+ /* routes */
+ for (i = 0; i < nm_ip6_config_get_num_routes (dst); ) {
+ idx = _routes_get_index (src, nm_ip6_config_get_route (dst, i));
+ if (idx < 0)
+ nm_ip6_config_del_route (dst, i);
+ else
+ i++;
+ }
+
+ /* domains */
+ for (i = 0; i < nm_ip6_config_get_num_domains (src); ) {
+ idx = _domains_get_index (src, nm_ip6_config_get_domain (dst, i));
+ if (idx < 0)
+ nm_ip6_config_del_domain (dst, i);
+ else
+ i++;
+ }
+
+ /* dns searches */
+ for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) {
+ idx = _searches_get_index (src, nm_ip6_config_get_search (dst, i));
+ if (idx < 0)
+ nm_ip6_config_del_search (dst, i);
+ else
+ i++;
+ }
+
+ g_object_thaw_notify (G_OBJECT (dst));
+}
+
/**
* nm_ip6_config_replace:
* @dst: config which will be replaced with everything in @src