|
|
|
|
@ -13,6 +13,7 @@
|
|
|
|
|
#include "topo_group.h" |
|
|
|
|
#include "route_connectivity.h" |
|
|
|
|
#include "route_ping.h" |
|
|
|
|
#include "nat_detection.h" |
|
|
|
|
#ifdef UTUN_HAVE_STANDBY |
|
|
|
|
#include "standby.h" |
|
|
|
|
#endif |
|
|
|
|
@ -78,22 +79,24 @@ static void cm_cand_tcp_ping_cb(int s, uint16_t r, void* arg, uint64_t n, const
|
|
|
|
|
|
|
|
|
|
static void cm_bg_ping_to_node(struct CONN_MGR* mgr, struct TOPO_NODE* ni) { |
|
|
|
|
for (const struct TOPO_ADDR4* a = ni->v4_addrs; a; a = a->next) { |
|
|
|
|
if (!(a->protocol & TOPO_PROTO_UDP)) continue; |
|
|
|
|
if (a->type != TOPO_ADDR_NAT && a->type != TOPO_ADDR_INTERFACE) continue; |
|
|
|
|
struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); sin.sin_family=AF_INET; |
|
|
|
|
memcpy(&sin.sin_addr.s_addr,a->addr,4); sin.sin_port=htons(a->port); |
|
|
|
|
struct sockaddr_storage sa; memcpy(&sa,&sin,sizeof(sin)); |
|
|
|
|
struct ETCP_SOCKET* s = mgr->instance->etcp_sockets; |
|
|
|
|
while (s) { if (s->local_addr.ss_family == AF_INET) break; s = s->next; } |
|
|
|
|
while (s) { if (!s->is_tcp && !s->probe_only && s->local_addr.ss_family == AF_INET) break; s = s->next; } |
|
|
|
|
if (!s) break; |
|
|
|
|
etcp_send_ping_to_socket(mgr->instance, s, ni->public_key, &sa, CONN_PROBE_TIMEOUT_MS, cm_bg_ping_noop_cb, NULL, NULL, 0, 0); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
for (const struct TOPO_ADDR6* a6 = ni->v6_addrs; a6; a6 = a6->next) { |
|
|
|
|
if (!(a6->protocol & TOPO_PROTO_UDP)) continue; |
|
|
|
|
if (a6->type != TOPO_ADDR_NAT && a6->type != TOPO_ADDR_INTERFACE) continue; |
|
|
|
|
struct sockaddr_in6 sin6; memset(&sin6,0,sizeof(sin6)); sin6.sin6_family=AF_INET6; |
|
|
|
|
memcpy(&sin6.sin6_addr,a6->addr,16); sin6.sin6_port=htons(a6->port); |
|
|
|
|
struct ETCP_SOCKET* s = mgr->instance->etcp_sockets; |
|
|
|
|
while (s) { if (s->local_addr.ss_family == AF_INET6) break; s = s->next; } |
|
|
|
|
while (s) { if (!s->is_tcp && !s->probe_only && s->local_addr.ss_family == AF_INET6) break; s = s->next; } |
|
|
|
|
if (!s) break; |
|
|
|
|
if (cm_classify_v6_addr(a6->addr) == CM_V6_LL) sin6.sin6_scope_id = s->netif_index; |
|
|
|
|
struct sockaddr_storage sa; memcpy(&sa,&sin6,sizeof(sin6)); |
|
|
|
|
@ -108,6 +111,12 @@ static void cm_bg_ping_to_node(struct CONN_MGR* mgr, struct TOPO_NODE* ni) {
|
|
|
|
|
* и INDIRECT-фаза не может выбрать посредника. */ |
|
|
|
|
void cm_bg_ping_timer_cb(void* arg) { |
|
|
|
|
struct CONN_MGR* mgr = (struct CONN_MGR*)arg; |
|
|
|
|
uint64_t nat_delay = nat_detection_probe_delay(mgr->instance->nat_det); |
|
|
|
|
if (nat_delay) { |
|
|
|
|
mgr->bg_ping_timer = uasync_set_timeout(mgr->instance->ua, nat_delay, mgr, cm_bg_ping_timer_cb, "cm_bg_nat_defer"); |
|
|
|
|
if (!mgr->bg_ping_timer) DEBUG_ERROR(DEBUG_CATEGORY_BGP, "background ping NAT defer scheduling failed"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
#ifdef UTUN_HAVE_STANDBY |
|
|
|
|
if (standby_get_sleep_tb() > 0) { |
|
|
|
|
mgr->bg_ping_wait = standby_wait(mgr, cm_bg_ping_timer_cb); |
|
|
|
|
@ -156,6 +165,12 @@ static int cm_has_active_conn(struct TOPO_GROUP* g, uint64_t nid) {
|
|
|
|
|
* Вызывается раз в ~2с, самоперезапускается. */ |
|
|
|
|
void cm_candidate_ping_timer_cb(void* arg) { |
|
|
|
|
struct CONN_MGR* mgr = (struct CONN_MGR*)arg; uint64_t now = get_time_tb(); |
|
|
|
|
uint64_t nat_delay = nat_detection_probe_delay(mgr->instance->nat_det); |
|
|
|
|
if (nat_delay) { |
|
|
|
|
mgr->candidate_ping_timer = uasync_set_timeout(mgr->instance->ua, nat_delay, mgr, cm_candidate_ping_timer_cb, "cm_candidate_nat_defer"); |
|
|
|
|
if (!mgr->candidate_ping_timer) DEBUG_ERROR(DEBUG_CATEGORY_BGP, "candidate ping NAT defer scheduling failed"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
#ifdef UTUN_HAVE_STANDBY |
|
|
|
|
if (standby_get_sleep_tb() > 0) { |
|
|
|
|
mgr->candidate_ping_wait = standby_wait(mgr, cm_candidate_ping_timer_cb); |
|
|
|
|
|