core: add nm_ip4_config_subtract()

Removes anything in 'src' from 'dst'.
This commit is contained in:
Dan Williams 2013-08-01 14:04:35 -05:00
parent 5c1ec7cedf
commit 7e21b528a9
4 changed files with 428 additions and 2 deletions

View file

@ -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)
{

View file

@ -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);

View file

@ -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

189
src/tests/test-ip4-config.c Normal file
View file

@ -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 ();
}