From 3c6ab56d3fdbc6464803cca61fe814f8b8fbbd6f Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Sat, 5 Jun 2021 17:54:32 +0545 Subject: [PATCH] allowed (temporarily) initially non-resolving supernode names (#701) --- include/n2n_define.h | 1 + src/edge.c | 13 ++++--- src/edge_utils.c | 10 +++--- src/n2n.c | 83 ++++++++++++++++++++++++-------------------- src/sn.c | 16 ++++----- src/sn_utils.c | 2 ++ 6 files changed, 70 insertions(+), 55 deletions(-) diff --git a/include/n2n_define.h b/include/n2n_define.h index 8b1a7c9..7f985c4 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -62,6 +62,7 @@ #define SORT_COMMUNITIES_INTERVAL 90 /* sec. until supernode sorts communities' hash list again */ +#define AF_INVALID -1 /* to mark a socket invalid by an invalid address family (do not use AF_UNSPEC, it could turn into auto-detect) */ #define N2N_RESOLVE_INTERVAL 300 /* seconds until edge and supernode try to resolve supernode names again */ #define N2N_RESOLVE_CHECK_INTERVAL 30 /* seconds until main loop checking in on changes from resolver thread */ diff --git a/src/edge.c b/src/edge.c index 776f976..d7efc81 100644 --- a/src/edge.c +++ b/src/edge.c @@ -51,6 +51,7 @@ int fetch_and_eventually_process_data (n2n_edge_t *eee, SOCKET sock, uint8_t *pktbuf, uint16_t *expected, uint16_t *position, time_t now); int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn_list); +int resolve_check (n2n_resolve_parameter_t *param, time_t now); /* ***************************************************** */ @@ -1023,6 +1024,11 @@ int main (int argc, char* argv[]) { traceEvent(TRACE_ERROR, "Failed in edge_init"); exit(1); } + + if(resolve_create_thread(&(eee->resolve_parameter), eee->conf.supernodes) == 0) { + traceEvent(TRACE_NORMAL, "Successfully created resolver thread"); + } + memcpy(&(eee->tuntap_priv_conf), &ec, sizeof(ec)); if((0 == strcmp("static", eee->tuntap_priv_conf.ip_mode)) || @@ -1168,8 +1174,9 @@ int main (int argc, char* argv[]) { } } } - seek_answer = 1; + + resolve_check(eee->resolve_parameter, now); } // allow a higher number of pings for first regular round of ping // to quicker get an inital 'supernode selection criterion overview' @@ -1227,10 +1234,6 @@ int main (int argc, char* argv[]) { traceEvent(TRACE_WARNING, "Running as root is discouraged, check out the -u/-g options"); #endif - if(resolve_create_thread(&(eee->resolve_parameter), eee->conf.supernodes) == 0) { - traceEvent(TRACE_NORMAL, "Successfully created resolver thread"); - } - #ifdef __linux__ signal(SIGPIPE, SIG_IGN); signal(SIGTERM, term_handler); diff --git a/src/edge_utils.c b/src/edge_utils.c index dd135c7..ff1ea1c 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -226,7 +226,7 @@ int supernode_connect(n2n_edge_t *eee) { eee->cb.sock_opened(eee); struct sockaddr_in sock; - sock.sin_family = AF_INET; + sock.sin_family = eee->curr_sn->sock.family; sock.sin_port = htons(eee->curr_sn->sock.port); memcpy(&(sock.sin_addr.s_addr), &(eee->curr_sn->sock.addr.v4), IPV4_SIZE); @@ -3502,10 +3502,10 @@ int edge_conf_add_supernode (n2n_edge_conf_t *conf, const char *ip_and_port) { sock = (n2n_sock_t*)calloc(1,sizeof(n2n_sock_t)); rv = supernode2sock(sock, ip_and_port); - if(rv != 0) { - traceEvent(TRACE_WARNING, "Invalid supernode address"); + if(rv < -2) { /* we accept resolver failure as it might resolve later */ + traceEvent(TRACE_WARNING, "Invalid supernode parameter."); free(sock); - return(1); + return 1; } skip_add = SN_ADD; @@ -3527,7 +3527,7 @@ int edge_conf_add_supernode (n2n_edge_conf_t *conf, const char *ip_and_port) { traceEvent(TRACE_NORMAL, "Adding supernode = %s", sn->ip_addr); conf->sn_num++; - return(0); + return 0; } /* ************************************** */ diff --git a/src/n2n.c b/src/n2n.c index d29493a..5ad3822 100644 --- a/src/n2n.c +++ b/src/n2n.c @@ -260,57 +260,56 @@ char * macaddr_str (macstr_t buf, int supernode2sock (n2n_sock_t *sn, const n2n_sn_name_t addrIn) { n2n_sn_name_t addr; - const char *supernode_host; + char *supernode_host; + char *supernode_port; int rv = 0; + int nameerr; + const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; + struct addrinfo * ainfo = NULL; + struct sockaddr_in * saddr; + + sn->family = AF_INVALID; memcpy(addr, addrIn, N2N_EDGE_SN_HOST_SIZE); - supernode_host = strtok(addr, ":"); if(supernode_host) { - char *supernode_port = strtok(NULL, ":"); - const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; - struct addrinfo * ainfo = NULL; - int nameerr; - + supernode_port = strtok(NULL, ":"); if(supernode_port) { sn->port = atoi(supernode_port); - } else { - traceEvent(TRACE_WARNING, "supernode2sock sees malformed supernode parameter (-l ) %s %s:%s", - addr, supernode_host, supernode_port); - } - - nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo); - - if(0 == nameerr) { - struct sockaddr_in * saddr; - - /* ainfo s the head of a linked list if non-NULL. */ - if(ainfo && (PF_INET == ainfo->ai_family)) { - /* It is definitely and IPv4 address -> sockaddr_in */ - saddr = (struct sockaddr_in *)ainfo->ai_addr; - - memcpy(sn->addr.v4, &(saddr->sin_addr.s_addr), IPV4_SIZE); - sn->family = AF_INET; + nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo); + if(0 == nameerr) { + /* ainfo s the head of a linked list if non-NULL. */ + if(ainfo && (PF_INET == ainfo->ai_family)) { + /* It is definitely and IPv4 address -> sockaddr_in */ + saddr = (struct sockaddr_in *)ainfo->ai_addr; + memcpy(sn->addr.v4, &(saddr->sin_addr.s_addr), IPV4_SIZE); + sn->family = AF_INET; + traceEvent(TRACE_INFO, "supernode2sock successfully resolves supernode IPv4 address for %s", supernode_host); + rv = 0; + } else { + /* Should only return IPv4 addresses due to aihints. */ + traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode IPv4 address for %s", supernode_host); + rv = -1; + } } else { - /* Should only return IPv4 addresses due to aihints. */ - traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode IPv4 address for %s", supernode_host); - rv = -1; + traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode host %s, %d: %s", supernode_host, nameerr, gai_strerror(nameerr)); + rv = -2; } - - freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ - ainfo = NULL; } else { - traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode host %s, %d: %s", supernode_host, nameerr, gai_strerror(nameerr)); - rv = -2; + traceEvent(TRACE_WARNING, "supernode2sock sees malformed supernode parameter (-l ) %s", addrIn); + rv = -3; } - } else { - traceEvent(TRACE_WARNING, "supernode2sock sees wrong supernode parameter (-l )"); - rv = -3; + traceEvent(TRACE_WARNING, "supernode2sock sees malformed supernode parameter (-l ) %s %s:%s", + addr, supernode_host, supernode_port); + rv = -4; } - return(rv); + freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ + ainfo = NULL; + + return rv; } @@ -319,9 +318,10 @@ void *resolve_thread (void *p) { #ifdef HAVE_PTHREAD n2n_resolve_parameter_t *param = (n2n_resolve_parameter_t*)p; n2n_resolve_ip_sock_t *entry, *tmp_entry; + int sleep_time = N2N_RESOLVE_INTERVAL / 10; /* initially shorter sleep */ while(1) { - sleep(N2N_RESOLVE_INTERVAL); + sleep(sleep_time); // lock access pthread_mutex_lock(¶m->access); @@ -339,6 +339,15 @@ void *resolve_thread (void *p) { // unlock access pthread_mutex_unlock(¶m->access); + + // determine next sleep duration (shorter if resolver errors occured) + sleep_time = N2N_RESOLVE_INTERVAL; + HASH_ITER(hh, param->list, entry, tmp_entry) { + if(entry->error_code) { + sleep_time = N2N_RESOLVE_INTERVAL / 10; + break; + } + } } #endif } diff --git a/src/sn.c b/src/sn.c index e904cb8..38aefab 100644 --- a/src/sn.c +++ b/src/sn.c @@ -398,25 +398,24 @@ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { length = strlen(_optarg); if(length >= N2N_EDGE_SN_HOST_SIZE) { traceEvent(TRACE_WARNING, "Size of -l argument too long: %zu. Maximum size is %d", length, N2N_EDGE_SN_HOST_SIZE); - break; + return -1; } if(!double_column) { - traceEvent(TRACE_WARNING, "Invalid -l format: ignored"); - return (-1); + traceEvent(TRACE_WARNING, "Invalid -l format: missing port"); + return -1; } socket = (n2n_sock_t *)calloc(1, sizeof(n2n_sock_t)); rv = supernode2sock(socket, _optarg); - if(rv != 0) { - traceEvent(TRACE_WARNING, "Invalid socket"); + if(rv < -2) { /* we accept resolver failure as it might resolve later */ + traceEvent(TRACE_WARNING, "Invalid supernode parameter."); free(socket); - break; + return -1; } if(sss->federation != NULL) { - skip_add = SN_ADD; anchor_sn = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), socket, null_mac, &skip_add); @@ -567,7 +566,8 @@ static int loadFromCLI (int argc, char * const argv[], n2n_sn_t *sss) { if(c == 255) { break; } - setOption(c, optarg, sss); + if(0 != setOption(c, optarg, sss)) + help(0); } return 0; diff --git a/src/sn_utils.c b/src/sn_utils.c index feadbf2..0d09819 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -1657,6 +1657,8 @@ static int process_udp (n2n_sn_t * sss, skip--; continue; } + if(peer->sock.family == AF_INVALID) + continue; /* do not add unresolved supernodes to payload */ if(memcmp(&(peer->sock), &(ack.sock), sizeof(n2n_sock_t)) == 0) continue; /* a supernode doesn't add itself to the payload */ if((now - peer->last_seen) >= LAST_SEEN_SN_NEW) continue; /* skip long-time-not-seen supernodes. * We need to allow for a little extra time because supernodes sometimes exceed