tests: cover tentative STUN mapping, expiry and native priority
This commit is contained in:
1 parent
417b848b50
commit
f5d923a671
2 files changed
+53
-9
No files matched your search
@@ -600,6 +600,13 @@ static void select_profile(struct nat_socket *state) {
|
||||
(selected_address.ss_family && !route_ping_addr_equal(&selected_address, &state->socket->nat_addr, 1));
|
||||
if (selected.mapping == current->mapping && selected.inbound == current->inbound &&
|
||||
selected.source == current->source && !address_changed) return;
|
||||
if (selected.source == ADDRESS_SOURCE_STUN)
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT tentative EIM? socket=%s STUN_local=%s netif=%u evidence=%016llx"
|
||||
" mapping=%s filtering=%s age_tb=%llu working_address=%s",
|
||||
state->socket->name, sockaddr_storage_to_str(&stun.local).str, stun.key.netif_index,
|
||||
(unsigned long long)stun.evidence_id, stun_nat_mapping_name(stun.mapping),
|
||||
stun_nat_filtering_name(stun.filtering), (unsigned long long)(now - stun.measured_at_tb),
|
||||
sockaddr_storage_to_str(&selected_address).str);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT selected socket=%s generation=%016llx source=%s previous=%s mapping=%s inbound=%s"
|
||||
" address_changed=%d reason=%s",
|
||||
state->socket->name, (unsigned long long)state->socket->generation, address_profile_source_name(selected.source),
|
||||
|
||||
+46
-9
@@ -371,10 +371,10 @@ static void wait_source(struct nat_fixture* nf, struct ETCP_SOCKET* socket, uint
|
||||
abort();
|
||||
}
|
||||
|
||||
/* STUN другого порта не назначает профиль рабочему endpoint, даже без ETCP-наблюдателей. */
|
||||
static void test_fallback(void) {
|
||||
/* Оценка STUN относится к IP/netif, сохраняет рабочий порт и уступает измерению ETCP. */
|
||||
static void test_fallback(int rfc) {
|
||||
struct nat_fixture nf; nat_fixture_init(&nf);
|
||||
struct fixture server = {.ua = nf.ua, .rfc = 1, .mapping = STUN_MAP_EIM,
|
||||
struct fixture server = {.ua = nf.ua, .rfc = rfc, .mapping = STUN_MAP_EIM,
|
||||
.filtering = STUN_FILTER_EIF, .multiple_clients = 1}; fixture_init(&server);
|
||||
char config[512];
|
||||
snprintf(config, sizeof(config), "[stun]\nenabled=yes\nserver=127.0.0.1:%u\nserver=127.0.0.3:%u\n"
|
||||
@@ -387,8 +387,10 @@ static void test_fallback(void) {
|
||||
uint64_t end = get_time_tb() + 3000000;
|
||||
do { test_clock_poll(nf.ua, 10000); assert(!stun_nat_get_socket_result(owner, socket, &diagnostic)); }
|
||||
while (get_time_tb() < end && diagnostic.status == STUN_NAT_PENDING);
|
||||
assert(diagnostic.mapping == STUN_MAP_EIM && diagnostic.filtering == STUN_FILTER_EIF);
|
||||
assert(socket->address_profile.source == ADDRESS_SOURCE_NONE && !socket->address_profile.mapping && !socket->address_profile.inbound);
|
||||
assert(diagnostic.mapping == (rfc ? STUN_MAP_EIM : STUN_MAP_MATCH));
|
||||
assert(diagnostic.filtering == (rfc ? STUN_FILTER_EIF : STUN_FILTER_UNKNOWN));
|
||||
wait_source(&nf, socket, ADDRESS_SOURCE_STUN); wait_source(&nf, duplicate, ADDRESS_SOURCE_STUN);
|
||||
assert(socket->address_profile.mapping == ADDRESS_MAP_EIM && socket->address_profile.inbound == ADDRESS_IN_UNKNOWN);
|
||||
assert(!memcmp(&socket->address_profile, &duplicate->address_profile, sizeof(socket->address_profile)));
|
||||
assert(!socket->nat_addr.ss_family && !duplicate->nat_addr.ss_family);
|
||||
struct nat_check_status status;
|
||||
@@ -400,12 +402,47 @@ static void test_fallback(void) {
|
||||
assert(snapshot && !topo_node_verify(snapshot));
|
||||
for (const struct TOPO_ADDR4* address = snapshot->v4_addrs; address; address = address->next)
|
||||
assert(address->type != TOPO_ADDR_NAT); /* тестовый внешний порт не опубликован */
|
||||
struct ETCP_SOCKET other = *socket;
|
||||
other.netif_index++;
|
||||
assert(stun_nat_get_socket_result(owner, &other, &diagnostic) < 0);
|
||||
other = *socket;
|
||||
((struct sockaddr_in*)&other.local_addr)->sin_addr.s_addr = htonl(0x7f000009u);
|
||||
assert(stun_nat_get_socket_result(owner, &other, &diagnostic) < 0);
|
||||
struct ETCP_CONN peer = {.peer_node_id = 1};
|
||||
struct ETCP_LINK link = {.conn = socket, .etcp = &peer};
|
||||
struct sockaddr_storage observed = {0};
|
||||
struct sockaddr_in* external = (struct sockaddr_in*)&observed;
|
||||
external->sin_family = AF_INET; external->sin_addr.s_addr = htonl(0xcb007107u); external->sin_port = htons(45678);
|
||||
nat_detection_observed_by_peer(owner->nat_det, &link, &observed);
|
||||
assert(socket->address_profile.source == ADDRESS_SOURCE_STUN);
|
||||
assert(route_ping_addr_equal(&socket->nat_addr, &observed, 1));
|
||||
test_clock_run_for(nf.ua, 10001);
|
||||
int found = 0;
|
||||
for (const struct TOPO_ADDR4* address = snapshot->v4_addrs; address; address = address->next) {
|
||||
if (address->type != TOPO_ADDR_NAT) continue;
|
||||
assert(address->port == 45678 && !memcmp(address->addr, &external->sin_addr, 4)); found++;
|
||||
}
|
||||
assert(found == 1);
|
||||
/* Противоречащий внешний IP исключает STUN-оценку, даже при том же локальном пути. */
|
||||
external->sin_addr.s_addr = htonl(0xcb007108u);
|
||||
nat_detection_observed_by_peer(owner->nat_det, &link, &observed);
|
||||
assert(socket->address_profile.source == ADDRESS_SOURCE_ETCP && socket->address_profile.mapping == ADDRESS_MAP_UNKNOWN);
|
||||
external->sin_addr.s_addr = htonl(0xcb007107u);
|
||||
nat_detection_observed_by_peer(owner->nat_det, &link, &observed);
|
||||
assert(socket->address_profile.source == ADDRESS_SOURCE_STUN);
|
||||
/* Неудачный refresh не омолаживает кэш: EIM? исчезает после TTL. */
|
||||
server.drop_primary = 1;
|
||||
test_clock_run_for(nf.ua, STUN_NAT_TTL_TB + 30000);
|
||||
assert(socket->address_profile.source == ADDRESS_SOURCE_ETCP && socket->address_profile.mapping == ADDRESS_MAP_UNKNOWN);
|
||||
assert(route_ping_addr_equal(&socket->nat_addr, &observed, 1));
|
||||
server.drop_primary = 0; stun_nat_recheck(owner);
|
||||
wait_source(&nf, socket, ADDRESS_SOURCE_STUN);
|
||||
struct UTUN_INSTANCE* observer = nat_fixture_node(&nf, "127.0.0.5", NULL, NULL);
|
||||
nat_fixture_connect(&nf, owner, "udp", observer); nat_detection_request_check_all(owner->nat_det);
|
||||
end = get_time_tb() + 300000;
|
||||
do { test_clock_poll(nf.ua, 10000); nat_detection_get_status(owner->nat_det, socket, &status); }
|
||||
while (get_time_tb() < end && status.reason != NAT_REASON_NO_HELPER);
|
||||
assert(status.reason == NAT_REASON_NO_HELPER && socket->address_profile.source == ADDRESS_SOURCE_NONE);
|
||||
assert(status.reason == NAT_REASON_NO_HELPER && socket->address_profile.source == ADDRESS_SOURCE_STUN);
|
||||
struct UTUN_INSTANCE* helper = nat_fixture_node(&nf, "127.0.0.6", NULL, NULL);
|
||||
nat_fixture_connect(&nf, observer, "udp", helper); nat_detection_request_check_all(owner->nat_det);
|
||||
wait_source(&nf, socket, ADDRESS_SOURCE_ETCP); wait_source(&nf, duplicate, ADDRESS_SOURCE_ETCP);
|
||||
@@ -418,7 +455,7 @@ static void test_fallback(void) {
|
||||
end = get_time_tb() + 3000000;
|
||||
do { test_clock_poll(nf.ua, 10000); assert(!stun_nat_get_socket_result(owner, socket, &next)); }
|
||||
while (get_time_tb() < end && next.status == STUN_NAT_PENDING);
|
||||
assert(next.mapping == STUN_MAP_EIM && next.evidence_id != prior.evidence_id);
|
||||
assert(next.mapping == (rfc ? STUN_MAP_EIM : STUN_MAP_MATCH) && next.evidence_id != prior.evidence_id);
|
||||
assert(!memcmp(&socket->address_profile, &measured, sizeof(measured)));
|
||||
nat_detection_request_check_all(owner->nat_det); end = get_time_tb() + 300000;
|
||||
do { test_clock_poll(nf.ua, 10000); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); }
|
||||
@@ -433,7 +470,7 @@ static void test_fallback(void) {
|
||||
assert(!uasync_remove_socket_t(nf.ua, server.endpoints[i].fd)); socket_close_wrapper(server.endpoints[i].fd);
|
||||
}
|
||||
socket_close_wrapper(server.source.fd); nat_fixture_cleanup(&nf);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS STUN isolation: diagnostics never replace the measured working endpoint");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS STUN EIM? RFC5780=%d: IP/netif, observed port, expiry and native priority", rfc);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -512,7 +549,7 @@ int main(void) {
|
||||
result = wait_result(&changed);
|
||||
assert(result.mapping == STUN_MAP_MATCH);
|
||||
fixture_destroy(&changed);
|
||||
test_fallback();
|
||||
test_fallback(0); test_fallback(1);
|
||||
test_clock_finish();
|
||||
puts("PASS STUN independent sockets, RFC5780, fallback, lifecycle and ETCP isolation");
|
||||
return 0;
|
||||
|
||||
Reference in new issue
Block a user