|
|
|
|
@ -14,7 +14,7 @@ static struct {
|
|
|
|
|
struct UTUN_INSTANCE *owner, *observer, *helper, *alias; |
|
|
|
|
struct ETCP_SOCKET *socket, *alias_source; |
|
|
|
|
enum fault_mode mode; |
|
|
|
|
unsigned dropped, altered, direct_received, observations; |
|
|
|
|
unsigned dropped, altered, direct_received, observations, preserved; |
|
|
|
|
int contacted, injected; |
|
|
|
|
socket_t delayed_fd; |
|
|
|
|
uint8_t delayed[1600]; |
|
|
|
|
@ -160,6 +160,9 @@ void __wrap_nat_detection_record_observation(struct NAT_DETECTION *detector, str
|
|
|
|
|
/* Подлинная проба приходит с локального IP, несмотря на пригодный предварительный адрес помощника. */ |
|
|
|
|
void __wrap_nat_detection_receive_ingress(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_KNOWN_ALIAS && detector == fault.owner->nat_det && |
|
|
|
|
!memcmp(key, fault.alias->my_keys.public_key, 32) && socket->address_profile.inbound == ADDRESS_IN_OPEN) |
|
|
|
|
fault.preserved++; |
|
|
|
|
if (fault.fixture && fault.mode == FAULT_LOCAL_INGRESS && detector == fault.owner->nat_det && |
|
|
|
|
!memcmp(key, fault.alias->my_keys.public_key, 32)) { |
|
|
|
|
struct nat_check_status before, after; |
|
|
|
|
@ -275,16 +278,16 @@ static void run_alias(const char *alias_ip, enum fault_mode mode) {
|
|
|
|
|
do { assert(sc_generate_keypair(&next) == SC_OK); } |
|
|
|
|
while (sc_derive_node_id_from_pubkey(next.public_key) <= alias->node_id); |
|
|
|
|
struct UTUN_INSTANCE *fresh = nat_fixture_node(&fixture, "127.0.0.6", &next, NULL); |
|
|
|
|
nat_detection_set_automatic(fresh->nat_det, 0); nat_fixture_connect(&fixture, observer, "udp", fresh); |
|
|
|
|
nat_detection_set_automatic(fresh->nat_det, 0); |
|
|
|
|
fault.helper = fresh; rounds = status.rounds; |
|
|
|
|
assert(!nat_detection_request_check_socket(owner->nat_det, socket, observer->node_id)); |
|
|
|
|
int preserved_seen = 0; end = get_time_tb() + 400000; |
|
|
|
|
/* Резерв нового измерения включён до появления нового IP в топологии. */ |
|
|
|
|
nat_fixture_connect(&fixture, observer, "udp", fresh); |
|
|
|
|
end = get_time_tb() + 400000; |
|
|
|
|
do { |
|
|
|
|
test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); |
|
|
|
|
if (status.helper == alias->node_id && status.reason == NAT_REASON_CONTACT_HISTORY && status.cycling && |
|
|
|
|
socket->address_profile.inbound == ADDRESS_IN_OPEN) preserved_seen = 1; |
|
|
|
|
} while (get_time_tb() < end && (status.rounds == rounds || status.phase || status.cycling)); |
|
|
|
|
assert(preserved_seen && !status.phase && !status.cycling && status.helper == fresh->node_id); |
|
|
|
|
assert(fault.preserved && !status.phase && !status.cycling && status.helper == fresh->node_id && !status.reason); |
|
|
|
|
assert(socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && socket->address_profile.inbound == ADDRESS_IN_OPEN); |
|
|
|
|
} |
|
|
|
|
fault.fixture = NULL; nat_fixture_cleanup(&fixture); |
|
|
|
|
@ -402,6 +405,9 @@ static void run_budget_resume(void) {
|
|
|
|
|
nat_fixture_connect(&fixture, owner, "udp", observer); |
|
|
|
|
memset(&fault, 0, sizeof(fault)); fault.fixture = &fixture; fault.owner = owner; fault.observer = observer; |
|
|
|
|
fault.socket = test_etcp_bound_socket(owner, "udp"); fault.mode = FAULT_BUDGET; |
|
|
|
|
for (unsigned i = 2; i < fixture.node_count; i++) |
|
|
|
|
assert(!etcp_send_ping_to_socket(owner, fault.socket, fixture.nodes[i]->my_keys.public_key, |
|
|
|
|
&test_etcp_bound_socket(fixture.nodes[i], "udp")->local_addr, 500, ignored_ping, NULL, NULL, 0, 0)); |
|
|
|
|
assert(!nat_detection_request_check_socket(owner->nat_det, fault.socket, observer->node_id)); |
|
|
|
|
struct nat_check_status status = {0}; uint64_t end = get_time_tb() + 500000; |
|
|
|
|
do { test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status)); } |
|
|
|
|
@ -421,10 +427,13 @@ static void run_budget_resume(void) {
|
|
|
|
|
assert(fault.socket->address_profile.inbound == ADDRESS_IN_UNKNOWN); |
|
|
|
|
fault.mode = FAULT_NONE; fault.delayed_length = 0; end = get_time_tb() + 700000; |
|
|
|
|
do { test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status)); } |
|
|
|
|
while (get_time_tb() < end && status.round == paused_round); |
|
|
|
|
assert(status.round != paused_round && status.helper == paused_helper && status.helper_reselections == completed_pairs); |
|
|
|
|
do { test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status)); } |
|
|
|
|
while (get_time_tb() < end && status.cycling); |
|
|
|
|
assert(!status.phase && !status.cycling && status.round != paused_round && status.helper == paused_helper); |
|
|
|
|
assert(status.helper_reselections == completed_pairs && fault.socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && |
|
|
|
|
fault.socket->address_profile.inbound == ADDRESS_IN_OPEN); |
|
|
|
|
assert(status.helper_reselections == completed_pairs + 1 && fault.socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && |
|
|
|
|
fault.socket->address_profile.inbound == ADDRESS_IN_UNKNOWN && status.reason == NAT_REASON_CONTACT_HISTORY); |
|
|
|
|
fault.fixture = NULL; nat_fixture_cleanup(&fixture); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS NAT budget pause retains mapping, rejects late ingress and retries the unfinished pair"); |
|
|
|
|
} |
|
|
|
|
|