summary refs log tree commit diff
path: root/src/core/platform/tests/test-address.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/platform/tests/test-address.c')
-rw-r--r--src/core/platform/tests/test-address.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/src/core/platform/tests/test-address.c b/src/core/platform/tests/test-address.c
new file mode 100644
index 00000000..d4d67105
--- /dev/null
+++ b/src/core/platform/tests/test-address.c
@@ -0,0 +1,465 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ */
+
+#include "src/core/nm-default-daemon.h"
+
+#include "test-common.h"
+
+#define IP4_ADDRESS       "192.0.2.1"
+#define IP4_ADDRESS_PEER  "192.0.2.2"
+#define IP4_ADDRESS_PEER2 "192.0.3.1"
+#define IP4_PLEN          24
+#define IP6_ADDRESS       "2001:db8:a:b:1:2:3:4"
+#define IP6_PLEN          64
+
+#define DEVICE_IFINDEX NMTSTP_ENV1_IFINDEX
+#define EX             NMTSTP_ENV1_EX
+
+/*****************************************************************************/
+
+static void
+ip4_address_callback(NMPlatform *               platform,
+                     NMPObjectType              obj_type,
+                     int                        ifindex,
+                     NMPlatformIP4Address *     received,
+                     NMPlatformSignalChangeType change_type,
+                     SignalData *               data)
+{
+    g_assert(received);
+    g_assert_cmpint(received->ifindex, ==, ifindex);
+    g_assert(data && data->name);
+    g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED);
+
+    if (data->ifindex && data->ifindex != received->ifindex)
+        return;
+    if (data->change_type != change_type)
+        return;
+
+    if (data->loop)
+        g_main_loop_quit(data->loop);
+
+    data->received_count++;
+    _LOGD("Received signal '%s' %dth time.", data->name, data->received_count);
+}
+
+static void
+ip6_address_callback(NMPlatform *               platform,
+                     NMPObjectType              obj_type,
+                     int                        ifindex,
+                     NMPlatformIP6Address *     received,
+                     NMPlatformSignalChangeType change_type,
+                     SignalData *               data)
+{
+    g_assert(received);
+    g_assert_cmpint(received->ifindex, ==, ifindex);
+    g_assert(data && data->name);
+    g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED);
+
+    if (data->ifindex && data->ifindex != received->ifindex)
+        return;
+    if (data->change_type != change_type)
+        return;
+
+    if (data->loop)
+        g_main_loop_quit(data->loop);
+
+    data->received_count++;
+    _LOGD("Received signal '%s' %dth time.", data->name, data->received_count);
+}
+
+/*****************************************************************************/
+
+static void
+test_ip4_address_general(void)
+{
+    const int   ifindex         = DEVICE_IFINDEX;
+    SignalData *address_added   = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+                                                   NM_PLATFORM_SIGNAL_ADDED,
+                                                   ip4_address_callback,
+                                                   ifindex);
+    SignalData *address_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+                                                     NM_PLATFORM_SIGNAL_CHANGED,
+                                                     ip4_address_callback,
+                                                     ifindex);
+    SignalData *address_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+                                                     NM_PLATFORM_SIGNAL_REMOVED,
+                                                     ip4_address_callback,
+                                                     ifindex);
+    GArray *    addresses;
+    NMPlatformIP4Address *address;
+    in_addr_t             addr;
+    guint32               lifetime  = 2000;
+    guint32               preferred = 1000;
+
+    inet_pton(AF_INET, IP4_ADDRESS, &addr);
+
+    /* Add address */
+    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+    nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
+    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+    accept_signal(address_added);
+
+    /* Add address again (aka update) */
+    nmtstp_ip4_address_add(NULL,
+                           EX,
+                           ifindex,
+                           addr,
+                           IP4_PLEN,
+                           addr,
+                           lifetime + 100,
+                           preferred + 50,
+                           0,
+                           NULL);
+    accept_signals(address_changed, 0, 1);
+
+    /* Test address listing */
+    addresses = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
+    g_assert(addresses);
+    g_assert_cmpint(addresses->len, ==, 1);
+    address = &g_array_index(addresses, NMPlatformIP4Address, 0);
+    g_assert_cmpint(address->ifindex, ==, ifindex);
+    g_assert_cmphex(address->address, ==, addr);
+    g_assert_cmphex(address->peer_address, ==, addr);
+    g_assert_cmpint(address->plen, ==, IP4_PLEN);
+    g_array_unref(addresses);
+
+    /* Remove address */
+    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr);
+    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+    accept_signal(address_removed);
+
+    /* Remove address again */
+    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr);
+
+    free_signal(address_added);
+    free_signal(address_changed);
+    free_signal(address_removed);
+}
+
+static void
+test_ip6_address_general(void)
+{
+    const int   ifindex         = DEVICE_IFINDEX;
+    SignalData *address_added   = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
+                                                   NM_PLATFORM_SIGNAL_ADDED,
+                                                   ip6_address_callback,
+                                                   ifindex);
+    SignalData *address_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
+                                                     NM_PLATFORM_SIGNAL_CHANGED,
+                                                     ip6_address_callback,
+                                                     ifindex);
+    SignalData *address_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
+                                                     NM_PLATFORM_SIGNAL_REMOVED,
+                                                     ip6_address_callback,
+                                                     ifindex);
+    GArray *    addresses;
+    NMPlatformIP6Address *address;
+    struct in6_addr       addr;
+    guint32               lifetime  = 2000;
+    guint32               preferred = 1000;
+    guint                 flags     = 0;
+
+    inet_pton(AF_INET6, IP6_ADDRESS, &addr);
+
+    /* Add address */
+    g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
+    nmtstp_ip6_address_add(NULL,
+                           EX,
+                           ifindex,
+                           addr,
+                           IP6_PLEN,
+                           in6addr_any,
+                           lifetime,
+                           preferred,
+                           flags);
+    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
+    accept_signal(address_added);
+
+    /* Add address again (aka update) */
+    nmtstp_ip6_address_add(NULL,
+                           EX,
+                           ifindex,
+                           addr,
+                           IP6_PLEN,
+                           in6addr_any,
+                           lifetime,
+                           preferred,
+                           flags);
+    accept_signals(address_changed, 0, 2);
+
+    /* Test address listing */
+    addresses = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex);
+    g_assert(addresses);
+    g_assert_cmpint(addresses->len, ==, 1);
+    address = &g_array_index(addresses, NMPlatformIP6Address, 0);
+    g_assert_cmpint(address->ifindex, ==, ifindex);
+    g_assert(!memcmp(&address->address, &addr, sizeof(addr)));
+    g_assert_cmpint(address->plen, ==, IP6_PLEN);
+    g_array_unref(addresses);
+
+    /* Remove address */
+    nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN);
+    g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
+    accept_signal(address_removed);
+
+    /* Remove address again */
+    nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN);
+
+    /* ensure not pending signal. */
+    accept_signals(address_changed, 0, 1);
+
+    free_signal(address_added);
+    free_signal(address_changed);
+    free_signal(address_removed);
+}
+
+static void
+test_ip4_address_general_2(void)
+{
+    const int   ifindex         = DEVICE_IFINDEX;
+    SignalData *address_added   = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+                                           NM_PLATFORM_SIGNAL_ADDED,
+                                           ip4_address_callback);
+    SignalData *address_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+                                             NM_PLATFORM_SIGNAL_REMOVED,
+                                             ip4_address_callback);
+    in_addr_t   addr;
+    guint32     lifetime  = 2000;
+    guint32     preferred = 1000;
+
+    inet_pton(AF_INET, IP4_ADDRESS, &addr);
+    g_assert(ifindex > 0);
+
+    /* Looks like addresses are not announced by kernel when the interface
+     * is down. Link-local IPv6 address is automatically added.
+     */
+    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, DEVICE_IFINDEX, NULL));
+
+    /* Add/delete notification */
+    nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
+    accept_signal(address_added);
+    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr);
+    accept_signal(address_removed);
+    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+
+    /* Add/delete conflict */
+    nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
+    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+    accept_signal(address_added);
+
+    free_signal(address_added);
+    free_signal(address_removed);
+}
+
+static void
+test_ip6_address_general_2(void)
+{
+    const int       ifindex         = DEVICE_IFINDEX;
+    SignalData *    address_added   = add_signal(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
+                                           NM_PLATFORM_SIGNAL_ADDED,
+                                           ip6_address_callback);
+    SignalData *    address_removed = add_signal(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
+                                             NM_PLATFORM_SIGNAL_REMOVED,
+                                             ip6_address_callback);
+    struct in6_addr addr;
+    guint32         lifetime  = 2000;
+    guint32         preferred = 1000;
+    guint           flags     = 0;
+
+    inet_pton(AF_INET6, IP6_ADDRESS, &addr);
+
+    /* Add/delete notification */
+    nmtstp_ip6_address_add(NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
+    accept_signal(address_added);
+    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
+
+    nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN);
+    accept_signal(address_removed);
+    g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
+
+    /* Add/delete conflict */
+    nmtstp_ip6_address_add(NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
+    accept_signal(address_added);
+    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
+
+    nmtstp_ip6_address_add(NULL,
+                           EX,
+                           ifindex,
+                           addr,
+                           IP6_PLEN,
+                           in6addr_any,
+                           lifetime,
+                           preferred,
+                           flags);
+    ensure_no_signal(address_added);
+    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
+
+    free_signal(address_added);
+    free_signal(address_removed);
+}
+
+/*****************************************************************************/
+
+static void
+test_ip4_address_peer(void)
+{
+    const int                   ifindex         = DEVICE_IFINDEX;
+    SignalData *                address_added   = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+                                           NM_PLATFORM_SIGNAL_ADDED,
+                                           ip4_address_callback);
+    SignalData *                address_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+                                             NM_PLATFORM_SIGNAL_REMOVED,
+                                             ip4_address_callback);
+    in_addr_t                   addr, addr_peer, addr_peer2;
+    guint32                     lifetime  = 2000;
+    guint32                     preferred = 1000;
+    const NMPlatformIP4Address *a;
+
+    inet_pton(AF_INET, IP4_ADDRESS, &addr);
+    inet_pton(AF_INET, IP4_ADDRESS_PEER, &addr_peer);
+    inet_pton(AF_INET, IP4_ADDRESS_PEER2, &addr_peer2);
+    g_assert(ifindex > 0);
+
+    g_assert(addr != addr_peer);
+
+    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL));
+    accept_signals(address_removed, 0, G_MAXINT);
+    accept_signals(address_added, 0, G_MAXINT);
+
+    /* Add/delete notification */
+    nmtstp_ip4_address_add(NULL,
+                           EX,
+                           ifindex,
+                           addr,
+                           IP4_PLEN,
+                           addr_peer,
+                           lifetime,
+                           preferred,
+                           0,
+                           NULL);
+    accept_signal(address_added);
+    a = nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer);
+    g_assert(a);
+    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
+
+    nmtstp_ip_address_assert_lifetime((NMPlatformIPAddress *) a, -1, lifetime, preferred);
+
+    nmtstp_ip4_address_add(NULL,
+                           EX,
+                           ifindex,
+                           addr,
+                           IP4_PLEN,
+                           addr_peer2,
+                           lifetime,
+                           preferred,
+                           0,
+                           NULL);
+    accept_signal(address_added);
+    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
+    a = nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2);
+    g_assert(a);
+
+    nmtstp_ip_address_assert_lifetime((NMPlatformIPAddress *) a, -1, lifetime, preferred);
+
+    g_assert(addr != addr_peer);
+    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr_peer);
+    accept_signal(address_removed);
+    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
+    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
+
+    free_signal(address_added);
+    free_signal(address_removed);
+}
+
+/*****************************************************************************/
+
+static void
+test_ip4_address_peer_zero(void)
+{
+    const int   ifindex = DEVICE_IFINDEX;
+    in_addr_t   addr, addr_peer;
+    guint32     lifetime  = 2000;
+    guint32     preferred = 1000;
+    const gint8 plen      = 24;
+    const char *label     = NULL;
+    in_addr_t   peers[3], r_peers[3];
+    int         i;
+    GArray *    addrs;
+
+    g_assert(ifindex > 0);
+
+    inet_pton(AF_INET, "192.168.5.2", &addr);
+    inet_pton(AF_INET, "192.168.6.2", &addr_peer);
+    peers[0] = addr;
+    peers[1] = addr_peer;
+    peers[2] = 0;
+
+    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL));
+
+    nmtst_rand_perm(NULL, r_peers, peers, sizeof(peers[0]), G_N_ELEMENTS(peers));
+    for (i = 0; i < G_N_ELEMENTS(peers); i++) {
+        g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
+
+        nmtstp_ip4_address_add(NULL,
+                               EX,
+                               ifindex,
+                               addr,
+                               plen,
+                               r_peers[i],
+                               lifetime,
+                               preferred,
+                               0,
+                               label);
+
+        addrs = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
+        g_assert(addrs);
+        g_assert_cmpint(addrs->len, ==, i + 1);
+        g_array_unref(addrs);
+    }
+
+    if (nmtst_is_debug() && nmtstp_is_root_test())
+        nmtstp_run_command_check("ip address show dev %s", DEVICE_NAME);
+
+    nmtst_rand_perm(NULL, r_peers, peers, sizeof(peers[0]), G_N_ELEMENTS(peers));
+    for (i = 0; i < G_N_ELEMENTS(peers); i++) {
+        g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
+
+        nmtstp_ip4_address_del(NULL, EX, ifindex, addr, plen, r_peers[i]);
+
+        addrs = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
+        g_assert(addrs);
+        g_assert_cmpint(addrs->len, ==, G_N_ELEMENTS(peers) - i - 1);
+        g_array_unref(addrs);
+    }
+}
+
+/*****************************************************************************/
+
+NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
+
+void
+_nmtstp_init_tests(int *argc, char ***argv)
+{
+    nmtst_init_with_logging(argc, argv, NULL, "ALL");
+}
+
+/*****************************************************************************
+ * SETUP TESTS
+ *****************************************************************************/
+
+void
+_nmtstp_setup_tests(void)
+{
+#define add_test_func(testpath, test_func) nmtstp_env1_add_test_func(testpath, test_func, FALSE)
+    add_test_func("/address/ipv4/general", test_ip4_address_general);
+    add_test_func("/address/ipv6/general", test_ip6_address_general);
+
+    add_test_func("/address/ipv4/general-2", test_ip4_address_general_2);
+    add_test_func("/address/ipv6/general-2", test_ip6_address_general_2);
+
+    add_test_func("/address/ipv4/peer", test_ip4_address_peer);
+    add_test_func("/address/ipv4/peer/zero", test_ip4_address_peer_zero);
+}