summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-08-01 14:04:35 -0500
committerDan Williams <dcbw@redhat.com>2013-08-02 17:19:36 -0500
commit7e21b528a974737a4508d3a21289537e54c46cfe (patch)
tree3d03912a0593c17ec5c182521bb468900c3b2afd
parent5c1ec7cedf701b79354c0c54283803334dc7344f (diff)
downloadNetworkManager-7e21b528a974737a4508d3a21289537e54c46cfe.tar.gz
core: add nm_ip4_config_subtract()
Removes anything in 'src' from 'dst'.
-rw-r--r--src/nm-ip4-config.c215
-rw-r--r--src/nm-ip4-config.h8
-rw-r--r--src/tests/Makefile.am18
-rw-r--r--src/tests/test-ip4-config.c189
4 files changed, 428 insertions, 2 deletions
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index bc621dd68a..8de188c513 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -381,6 +381,136 @@ nm_ip4_config_merge (NMIP4Config *dst, NMIP4Config *src)
nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
}
+/**
+ * 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)
+{
+ guint32 i, j;
+
+ g_return_if_fail (src != NULL);
+ g_return_if_fail (dst != NULL);
+
+ /* addresses */
+ for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) {
+ const NMPlatformIP4Address *src_addr = nm_ip4_config_get_address (src, i);
+
+ for (j = 0; j < nm_ip4_config_get_num_addresses (dst); j++) {
+ const NMPlatformIP4Address *dst_addr = nm_ip4_config_get_address (dst, j);
+
+ if (src_addr->address == dst_addr->address &&
+ src_addr->plen == dst_addr->plen) {
+ nm_ip4_config_del_address (dst, j);
+ break;
+ }
+ }
+ }
+
+ /* ptp address */
+ if (nm_ip4_config_get_ptp_address (src) == nm_ip4_config_get_ptp_address (dst))
+ nm_ip4_config_set_ptp_address (dst, 0);
+
+ /* nameservers */
+ for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) {
+ guint32 src_ns = nm_ip4_config_get_nameserver (src, i);
+
+ for (j = 0; j < nm_ip4_config_get_num_nameservers (dst); j++) {
+ guint32 dst_ns = nm_ip4_config_get_nameserver (dst, j);
+
+ if (dst_ns == src_ns) {
+ nm_ip4_config_del_nameserver (dst, j);
+ break;
+ }
+ }
+ }
+
+ /* default gateway */
+ if (nm_ip4_config_get_gateway (src) == nm_ip4_config_get_gateway (dst))
+ nm_ip4_config_set_gateway (dst, 0);
+
+ /* routes */
+ for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) {
+ NMIP4Route *src_route = nm_ip4_config_get_route (src, i);
+
+ for (j = 0; j < nm_ip4_config_get_num_routes (dst); j++) {
+ NMIP4Route *dst_route = nm_ip4_config_get_route (dst, j);
+
+ if (nm_ip4_route_compare (src_route, dst_route)) {
+ nm_ip4_config_del_route (dst, j);
+ break;
+ }
+ }
+ }
+
+ /* domains */
+ for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) {
+ const char *src_domain = nm_ip4_config_get_domain (src, i);
+
+ for (j = 0; j < nm_ip4_config_get_num_domains (dst); j++) {
+ const char *dst_domain = nm_ip4_config_get_domain (dst, j);
+
+ if (g_strcmp0 (src_domain, dst_domain) == 0) {
+ nm_ip4_config_del_domain (dst, j);
+ break;
+ }
+ }
+ }
+
+ /* dns searches */
+ for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) {
+ const char *src_search = nm_ip4_config_get_search (src, i);
+
+ for (j = 0; j < nm_ip4_config_get_num_searches (dst); j++) {
+ const char *dst_search = nm_ip4_config_get_search (dst, j);
+
+ if (g_strcmp0 (src_search, dst_search) == 0) {
+ nm_ip4_config_del_search (dst, j);
+ break;
+ }
+ }
+ }
+
+ if (nm_ip4_config_get_mss (src) == nm_ip4_config_get_mss (dst))
+ nm_ip4_config_set_mss (dst, 0);
+
+ /* NIS */
+ for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) {
+ guint32 src_nis = nm_ip4_config_get_nis_server (src, i);
+
+ for (j = 0; j < nm_ip4_config_get_num_nis_servers (dst); j++) {
+ guint32 dst_nis = nm_ip4_config_get_nis_server (dst, j);
+
+ if (dst_nis == src_nis) {
+ nm_ip4_config_del_nis_server (dst, j);
+ break;
+ }
+ }
+ }
+
+ if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0)
+ nm_ip4_config_set_nis_domain (dst, NULL);
+
+ /* WINS */
+ for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) {
+ guint32 src_wins = nm_ip4_config_get_wins (src, i);
+
+ for (j = 0; j < nm_ip4_config_get_num_wins (dst); j++) {
+ guint32 dst_wins = nm_ip4_config_get_wins (dst, j);
+
+ if (dst_wins == src_wins) {
+ nm_ip4_config_del_wins (dst, j);
+ break;
+ }
+ }
+ }
+}
+
gboolean
nm_ip4_config_destination_is_direct (NMIP4Config *config, guint32 network, int plen)
{
@@ -467,6 +597,16 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
g_array_append_val (priv->addresses, *new);
}
+void
+nm_ip4_config_del_address (NMIP4Config *config, guint i)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+
+ g_return_if_fail (i < priv->addresses->len);
+
+ g_array_remove_index (priv->addresses, i);
+}
+
guint
nm_ip4_config_get_num_addresses (NMIP4Config *config)
{
@@ -535,6 +675,31 @@ nm_ip4_config_take_route (NMIP4Config *config, NMIP4Route *route)
nm_ip4_route_unref (route);
}
+void
+nm_ip4_config_del_route (NMIP4Config *config, guint i)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+ GSList *iter, *last = priv->routes;
+ guint n;
+
+ if (i == 0) {
+ last = priv->routes;
+ priv->routes = last->next;
+ last->next = NULL;
+ g_slist_free_full (last, (GDestroyNotify) nm_ip4_route_unref);
+ } else {
+ for (iter = priv->routes->next, n = 1, last = NULL; iter; iter = iter->next, n++) {
+ if (n == i) {
+ last->next = iter->next;
+ iter->next = NULL;
+ g_slist_free_full (iter, (GDestroyNotify) nm_ip4_route_unref);
+ break;
+ }
+ last = iter;
+ }
+ }
+}
+
guint
nm_ip4_config_get_num_routes (NMIP4Config *config)
{
@@ -576,6 +741,16 @@ nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 new)
g_array_append_val (priv->nameservers, new);
}
+void
+nm_ip4_config_del_nameserver (NMIP4Config *config, guint i)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+
+ g_return_if_fail (i < priv->nameservers->len);
+
+ g_array_remove_index (priv->nameservers, i);
+}
+
guint32
nm_ip4_config_get_num_nameservers (NMIP4Config *config)
{
@@ -618,6 +793,16 @@ nm_ip4_config_add_domain (NMIP4Config *config, const char *domain)
g_ptr_array_add (priv->domains, g_strdup (domain));
}
+void
+nm_ip4_config_del_domain (NMIP4Config *config, guint i)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+
+ g_return_if_fail (i < priv->domains->len);
+
+ g_ptr_array_remove_index (priv->domains, i);
+}
+
guint32
nm_ip4_config_get_num_domains (NMIP4Config *config)
{
@@ -660,6 +845,16 @@ nm_ip4_config_add_search (NMIP4Config *config, const char *new)
g_ptr_array_add (priv->searches, g_strdup (new));
}
+void
+nm_ip4_config_del_search (NMIP4Config *config, guint i)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+
+ g_return_if_fail (i < priv->searches->len);
+
+ g_ptr_array_remove_index (priv->searches, i);
+}
+
guint32
nm_ip4_config_get_num_searches (NMIP4Config *config)
{
@@ -735,6 +930,16 @@ nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis)
g_array_append_val (priv->nis, nis);
}
+void
+nm_ip4_config_del_nis_server (NMIP4Config *config, guint i)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+
+ g_return_if_fail (i < priv->nis->len);
+
+ g_array_remove_index (priv->nis, i);
+}
+
guint32
nm_ip4_config_get_num_nis_servers (NMIP4Config *config)
{
@@ -793,6 +998,16 @@ nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins)
g_array_append_val (priv->wins, wins);
}
+void
+nm_ip4_config_del_wins (NMIP4Config *config, guint i)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+
+ g_return_if_fail (i < priv->wins->len);
+
+ g_array_remove_index (priv->wins, i);
+}
+
guint32
nm_ip4_config_get_num_wins (NMIP4Config *config)
{
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index f441be86c4..adef22e8c3 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_destination_is_direct (NMIP4Config *config, guint32 dest, int plen);
/* Gateways */
@@ -76,6 +77,7 @@ guint32 nm_ip4_config_get_gateway (NMIP4Config *config);
/* Addresses */
void nm_ip4_config_reset_addresses (NMIP4Config *config);
void nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *address);
+void nm_ip4_config_del_address (NMIP4Config *config, guint i);
guint nm_ip4_config_get_num_addresses (NMIP4Config *config);
const NMPlatformIP4Address *nm_ip4_config_get_address (NMIP4Config *config, guint i);
@@ -83,24 +85,28 @@ const NMPlatformIP4Address *nm_ip4_config_get_address (NMIP4Config *config, guin
void nm_ip4_config_reset_routes (NMIP4Config *config);
void nm_ip4_config_add_route (NMIP4Config *config, NMIP4Route *route);
void nm_ip4_config_take_route (NMIP4Config *config, NMIP4Route *route);
+void nm_ip4_config_del_route (NMIP4Config *config, guint i);
guint32 nm_ip4_config_get_num_routes (NMIP4Config *config);
NMIP4Route * nm_ip4_config_get_route (NMIP4Config *config, guint32 i);
/* Nameservers */
void nm_ip4_config_reset_nameservers (NMIP4Config *config);
void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver);
+void nm_ip4_config_del_nameserver (NMIP4Config *config, guint i);
guint32 nm_ip4_config_get_num_nameservers (NMIP4Config *config);
guint32 nm_ip4_config_get_nameserver (NMIP4Config *config, guint i);
/* Domains */
void nm_ip4_config_reset_domains (NMIP4Config *config);
void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain);
+void nm_ip4_config_del_domain (NMIP4Config *config, guint i);
guint32 nm_ip4_config_get_num_domains (NMIP4Config *config);
const char * nm_ip4_config_get_domain (NMIP4Config *config, guint i);
/* Search lists */
void nm_ip4_config_reset_searches (NMIP4Config *config);
void nm_ip4_config_add_search (NMIP4Config *config, const char *search);
+void nm_ip4_config_del_search (NMIP4Config *config, guint i);
guint32 nm_ip4_config_get_num_searches (NMIP4Config *config);
const char * nm_ip4_config_get_search (NMIP4Config *config, guint i);
@@ -115,6 +121,7 @@ guint32 nm_ip4_config_get_ptp_address (NMIP4Config *config);
/* NIS */
void nm_ip4_config_reset_nis_servers (NMIP4Config *config);
void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis);
+void nm_ip4_config_del_nis_server (NMIP4Config *config, guint i);
guint32 nm_ip4_config_get_num_nis_servers (NMIP4Config *config);
guint32 nm_ip4_config_get_nis_server (NMIP4Config *config, guint i);
void nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain);
@@ -123,6 +130,7 @@ const char * nm_ip4_config_get_nis_domain (NMIP4Config *config);
/* WINS */
void nm_ip4_config_reset_wins (NMIP4Config *config);
void nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins);
+void nm_ip4_config_del_wins (NMIP4Config *config, guint i);
guint32 nm_ip4_config_get_num_wins (NMIP4Config *config);
guint32 nm_ip4_config_get_wins (NMIP4Config *config, guint i);
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index cb972c8d7d..2132b38fb4 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -11,7 +11,8 @@ INCLUDES = \
noinst_PROGRAMS = \
test-dhcp-options \
test-policy-hosts \
- test-wifi-ap-utils
+ test-wifi-ap-utils \
+ test-ip4-config
####### DHCP options test #######
@@ -50,13 +51,26 @@ test_wifi_ap_utils_CPPFLAGS = \
test_wifi_ap_utils_LDADD = \
$(top_builddir)/src/libNetworkManager.la
+####### ip4 config test #######
+
+test_ip4_config_SOURCES = \
+ test-ip4-config.c
+
+test_ip4_config_CPPFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+test_ip4_config_LDADD = \
+ $(top_builddir)/src/libNetworkManager.la
+
####### secret agent interface test #######
EXTRA_DIST = test-secret-agent.py
###########################################
-check-local: test-dhcp-options test-policy-hosts test-wifi-ap-utils
+check-local: test-dhcp-options test-policy-hosts test-wifi-ap-utils test-ip4-config
$(abs_builddir)/test-dhcp-options
$(abs_builddir)/test-policy-hosts
$(abs_builddir)/test-wifi-ap-utils
+ $(abs_builddir)/test-ip4-config
diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c
new file mode 100644
index 0000000000..373bf2eee2
--- /dev/null
+++ b/src/tests/test-ip4-config.c
@@ -0,0 +1,189 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "nm-ip4-config.h"
+
+static void
+addr_init (NMPlatformIP4Address *a, const char *addr, guint plen)
+{
+ memset (a, 0, sizeof (*a));
+ g_assert (inet_pton (AF_INET, addr, (void *) &a->address) == 1);
+ a->plen = plen;
+}
+
+static NMIP4Route *
+route_new (const char *network, guint plen, const char *gw)
+{
+ NMIP4Route *route;
+ guint n;
+
+ route = nm_ip4_route_new ();
+ g_assert (inet_pton (AF_INET, network, (void *) &n) == 1);
+ nm_ip4_route_set_dest (route, n);
+ nm_ip4_route_set_prefix (route, plen);
+ if (gw) {
+ n = 0;
+ g_assert (inet_pton (AF_INET, gw, (void *) &n) == 1);
+ nm_ip4_route_set_next_hop (route, n);
+ }
+ return route;
+}
+
+static guint32
+addr_to_num (const char *addr)
+{
+ guint n;
+
+ g_assert (inet_pton (AF_INET, addr, (void *) &n) == 1);
+ return n;
+}
+
+static NMIP4Config *
+build_test_config (void)
+{
+ NMIP4Config *config;
+ NMPlatformIP4Address addr;
+ NMIP4Route *route;
+
+ /* Build up the config to subtract */
+ config = nm_ip4_config_new ();
+
+ addr_init (&addr, "192.168.1.10", 24);
+ nm_ip4_config_add_address (config, &addr);
+
+ route = route_new ("10.0.0.0", 8, "192.168.1.1");
+ nm_ip4_config_take_route (config, route);
+
+ route = route_new ("172.16.0.0", 16, "192.168.1.1");
+ nm_ip4_config_take_route (config, route);
+
+ nm_ip4_config_set_gateway (config, addr_to_num ("192.168.1.1"));
+
+ nm_ip4_config_add_nameserver (config, addr_to_num ("4.2.2.1"));
+ nm_ip4_config_add_nameserver (config, addr_to_num ("4.2.2.2"));
+ nm_ip4_config_add_domain (config, "foobar.com");
+ nm_ip4_config_add_domain (config, "baz.com");
+ nm_ip4_config_add_search (config, "blahblah.com");
+ nm_ip4_config_add_search (config, "beatbox.com");
+
+ nm_ip4_config_set_ptp_address (config, addr_to_num ("1.2.3.4"));
+
+ nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.9"));
+ nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.10"));
+
+ nm_ip4_config_add_wins (config, addr_to_num ("4.2.3.9"));
+ nm_ip4_config_add_wins (config, addr_to_num ("4.2.3.10"));
+
+ return config;
+}
+
+static void
+test_subtract (void)
+{
+ NMIP4Config *src, *dst;
+ NMPlatformIP4Address addr;
+ const NMPlatformIP4Address *test_addr;
+ NMIP4Route *route;
+ const char *expected_addr = "192.168.1.12";
+ guint32 expected_addr_plen = 24;
+ const char *expected_route_dest = "8.7.6.5";
+ guint32 expected_route_plen = 8;
+ const char *expected_route_next_hop = "192.168.1.1";
+ guint32 expected_ns1 = addr_to_num ("8.8.8.8");
+ guint32 expected_ns2 = addr_to_num ("8.8.8.9");
+ const char *expected_domain = "wonderfalls.com";
+ const char *expected_search = "somewhere.com";
+ guint32 expected_nis = addr_to_num ("1.2.3.13");
+ guint32 expected_wins = addr_to_num ("2.3.4.5");
+
+ src = build_test_config ();
+
+ /* add a couple more things to the test config */
+ dst = build_test_config ();
+ addr_init (&addr, expected_addr, expected_addr_plen);
+ nm_ip4_config_add_address (dst, &addr);
+
+ route = route_new (expected_route_dest, expected_route_plen, expected_route_next_hop);
+ nm_ip4_config_take_route (dst, route);
+
+ nm_ip4_config_add_nameserver (dst, expected_ns1);
+ nm_ip4_config_add_nameserver (dst, expected_ns2);
+ nm_ip4_config_add_domain (dst, expected_domain);
+ nm_ip4_config_add_search (dst, expected_search);
+
+ nm_ip4_config_add_nis_server (dst, expected_nis);
+ nm_ip4_config_add_wins (dst, expected_wins);
+
+ nm_ip4_config_subtract (dst, src);
+
+ /* ensure what's left is what we expect */
+ g_assert_cmpuint (nm_ip4_config_get_num_addresses (dst), ==, 1);
+ test_addr = nm_ip4_config_get_address (dst, 0);
+ g_assert (test_addr != NULL);
+ g_assert_cmpuint (test_addr->address, ==, addr_to_num (expected_addr));
+ g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
+
+ g_assert_cmpuint (nm_ip4_config_get_ptp_address (dst), ==, 0);
+ g_assert_cmpuint (nm_ip4_config_get_gateway (dst), ==, 0);
+
+ g_assert_cmpuint (nm_ip4_config_get_num_routes (dst), ==, 1);
+ route = nm_ip4_config_get_route (dst, 0);
+ g_assert (route != NULL);
+ g_assert_cmpuint (nm_ip4_route_get_dest (route), ==, addr_to_num (expected_route_dest));
+ g_assert_cmpuint (nm_ip4_route_get_prefix (route), ==, expected_route_plen);
+ g_assert_cmpuint (nm_ip4_route_get_next_hop (route), ==, addr_to_num (expected_route_next_hop));
+
+ g_assert_cmpuint (nm_ip4_config_get_num_nameservers (dst), ==, 2);
+ g_assert_cmpuint (nm_ip4_config_get_nameserver (dst, 0), ==, expected_ns1);
+ g_assert_cmpuint (nm_ip4_config_get_nameserver (dst, 1), ==, expected_ns2);
+
+ g_assert_cmpuint (nm_ip4_config_get_num_domains (dst), ==, 1);
+ g_assert_cmpstr (nm_ip4_config_get_domain (dst, 0), ==, expected_domain);
+ g_assert_cmpuint (nm_ip4_config_get_num_searches (dst), ==, 1);
+ g_assert_cmpstr (nm_ip4_config_get_search (dst, 0), ==, expected_search);
+
+ g_assert_cmpuint (nm_ip4_config_get_num_nis_servers (dst), ==, 1);
+ g_assert_cmpuint (nm_ip4_config_get_nis_server (dst, 0), ==, expected_nis);
+
+ g_assert_cmpuint (nm_ip4_config_get_num_wins (dst), ==, 1);
+ g_assert_cmpuint (nm_ip4_config_get_wins (dst, 0), ==, expected_wins);
+
+ g_object_unref (src);
+ g_object_unref (dst);
+}
+
+/*******************************************/
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_type_init ();
+
+ g_test_add_func ("/ip4-config/subtract", test_subtract);
+
+ return g_test_run ();
+}
+