NetworkManager/src/tests/test-ip4-config.c
Thomas Haller aee48dfd44 core: adjust route equality for NMIP4Config/NMIP6Config to what kernel does
For kernel, route ID compare identical according to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID.
Well, mostly. In practice, NM ignores several route properties that
kernel considers part of the ID too. This leaves the possibility that
kernel allows addition of two routes that compare idential for
NetworkManager.

Anyway, NMIP4Config/NMIP6Config should use the same equality as platform
cache. Otherwise, there is the odd situation that ip-config merges routes
that are treated as different by kernel.

For IP addresses the ID operator already corresponded to what kernel
does. There is no change for addresses.

Note that NMSettingIPConfig also uses a different algorithm for
comparing routes. But that doesn't really matter here, it it differed
before too.
2017-09-13 08:17:31 +02:00

347 lines
12 KiB
C

/* -*- 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 - 2014 Red Hat, Inc.
*
*/
#include "nm-default.h"
#include <string.h>
#include <arpa/inet.h>
#include "nm-ip4-config.h"
#include "platform/nm-platform.h"
#include "nm-test-utils-core.h"
static NMIP4Config *
build_test_config (void)
{
NMIP4Config *config;
NMPlatformIP4Address addr;
NMPlatformIP4Route route;
/* Build up the config to subtract */
config = nmtst_ip4_config_new (1);
addr = *nmtst_platform_ip4_address ("192.168.1.10", "1.2.3.4", 24);
nm_ip4_config_add_address (config, &addr);
route = *nmtst_platform_ip4_route ("10.0.0.0", 8, "192.168.1.1");
nm_ip4_config_add_route (config, &route, NULL);
route = *nmtst_platform_ip4_route ("172.16.0.0", 16, "192.168.1.1");
nm_ip4_config_add_route (config, &route, NULL);
nm_ip4_config_set_gateway (config, nmtst_inet4_from_string ("192.168.1.1"));
nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("4.2.2.1"));
nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("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_add_nis_server (config, nmtst_inet4_from_string ("1.2.3.9"));
nm_ip4_config_add_nis_server (config, nmtst_inet4_from_string ("1.2.3.10"));
nm_ip4_config_add_wins (config, nmtst_inet4_from_string ("4.2.3.9"));
nm_ip4_config_add_wins (config, nmtst_inet4_from_string ("4.2.3.10"));
return config;
}
static void
test_subtract (void)
{
NMIP4Config *src, *dst;
NMPlatformIP4Address addr;
NMPlatformIP4Route route;
const NMPlatformIP4Address *test_addr;
const NMPlatformIP4Route *test_route;
const char *expected_addr = "192.168.1.12";
guint32 expected_addr_plen = 24;
const char *expected_route_dest = "8.0.0.0";
guint32 expected_route_plen = 8;
const char *expected_route_next_hop = "192.168.1.1";
guint32 expected_ns1 = nmtst_inet4_from_string ("8.8.8.8");
guint32 expected_ns2 = nmtst_inet4_from_string ("8.8.8.9");
const char *expected_domain = "wonderfalls.com";
const char *expected_search = "somewhere.com";
guint32 expected_nis = nmtst_inet4_from_string ("1.2.3.13");
guint32 expected_wins = nmtst_inet4_from_string ("2.3.4.5");
guint32 expected_mss = 1400;
guint32 expected_mtu = 1492;
src = build_test_config ();
/* add a couple more things to the test config */
dst = build_test_config ();
addr = *nmtst_platform_ip4_address (expected_addr, NULL, expected_addr_plen);
nm_ip4_config_add_address (dst, &addr);
route = *nmtst_platform_ip4_route (expected_route_dest, expected_route_plen, expected_route_next_hop);
nm_ip4_config_add_route (dst, &route, NULL);
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_set_mss (dst, expected_mss);
nm_ip4_config_set_mtu (dst, expected_mtu, NM_IP_CONFIG_SOURCE_UNKNOWN);
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 = _nmtst_ip4_config_get_address (dst, 0);
g_assert (test_addr != NULL);
g_assert_cmpuint (test_addr->address, ==, nmtst_inet4_from_string (expected_addr));
g_assert_cmpuint (test_addr->peer_address, ==, test_addr->address);
g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
g_assert_cmpuint (nm_ip4_config_get_gateway (dst), ==, 0);
g_assert_cmpuint (nm_ip4_config_get_num_routes (dst), ==, 1);
test_route = _nmtst_ip4_config_get_route (dst, 0);
g_assert (test_route != NULL);
g_assert_cmpuint (test_route->network, ==, nmtst_inet4_from_string (expected_route_dest));
g_assert_cmpuint (test_route->plen, ==, expected_route_plen);
g_assert_cmpuint (test_route->gateway, ==, nmtst_inet4_from_string (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_assert_cmpuint (nm_ip4_config_get_mss (dst), ==, expected_mss);
g_assert_cmpuint (nm_ip4_config_get_mtu (dst), ==, expected_mtu);
g_object_unref (src);
g_object_unref (dst);
}
static void
test_compare_with_source (void)
{
NMIP4Config *a, *b;
NMPlatformIP4Address addr;
NMPlatformIP4Route route;
a = nmtst_ip4_config_new (1);
b = nmtst_ip4_config_new (2);
/* Address */
addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24);
addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
addr.addr_source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip4_config_add_address (b, &addr);
/* Route */
route = *nmtst_platform_ip4_route ("10.0.0.0", 8, "192.168.1.1");
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_route (a, &route, NULL);
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip4_config_add_route (b, &route, NULL);
/* Assert that the configs are basically the same, eg that the source is ignored */
g_assert (nm_ip4_config_equal (a, b));
g_object_unref (a);
g_object_unref (b);
}
static void
test_add_address_with_source (void)
{
NMIP4Config *a;
NMPlatformIP4Address addr;
const NMPlatformIP4Address *test_addr;
a = nmtst_ip4_config_new (1);
/* Test that a higher priority source is not overwritten */
addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24);
addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
test_addr = _nmtst_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
addr.addr_source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip4_config_add_address (a, &addr);
test_addr = _nmtst_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
/* Test that a lower priority address source is overwritten */
_nmtst_ip4_config_del_address (a, 0);
addr.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
nm_ip4_config_add_address (a, &addr);
test_addr = _nmtst_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
test_addr = _nmtst_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
g_object_unref (a);
}
static void
test_add_route_with_source (void)
{
gs_unref_object NMIP4Config *a = NULL;
NMPlatformIP4Route route;
const NMPlatformIP4Route *test_route;
a = nmtst_ip4_config_new (1);
/* Test that a higher priority source is not overwritten */
route = *nmtst_platform_ip4_route ("1.2.3.0", 24, "1.2.3.1");
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
_nmtst_ip4_config_del_route (a, 0);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 0);
/* Test that a lower priority address source is overwritten */
route.rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_RTPROT_KERNEL);
route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
}
static void
test_merge_subtract_mss_mtu (void)
{
NMIP4Config *cfg1, *cfg2, *cfg3;
guint32 expected_mss2 = 1400;
guint32 expected_mtu2 = 1492;
guint32 expected_mss3 = 555;
guint32 expected_mtu3 = 666;
cfg1 = build_test_config ();
cfg2 = build_test_config ();
cfg3 = build_test_config ();
/* add MSS, MTU to configs to test them */
nm_ip4_config_set_mss (cfg2, expected_mss2);
nm_ip4_config_set_mtu (cfg2, expected_mtu2, NM_IP_CONFIG_SOURCE_UNKNOWN);
nm_ip4_config_set_mss (cfg3, expected_mss3);
nm_ip4_config_set_mtu (cfg3, expected_mtu3, NM_IP_CONFIG_SOURCE_UNKNOWN);
nm_ip4_config_merge (cfg1, cfg2, NM_IP_CONFIG_MERGE_DEFAULT);
/* ensure MSS and MTU are in cfg1 */
g_assert_cmpuint (nm_ip4_config_get_mss (cfg1), ==, expected_mss2);
g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, expected_mtu2);
nm_ip4_config_merge (cfg1, cfg3, NM_IP_CONFIG_MERGE_DEFAULT);
/* ensure again the MSS and MTU in cfg1 got overridden */
g_assert_cmpuint (nm_ip4_config_get_mss (cfg1), ==, expected_mss3);
g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, expected_mtu3);
nm_ip4_config_subtract (cfg1, cfg3);
/* ensure MSS and MTU are zero in cfg1 */
g_assert_cmpuint (nm_ip4_config_get_mss (cfg1), ==, 0);
g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, 0);
g_object_unref (cfg1);
g_object_unref (cfg2);
g_object_unref (cfg3);
}
static void
test_strip_search_trailing_dot (void)
{
NMIP4Config *config;
config = nmtst_ip4_config_new (1);
nm_ip4_config_add_search (config, ".");
nm_ip4_config_add_search (config, "foo");
nm_ip4_config_add_search (config, "bar.");
nm_ip4_config_add_search (config, "baz.com");
nm_ip4_config_add_search (config, "baz.com.");
g_assert_cmpuint (nm_ip4_config_get_num_searches (config), ==, 3);
g_assert_cmpstr (nm_ip4_config_get_search (config, 0), ==, "foo");
g_assert_cmpstr (nm_ip4_config_get_search (config, 1), ==, "bar");
g_assert_cmpstr (nm_ip4_config_get_search (config, 2), ==, "baz.com");
g_object_unref (config);
}
/*****************************************************************************/
NMTST_DEFINE ();
int
main (int argc, char **argv)
{
nmtst_init_with_logging (&argc, &argv, NULL, "DEFAULT");
g_test_add_func ("/ip4-config/subtract", test_subtract);
g_test_add_func ("/ip4-config/compare-with-source", test_compare_with_source);
g_test_add_func ("/ip4-config/add-address-with-source", test_add_address_with_source);
g_test_add_func ("/ip4-config/add-route-with-source", test_add_route_with_source);
g_test_add_func ("/ip4-config/merge-subtract-mss-mtu", test_merge_subtract_mss_mtu);
g_test_add_func ("/ip4-config/strip-search-trailing-dot", test_strip_search_trailing_dot);
return g_test_run ();
}