|
|
|
|
@ -679,7 +679,8 @@ void nat_detection_receive_ingress(struct NAT_DETECTION *detector, struct ETCP_S
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT ingress ignored without pending endpoint/valid tag length=%zu", length); return; |
|
|
|
|
} |
|
|
|
|
uint8_t expected[ROUTE_OBSERVE_TAG_SIZE]; route_ping_make_tag(expected, socket, state->group_id, state->round); |
|
|
|
|
uint8_t step = state->phase == NAT_PRE ? NAT_STEP_PRE : state->phase == NAT_POST ? NAT_STEP_POST : 0; |
|
|
|
|
uint8_t step = state->phase == NAT_PREPARE_C ? NAT_STEP_PREPARE : state->phase == NAT_PRE ? NAT_STEP_PRE : |
|
|
|
|
state->phase == NAT_POST ? NAT_STEP_POST : 0; |
|
|
|
|
if (!step || memcmp(tag, expected, sizeof(expected)) || tag[ROUTE_OBSERVE_TAG_SIZE] != step || |
|
|
|
|
read64(tag + ROUTE_OBSERVE_TAG_SIZE + 1) != state->token || |
|
|
|
|
sc_derive_node_id_from_pubkey(peer_key) != state->helper || memcmp(peer_key, state->helper_key, 32) || |
|
|
|
|
@ -689,7 +690,7 @@ void nat_detection_receive_ingress(struct NAT_DETECTION *detector, struct ETCP_S
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT ingress correlation/source mismatch socket=%s phase=%u round=%016llx source=%s", |
|
|
|
|
socket->name, state->phase, (unsigned long long)state->round, sockaddr_storage_to_str(source).str); return; |
|
|
|
|
} |
|
|
|
|
if (step == NAT_STEP_PRE) { |
|
|
|
|
if (step == NAT_STEP_PRE || step == NAT_STEP_PREPARE) { |
|
|
|
|
if (!state->pre_received) { state->filter_clean = !contacted(state, source); state->helper_address = *source; } |
|
|
|
|
state->pre_received = 1; |
|
|
|
|
} |
|
|
|
|
@ -756,7 +757,7 @@ static void helper_ping_cb(int success, uint16_t rtt, void *arg, uint64_t nonce,
|
|
|
|
|
if (probe->cancelled) return; |
|
|
|
|
probe->active = 0; probe->tcp = NULL; |
|
|
|
|
uint8_t step = probe->message.step; |
|
|
|
|
if (step == NAT_STEP_PREPARE || step == NAT_STEP_ALT) { |
|
|
|
|
if (step == NAT_STEP_ALT || (step == NAT_STEP_PREPARE && probe->alternate_fallback)) { |
|
|
|
|
struct ETCP_SOCKET *socket = find_socket(probe->detector, probe->io_socket, probe->io_generation); |
|
|
|
|
struct sockaddr_storage mapped; |
|
|
|
|
if (success && socket && !route_ping_observation(data, length, socket, probe->group_id, |
|
|
|
|
@ -791,6 +792,12 @@ static void helper_ping_cb(int success, uint16_t rtt, void *arg, uint64_t nonce,
|
|
|
|
|
helper_finish(probe, NAT_REASON_INVALID_OBSERVATION); return; |
|
|
|
|
} |
|
|
|
|
probe->message.received++; |
|
|
|
|
if (step == NAT_STEP_PREPARE) { helper_finish(probe, NAT_REASON_NONE); return; } |
|
|
|
|
} |
|
|
|
|
if (step == NAT_STEP_PREPARE && probe->message.sent >= NAT_PROBE_COUNT) { |
|
|
|
|
probe->alternate_fallback = 1; probe->message.sent = 0; |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT first ingress blocked; discover helper mapping through broker group=%016llx owner=%016llx", |
|
|
|
|
(unsigned long long)probe->group_id, (unsigned long long)read64(probe->message.owner)); |
|
|
|
|
} |
|
|
|
|
if (probe->message.sent >= NAT_PROBE_COUNT) { helper_finish(probe, NAT_REASON_NONE); return; } |
|
|
|
|
} |
|
|
|
|
@ -811,7 +818,7 @@ static int helper_send(struct nat_probe *probe) {
|
|
|
|
|
if (parameters) { topo_node_reality_config(&reality, parameters); camouflage = &reality; } |
|
|
|
|
result = etcp_send_tcp_ping(detector->instance, probe->owner_key, &target, timeout, |
|
|
|
|
helper_ping_cb, probe, &probe->tcp, camouflage); |
|
|
|
|
} else if (probe->message.step == NAT_STEP_PREPARE || probe->message.step == NAT_STEP_ALT) { |
|
|
|
|
} else if (probe->message.step == NAT_STEP_ALT || (probe->message.step == NAT_STEP_PREPARE && probe->alternate_fallback)) { |
|
|
|
|
struct ETCP_SOCKET *source = find_socket(detector, probe->source_socket, probe->source_generation); |
|
|
|
|
if (!source) { DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT helper source generation disappeared"); return -1; } |
|
|
|
|
struct ETCP_SOCKET *socket = helper_socket(detector, source, probe->message.step == NAT_STEP_ALT); |
|
|
|
|
@ -954,7 +961,8 @@ static void handle_result(struct nat_socket *state, const struct nat_wire *messa
|
|
|
|
|
struct sockaddr_storage primary; |
|
|
|
|
if (route_ping_addr_decode(message->primary, &primary) || primary.ss_family != state->local.ss_family || |
|
|
|
|
!public_address(state->detector, &primary)) { owner_finish(state, NAT_REASON_INVALID_OBSERVATION); return; } |
|
|
|
|
int same_ip = route_ping_addr_equal(&state->observer_address, &primary, 0), old_contact = contacted(state, &primary); |
|
|
|
|
int same_ip = route_ping_addr_equal(&state->observer_address, &primary, 0); |
|
|
|
|
int old_contact = state->pre_received ? !state->filter_clean : contacted(state, &primary); |
|
|
|
|
if (same_ip || (old_contact && !state->using_fallback)) { |
|
|
|
|
if (!same_ip && !state->fallback.group) state->fallback = (struct nat_pair){state->group_id, state->observer, state->helper}; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT try another pair socket=%s group=%016llx helper=%016llx endpoint=%s reason=%s", |
|
|
|
|
@ -963,6 +971,11 @@ static void handle_result(struct nat_socket *state, const struct nat_wire *messa
|
|
|
|
|
owner_finish(state, same_ip ? NAT_REASON_NO_HELPER : NAT_REASON_CONTACT_HISTORY); return; |
|
|
|
|
} |
|
|
|
|
state->helper_address = primary; state->filter_clean = !old_contact; |
|
|
|
|
if (state->pre_received) { |
|
|
|
|
state->phase = NAT_OBSERVE_C; |
|
|
|
|
if (owner_observe(state)) owner_finish(state, NAT_REASON_SEND_ERROR); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (owner_run(state, NAT_STEP_PRE)) owner_finish(state, NAT_REASON_CONTROL_LOST); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|