/
niceSOFT
/
systemd
Обзор
Документация
Войти
/
niceSOFT
/
systemd
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/network/test-network.c
252 строки
10 KB
Luca Boccassi
network: cancel netlink calls for detached requests
15 июл 2026, 21:21
15 июл 2026, 21:21
890dd23
Код
Авторство
О чём код?
/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include <net/if.h> #include "sd-netlink.h" #include "alloc-util.h" #include "hashmap.h" #include "hostname-setup.h" #include "netlink-util.h" #include "network-internal.h" #include "networkd-manager.h" #include "networkd-queue.h" #include "networkd-route-util.h" #include "ordered-set.h" #include "strv.h" #include "tests.h" #include "vrf.h" TEST(deserialize_in_addr) { _cleanup_free_ struct in_addr *addresses = NULL; _cleanup_free_ struct in6_addr *addresses6 = NULL; union in_addr_union a, b, c, d, e, f; static const char *addresses_string = "192.168.0.1 0:0:0:0:0:FFFF:204.152.189.116 192.168.0.2 ::1 192.168.0.3 1:0:0:0:0:0:0:8"; ASSERT_ERROR(in_addr_from_string(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a), EINVAL); ASSERT_ERROR(in_addr_from_string(AF_INET6, "192.168.0.1", &d), EINVAL); ASSERT_OK(in_addr_from_string(AF_INET, "192.168.0.1", &a)); ASSERT_OK(in_addr_from_string(AF_INET, "192.168.0.2", &b)); ASSERT_OK(in_addr_from_string(AF_INET, "192.168.0.3", &c)); ASSERT_OK(in_addr_from_string(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d)); ASSERT_OK(in_addr_from_string(AF_INET6, "::1", &e)); ASSERT_OK(in_addr_from_string(AF_INET6, "1:0:0:0:0:0:0:8", &f)); ASSERT_OK_EQ(deserialize_in_addrs(&addresses, addresses_string), 3); ASSERT_NOT_NULL(addresses); ASSERT_TRUE(in4_addr_equal(&a.in, &addresses[0])); ASSERT_TRUE(in4_addr_equal(&b.in, &addresses[1])); ASSERT_TRUE(in4_addr_equal(&c.in, &addresses[2])); ASSERT_OK_EQ(deserialize_in6_addrs(&addresses6, addresses_string), 3); ASSERT_NOT_NULL(addresses6); ASSERT_TRUE(in6_addr_equal(&d.in6, &addresses6[0])); ASSERT_TRUE(in6_addr_equal(&e.in6, &addresses6[1])); ASSERT_TRUE(in6_addr_equal(&f.in6, &addresses6[2])); } static void test_route_tables_one(Manager *manager, const char *name, uint32_t number) { _cleanup_free_ char *str = NULL, *expected = NULL, *num_str = NULL; uint32_t t; if (!STR_IN_SET(name, "default", "main", "local")) { ASSERT_STREQ(hashmap_get(manager->route_table_names_by_number, UINT32_TO_PTR(number)), name); ASSERT_EQ(PTR_TO_UINT32(hashmap_get(manager->route_table_numbers_by_name, name)), number); } ASSERT_OK(asprintf(&expected, "%s(%" PRIu32 ")", name, number)); ASSERT_OK(manager_get_route_table_to_string(manager, number, /* append_num= */ true, &str)); ASSERT_STREQ(str, expected); str = mfree(str); ASSERT_OK(manager_get_route_table_to_string(manager, number, /* append_num= */ false, &str)); ASSERT_STREQ(str, name); ASSERT_OK(manager_get_route_table_from_string(manager, name, &t)); ASSERT_EQ(t, number); ASSERT_OK(asprintf(&num_str, "%" PRIu32, number)); ASSERT_OK(manager_get_route_table_from_string(manager, num_str, &t)); ASSERT_EQ(t, number); } TEST(route_tables) { _cleanup_(manager_freep) Manager *manager = NULL; ASSERT_OK(manager_new(&manager, /* test_mode= */ true)); ASSERT_OK(manager_setup(manager)); ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "hoge:123 foo:456 aaa:111", manager, manager)); ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "bbb:11111 ccc:22222", manager, manager)); ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "ddd:22222", manager, manager)); test_route_tables_one(manager, "hoge", 123); test_route_tables_one(manager, "foo", 456); test_route_tables_one(manager, "aaa", 111); test_route_tables_one(manager, "bbb", 11111); test_route_tables_one(manager, "ccc", 22222); ASSERT_FALSE(hashmap_contains(manager->route_table_numbers_by_name, "ddd")); test_route_tables_one(manager, "default", 253); test_route_tables_one(manager, "main", 254); test_route_tables_one(manager, "local", 255); ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "", manager, manager)); ASSERT_NULL(manager->route_table_names_by_number); ASSERT_NULL(manager->route_table_numbers_by_name); /* Invalid pairs */ ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "main:123 default:333 local:999", manager, manager)); ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "xxx:253 yyy:254 local:255", manager, manager)); ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "1234:321 :567 hoge:foo aaa:-888", manager, manager)); ASSERT_NULL(manager->route_table_names_by_number); ASSERT_NULL(manager->route_table_numbers_by_name); test_route_tables_one(manager, "default", 253); test_route_tables_one(manager, "main", 254); test_route_tables_one(manager, "local", 255); } TEST(vrf_table) { _cleanup_(manager_freep) Manager *manager = NULL; Vrf vrf = {}; ASSERT_OK(manager_new(&manager, /* test_mode= */ true)); ASSERT_OK(manager_setup(manager)); vrf.meta.manager = manager; ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "default", &vrf.table, &vrf)); ASSERT_EQ(vrf.table, 253U); ASSERT_OK(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "vrf-test:1234", manager, manager)); ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "vrf-test", &vrf.table, &vrf)); ASSERT_EQ(vrf.table, 1234U); ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "5678", &vrf.table, &vrf)); ASSERT_EQ(vrf.table, 5678U); ASSERT_OK(config_parse_vrf_table("netdev", "filename", 1, "VRF", 1, "Table", 0, "no-such-table", &vrf.table, &vrf)); ASSERT_EQ(vrf.table, 5678U); } static int test_request_process(Request *req, Link *link, void *userdata) { assert_not_reached(); } static int test_request_netlink_handler( sd_netlink *rtnl, sd_netlink_message *message, Request *req, Link *link, void *userdata) { assert(rtnl); assert(message); assert(req); assert(!link); assert(userdata); *(bool*) userdata = true; return 0; } static void test_request_netlink_handler_one(bool detach) { _cleanup_(manager_freep) Manager *manager = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; bool handler_called = false; unsigned counter = 0; Request *req; ASSERT_OK(manager_new(&manager, /* test_mode= */ true)); ASSERT_OK(sd_netlink_open(&rtnl)); ASSERT_OK_POSITIVE(manager_queue_request_full( manager, REQUEST_TYPE_ADDRESS_LABEL, &handler_called, /* free_func= */ NULL, /* hash_func= */ NULL, /* compare_func= */ NULL, test_request_process, &counter, test_request_netlink_handler, &req)); ASSERT_EQ(counter, 1U); int ifindex = (int) if_nametoindex("lo"); ASSERT_GT(ifindex, 0); ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex)); ASSERT_OK(request_call_netlink_async(rtnl, message, req)); ASSERT_EQ(netlink_get_reply_callback_count(rtnl), 1U); if (detach) { request_detach(req); ASSERT_EQ(counter, 0U); ASSERT_EQ(netlink_get_reply_callback_count(rtnl), 0U); } ASSERT_OK(sd_netlink_wait(rtnl, 0)); ASSERT_OK_POSITIVE(sd_netlink_process(rtnl, /* ret= */ NULL)); ASSERT_EQ(handler_called, !detach); ASSERT_EQ(counter, 0U); ASSERT_EQ(netlink_get_reply_callback_count(rtnl), 0U); ASSERT_TRUE(ordered_set_isempty(manager->request_queue)); } TEST(request_netlink_handler_called) { test_request_netlink_handler_one(/* detach= */ false); } TEST(request_netlink_handler_detached) { test_request_netlink_handler_one(/* detach= */ true); } TEST(manager_enumerate) { _cleanup_(manager_freep) Manager *manager = NULL; ASSERT_OK(manager_new(&manager, /* test_mode= */ true)); ASSERT_OK(manager_setup(manager)); /* TODO: should_reload, is false if the config dirs do not exist, so we can't do this test here, move * it to a test for paths_check_timestamps directly. */ if (ASSERT_OK_OR(manager_load_config(manager), -EPERM) < 0) return (void) log_tests_skipped("Cannot load configuration files"); ASSERT_OK(manager_enumerate(manager)); } TEST(dhcp_hostname_shorten_overlong) { _cleanup_free_ char *s = NULL; /* simple hostname, no actions, no errors */ ASSERT_OK_ZERO(shorten_overlong("name1", &s)); ASSERT_STREQ(s, "name1"); s = mfree(s); /* simple fqdn, no actions, no errors */ ASSERT_OK_ZERO(shorten_overlong("name1.example.com", &s)); ASSERT_STREQ(s, "name1.example.com"); s = mfree(s); /* overlong fqdn, cut to first dot, no errors */ ASSERT_OK_POSITIVE(shorten_overlong("name1.test-dhcp-this-one-here-is-a-very-very-long-domain.example.com", &s)); ASSERT_STREQ(s, "name1"); s = mfree(s); /* overlong hostname, cut to HOST_MAX_LEN, no errors */ ASSERT_OK_POSITIVE(shorten_overlong("test-dhcp-this-one-here-is-a-very-very-long-hostname-without-domainname", &s)); ASSERT_STREQ(s, "test-dhcp-this-one-here-is-a-very-very-long-hostname-without-dom"); s = mfree(s); /* overlong fqdn, cut to first dot, empty result error */ ASSERT_ERROR(shorten_overlong(".test-dhcp-this-one-here-is-a-very-very-long-hostname.example.com", &s), EDOM); ASSERT_NULL(s); } DEFINE_TEST_MAIN(LOG_INFO);