From d0ee0341c5691ecfe9b64d423f00cb7ef9446981 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 23 Oct 2026 22:36:39 +0200 Subject: [PATCH] Verify cancelled link constructors and guard UDP handshake callbacks --- src/transport_layer/etcp_connections.c | 3 ++- tests/test_etcp_lifecycle.c | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index e46aff55..bac5e112 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -349,10 +349,11 @@ void etcp_link_restart_init_timer(struct ETCP_LINK* link) { void etcp_link_enter_init(struct ETCP_LINK* link) { DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); if (!link) return; + struct ETCP_CONN *conn = link->etcp; int old_state = link->link_state; link->link_state = LINK_STATE_HANDSHAKE; // handshake etcp_fire_link_status_cbk(link, old_state, link->link_status); - if (!etcp_link_rx_alive(link->etcp, link)) return; + if (!etcp_link_rx_alive(conn, link)) return; if (link->is_server != 0) return; int reset = (link->etcp->got_initial_pkt == 0); etcp_link_send_init(link, reset, 0); diff --git a/tests/test_etcp_lifecycle.c b/tests/test_etcp_lifecycle.c index 7cd3865d..2de88505 100644 --- a/tests/test_etcp_lifecycle.c +++ b/tests/test_etcp_lifecycle.c @@ -172,6 +172,27 @@ static void constructor_close_cases(struct UTUN_INSTANCE *inst) { } struct link_close_case { struct ETCP_LINK *neighbor; unsigned events, nested; }; +static void cancel_created_link(struct ETCP_CONN *conn, struct ETCP_LINK *link, int old_state, int old_status, void *arg) { + (void)old_status; + unsigned action = (unsigned)(uintptr_t)arg; + if (old_state != -1) return; + if (action == 1) etcp_link_close(link); + else etcp_connection_close(conn); +} +static void link_constructor_close_cases(struct UTUN_INSTANCE *inst) { + for (unsigned action = 1; action <= 2; action++) { + struct ETCP_CONN *conn = etcp_connection_create(inst, "cancel link"); CHECK(conn); + CHECK(etcp_conn_ref_take(conn) == 0); + etcp_add_link_status_cbk(inst, cancel_created_link, (void*)(uintptr_t)action); + CHECK(etcp_link_new(conn, NULL, NULL, 0) == NULL); + CHECK(!conn->links); + etcp_remove_link_status_cbk(inst, cancel_created_link, (void*)(uintptr_t)action); + etcp_connection_close(conn); etcp_conn_ref_free(conn); + uasync_drain_immediate(inst->ua); uasync_poll(inst->ua, 0); + CHECK(!inst->connections->count); + printf("PASS link creation cancelled by closing %s\n", action == 1 ? "link" : "connection"); + } +} static void close_neighbor(struct ETCP_CONN *conn, struct ETCP_LINK *link, int old_state, int old_status, void *arg) { (void)conn; (void)old_state; (void)old_status; struct link_close_case *test = arg; @@ -231,7 +252,8 @@ int main(void) { uasync_poll(inst.ua,0); CHECK(inst.connections->count == 0); printf("PASS lifecycle scenario %d\n",scenario+1); } - ncd_cases(&inst); ncd_late_up_case(&inst); recovery_cases(&inst); neighbor_close_case(&inst); constructor_close_cases(&inst); + ncd_cases(&inst); ncd_late_up_case(&inst); recovery_cases(&inst); neighbor_close_case(&inst); + constructor_close_cases(&inst); link_constructor_close_cases(&inst); queue_free(inst.connections); uasync_poll(inst.ua,0); CHECK(inst.ua->timer_alloc_count == inst.ua->timer_free_count); uasync_destroy(inst.ua,0); CHECK(u_get_allocated_count() == baseline);