From 906f24758858ab762b5a317b9c8ff784fc3b95dc Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 17 Oct 2026 18:25:53 +0200 Subject: [PATCH] tests: verify tentative EIM with known helper and unknown inbound access --- tests/test_android_replies.c | 5 +++++ tests/test_nat_detection_faults.c | 27 +++++++++++++++++++++++++-- tests/test_sock_match.c | 2 ++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/test_android_replies.c b/tests/test_android_replies.c index f017c7cd..149d5ff2 100644 --- a/tests/test_android_replies.c +++ b/tests/test_android_replies.c @@ -79,6 +79,11 @@ static int check_addresses(const char *channel) { REQUIRE(!topo_node_sqlite_addrs_put(instance->topo_sqlite_db, instance->node_id, &node)); json = utun_bridge_get_member_detail_json(channel, instance->node_id); REQUIRE(json && !extract(json, "$.adr[0].at", value, sizeof(value)) && !strcmp(value, "4")); /* NAT, тип неизвестен */ + u_free(json); + meta4.address_profile.mapping = ADDRESS_MAP_EIM; + REQUIRE(!topo_node_sqlite_addrs_put(instance->topo_sqlite_db, instance->node_id, &node)); + json = utun_bridge_get_member_detail_json(channel, instance->node_id); + REQUIRE(json && !extract(json, "$.adr[0].at", value, sizeof(value)) && !strcmp(value, "6")); /* EIM? */ u_free(json); return 0; } diff --git a/tests/test_nat_detection_faults.c b/tests/test_nat_detection_faults.c index e35bedf2..96d1d920 100644 --- a/tests/test_nat_detection_faults.c +++ b/tests/test_nat_detection_faults.c @@ -6,7 +6,7 @@ enum fault_mode { FAULT_NONE, FAULT_NO_PONG, FAULT_FILTERED, FAULT_LATE_PRE, FAULT_CONTACT, FAULT_DEPENDENT, FAULT_UNSTABLE, FAULT_NO_REPORT, FAULT_INGRESS_BLOCKED, FAULT_NO_ANCHOR, - FAULT_LOCAL_INGRESS, FAULT_LOCAL_OBSERVER, FAULT_LOCAL_HELPER_MAPPING, FAULT_CONTROL_STALL }; + FAULT_LOCAL_INGRESS, FAULT_LOCAL_OBSERVER, FAULT_LOCAL_HELPER_MAPPING, FAULT_CONTROL_STALL, FAULT_EIM_UNVERIFIED }; static struct { struct nat_fixture *fixture; @@ -79,7 +79,8 @@ ssize_t __wrap_socket_sendto(socket_t fd, const void *packet, size_t length, con fault.altered++; return __real_socket_sendto(fault.alias_source->fd, packet, length, target, target_length); } - if ((fault.mode == FAULT_NO_PONG || fault.mode == FAULT_NO_ANCHOR) && to_owner && plain[3] == ETCP_PONG) { + if ((fault.mode == FAULT_NO_PONG || fault.mode == FAULT_NO_ANCHOR || fault.mode == FAULT_EIM_UNVERIFIED) && + to_owner && plain[3] == ETCP_PONG) { fault.dropped++; return length; } if (source == fault.socket && plain[3] == ETCP_PING && (plain[4] & ETCP_PING_FLAG_OBSERVE) && @@ -116,6 +117,14 @@ ssize_t __wrap_socket_sendto(socket_t fd, const void *packet, size_t length, con void __wrap_nat_detection_record_observation(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket, const uint8_t *key, const struct sockaddr_storage *source, const uint8_t *tag, size_t length) { + if (fault.fixture && fault.mode == FAULT_EIM_UNVERIFIED && length == ROUTE_OBSERVE_TAG_SIZE + 9 && + !memcmp(key, fault.owner->my_keys.public_key, 32)) { + /* Два направления видят один переведённый адрес. История помощника уже загрязнена настоящим PING. */ + struct sockaddr_storage mapped = *source; + assert(inet_pton(AF_INET, "127.0.0.9", &((struct sockaddr_in *)&mapped)->sin_addr) == 1); + fault.observations++; + __real_nat_detection_record_observation(detector, socket, key, &mapped, tag, length); return; + } if (fault.fixture && socket->instance == fault.observer && length == ROUTE_OBSERVE_TAG_SIZE + 9 && ((fault.mode == FAULT_LOCAL_OBSERVER && !memcmp(key, fault.owner->my_keys.public_key, 32)) || (fault.mode == FAULT_LOCAL_HELPER_MAPPING && !memcmp(key, fault.alias->my_keys.public_key, 32)))) { @@ -178,6 +187,9 @@ static void run_case(enum fault_mode mode, uint8_t mapping, uint8_t inbound) { nat_detection_set_automatic(owner->nat_det, 0); memset(&fault, 0, sizeof(fault)); fault.fixture = &fixture; fault.owner = owner; fault.observer = observer; fault.helper = helper; fault.socket = test_etcp_bound_socket(owner, "udp"); fault.mode = mode; + if (mode == FAULT_EIM_UNVERIFIED) + assert(!etcp_send_ping_to_socket(owner, fault.socket, helper->my_keys.public_key, + &test_etcp_bound_socket(helper, "udp")->local_addr, 500, ignored_ping, NULL, NULL, 0, 0)); struct nat_check_status status = {0}; nat_detection_get_status(owner->nat_det, fault.socket, &status); uint32_t rounds = status.rounds; assert(!nat_detection_request_check_socket(owner->nat_det, fault.socket, observer->node_id)); @@ -194,6 +206,16 @@ static void run_case(enum fault_mode mode, uint8_t mapping, uint8_t inbound) { if (mode == FAULT_DEPENDENT || mode == FAULT_UNSTABLE) assert(fault.altered); if (mode == FAULT_LOCAL_OBSERVER) assert(fault.injected && status.helper_reselections && !fault.observations); if (mode == FAULT_CONTROL_STALL) assert(fault.dropped && fault.observations >= 2 && status.rounds == rounds + 1); + if (mode == FAULT_EIM_UNVERIFIED) { + assert(fault.observations >= 4 && !fault.direct_received && fault.socket->nat_addr.ss_family == AF_INET); + sqlite3_stmt *statement = NULL; + assert(sqlite3_prepare_v2(owner->topo_sqlite_db, + "SELECT addr_type FROM node_addresses WHERE node_id=? AND socket_id=? AND address_kind=?", -1, &statement, NULL) == SQLITE_OK); + sqlite3_bind_int64(statement, 1, (sqlite3_int64)owner->node_id); + sqlite3_bind_int(statement, 2, fault.socket->sock_id); sqlite3_bind_int(statement, 3, TOPO_ADDR_NAT); + assert(sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_int(statement, 0) == ADDR_TYPE_NAT_EIM_UNVERIFIED); + sqlite3_finalize(statement); + } fault.fixture = NULL; nat_fixture_cleanup(&fixture); DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS NAT fault mode=%d", mode); } @@ -346,6 +368,7 @@ int main(void) { run_case(FAULT_NO_ANCHOR, ADDRESS_MAP_UNCHANGED, ADDRESS_IN_UNKNOWN); run_case(FAULT_LOCAL_OBSERVER, ADDRESS_MAP_UNKNOWN, ADDRESS_IN_UNKNOWN); run_case(FAULT_CONTROL_STALL, ADDRESS_MAP_UNCHANGED, ADDRESS_IN_UNKNOWN); + run_case(FAULT_EIM_UNVERIFIED, ADDRESS_MAP_EIM, ADDRESS_IN_UNKNOWN); run_alias("127.0.0.3", FAULT_NONE); run_alias("127.0.0.2", FAULT_NONE); run_alias("127.0.0.9", FAULT_LOCAL_INGRESS); run_alias("127.0.0.9", FAULT_LOCAL_HELPER_MAPPING); run_lan_observation(); run_unknown_address(); run_endpoint_retry(); diff --git a/tests/test_sock_match.c b/tests/test_sock_match.c index f9567ef6..0f77ef2c 100644 --- a/tests/test_sock_match.c +++ b/tests/test_sock_match.c @@ -17,6 +17,8 @@ int main(void) { assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &observed, 1) == SOCK_TC_PROBE); struct address_profile open = {.mapping = ADDRESS_MAP_EIM, .inbound = ADDRESS_IN_OPEN, .source = ADDRESS_SOURCE_ETCP}; struct address_profile contact = open; contact.inbound = ADDRESS_IN_CONTACT; + struct address_profile unverified = open; unverified.inbound = ADDRESS_IN_UNKNOWN; + assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &unverified, 1) == SOCK_TC_PROBE); struct address_profile dependent = open; dependent.mapping = ADDRESS_MAP_DEPENDENT; dependent.inbound = ADDRESS_IN_UNKNOWN; assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_PUBLIC, &unknown, 1) == SOCK_TC_PROBE);