Exercise IPv6 REALITY guards and reentrant node snapshot replacement

This commit is contained in:
evgeny committed 2026-10-24 20:15:30 +02:00
1 parent 496a3c788e
commit e137778ba2
2 files changed
+65 -2

No files matched your search

+1 -1
View File
@@ -721,7 +721,7 @@ test_ncd_faults_SOURCES = test_ncd_faults.c $(test_clock_sources)
test_ncd_faults_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
test_ncd_faults_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
test_ncd_faults_LDFLAGS = $(test_clock_ldflags) -Wl,--wrap=etcp_conn_add_cbk -Wl,--wrap=uasync_call_soon \
-Wl,--wrap=uasync_set_timeout -Wl,--wrap=u_calloc_impl
-Wl,--wrap=uasync_set_timeout -Wl,--wrap=u_calloc_impl -Wl,--wrap=socket_sendto
endif
test_group_ownership_SOURCES = test_group_ownership.c
+64 -1
View File
@@ -18,6 +18,11 @@ static struct UTUN_INSTANCE* inst;
static size_t allocations;
static int fail_callback, fail_soon, fail_connect, fail_alloc;
/* Здесь проверяем выбор пар и состояния; пакеты проб не отправляем в сеть. */
ssize_t __wrap_socket_sendto(socket_t fd, const void* data, size_t length, const struct sockaddr* addr, socklen_t size) {
(void)fd; (void)data; (void)addr; (void)size; return (ssize_t)length;
}
void __real_etcp_conn_add_cbk(struct ETCP_CONN*, etcp_cbk_fn, void*, int);
void __wrap_etcp_conn_add_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg, int events) {
if (!fail_callback) __real_etcp_conn_add_cbk(conn, fn, arg, events);
@@ -270,6 +275,63 @@ static void nested_remove(void) {
node_conn_direct_force_close(handle); teardown();
}
static void ipv6_candidates(void) {
setup(); struct TOPO_NODE* node = known_node(0);
struct TOPO_ADDR6* global = memory_pool_alloc(inst->topo_groups->v6_addr_pool); CHECK(global);
struct TOPO_ADDR6* local = memory_pool_alloc(inst->topo_groups->v6_addr_pool); CHECK(local);
*global = (struct TOPO_ADDR6){.addr = {0x20,1,0xd,0xb8,0,0,0,0,0,0,0,0,0,0,0,1}, .port = 9, .protocol = TOPO_PROTO_UDP};
*local = (struct TOPO_ADDR6){.addr = {0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, .port = 10,
.protocol = TOPO_PROTO_UDP, .next = global};
node->v6_addrs = local;
struct TOPO_SOCKMETA6* meta = memory_pool_alloc(inst->topo_groups->v6_sock_meta_pool); CHECK(meta);
*meta = (struct TOPO_SOCKMETA6){.config_type = CFG_SERVER_TYPE_PRIVATE}; node->v6_sock_meta = meta;
struct CFG_SERVER server = {.name = "NCD IPv6", .type = CFG_SERVER_TYPE_LOCAL, .mtu = 1280};
struct sockaddr_in6* addr = (struct sockaddr_in6*)&server.ip;
addr->sin6_family = AF_INET6; addr->sin6_addr = in6addr_loopback;
struct ETCP_SOCKET* sock = etcp_socket_add(inst, &server); CHECK(sock); sock->netif_index = 0;
struct NODE_CONN_DIRECT* handle = NULL;
CHECK(node_conn_direct_open(inst, node->node_id, NULL, NULL, &handle, NULL) == NCD_NEW);
struct ETCP_CONN* conn = node_conn_direct_get_conn(handle); CHECK(link_count(conn) == 1);
sock->netif_index = 1;
CHECK(ncd_add_socket_links(inst, sock) == 1 && link_count(conn) == 2);
CHECK(((struct sockaddr_in6*)&conn->links->remote_addr)->sin6_scope_id == 1);
node_conn_direct_force_close(handle); teardown();
}
static void missing_reality(void) {
setup(); struct TOPO_NODE* node = known_node(1);
node->v4_addrs->protocol = TOPO_PROTO_TCP | TOPO_PROTO_REALITY;
struct NODE_CONN_DIRECT* handle = NULL;
CHECK(node_conn_direct_open(inst, node->node_id, NULL, NULL, &handle, NULL) == NCD_NEW);
CHECK(!node_conn_direct_get_conn(handle)->links && !node_conn_direct_compatible(inst, node->node_id));
node_conn_direct_force_close(handle); teardown();
}
static void replace_addresses(struct ETCP_CONN* conn, struct ETCP_LINK* link, int old_state, int old_status, void* arg) {
(void)link; (void)old_status;
int* replaced = arg;
if (old_state != -1 || (*replaced)++) return;
struct TOPO_NODE* update = u_calloc(1, sizeof(*update)); CHECK(update);
struct TOPO_NODE* known = topo_node_registry_find(inst->topo_groups, conn->peer_node_id); CHECK(known);
update->node_id = known->node_id; memcpy(update->public_key, known->public_key, sizeof(update->public_key));
struct TOPO_ADDR4* addr = memory_pool_alloc(inst->topo_groups->v4_addr_pool); CHECK(addr);
*addr = (struct TOPO_ADDR4){.addr = {127,0,0,1}, .port = 12, .protocol = TOPO_PROTO_UDP}; update->v4_addrs = addr;
CHECK(topo_node_registry_store(inst->topo_groups, update) == known);
topo_node_registry_unref(inst->topo_groups, known->node_id);
}
static void snapshot_replaced(void) {
setup(); struct TOPO_NODE* node = known_node(2); local_socket();
struct NODE_CONN_DIRECT* handle = NULL; int replaced = 0;
etcp_add_link_status_cbk(inst, replace_addresses, &replaced);
CHECK(node_conn_direct_open(inst, node->node_id, NULL, NULL, &handle, NULL) == NCD_NEW);
etcp_remove_link_status_cbk(inst, replace_addresses, &replaced);
struct ETCP_CONN* conn = node_conn_direct_get_conn(handle);
CHECK(replaced == 2 && link_count(conn) == 2 && node->v4_addrs->port == 12);
CHECK(node_conn_direct_update_node(inst, node->node_id) == 1 && link_count(conn) == 3);
node_conn_direct_force_close(handle); teardown();
}
int main(int argc, char** argv) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO);
if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG);
@@ -278,7 +340,8 @@ int main(int argc, char** argv) {
{"callback", callback_failure}, {"up", up_failure}, {"timer", timer_failure},
{"fin_wait", fin_wait_failure}, {"nested", nested_events}, {"control", control_length},
{"new", new_transport_failures}, {"policy", candidate_policy}, {"capacity", socket_capacity},
{"cancel", open_cancelled}, {"remove", nested_remove}
{"cancel", open_cancelled}, {"remove", nested_remove}, {"ipv6", ipv6_candidates},
{"reality", missing_reality}, {"snapshot", snapshot_replaced}
};
unsigned selected = 0;
for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {