From b3bf36f8671ae0dc32f9fac717b567cebecb32c3 Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Mon, 13 Sep 2021 11:33:27 +0545 Subject: [PATCH] separated 'detect_local_ip_address()' function (#781) --- include/n2n.h | 2 ++ src/edge_utils.c | 32 +++++++++++--------------------- src/n2n.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/include/n2n.h b/include/n2n.h index 22bf343..90751c2 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -223,6 +223,8 @@ char * ip_subnet_to_str (dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr); SOCKET open_socket (int local_port, in_addr_t address, int type); int sock_equal (const n2n_sock_t * a, const n2n_sock_t * b); +int detect_local_ip_address (n2n_sock_t* out_sock, + const n2n_edge_t* eee); /* Header encryption */ uint64_t time_stamp (void); diff --git a/src/edge_utils.c b/src/edge_utils.c index e790912..99776d2 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -204,9 +204,8 @@ int supernode_connect(n2n_edge_t *eee) { int sockopt; struct sockaddr_in sn_sock; - struct sockaddr_in local_sock; - int sock_len = sizeof(local_sock); - SOCKET probe_sock; + n2n_sock_t local_sock; + n2n_sock_str_t sockbuf; if((eee->conf.connect_tcp) && (eee->sock >= 0)) { closesocket(eee->sock); @@ -266,25 +265,16 @@ int supernode_connect(n2n_edge_t *eee) { traceEvent(TRACE_INFO, "PMTU discovery %s", (eee->conf.disable_pmtu_discovery) ? "disabled" : "enabled"); #endif - // detetct local port even/especially if chosen by OS... - if((getsockname(eee->sock, (struct sockaddr *)&local_sock, &sock_len) == 0) - && (local_sock.sin_family == AF_INET) - && (sock_len == sizeof(local_sock))) { - // ... and write to local preferred socket -- no matter if used or not - eee->conf.preferred_sock.port = ntohs(local_sock.sin_port); - // probe for & overwrite local address only if auto-detection mode + memset(&local_sock, 0, sizeof(n2n_sock_t)); + if(detect_local_ip_address(&local_sock, eee) == 0) { + // always overwrite local port even/especially if chosen by OS... + eee->conf.preferred_sock.port = local_sock.port; + // only if auto-detection mode, ... if(eee->conf.preferred_sock_auto) { - probe_sock = socket(PF_INET, SOCK_DGRAM, 0); - // connecting the UDP socket makes getsockname read the local address it uses to connect (to the sn in this case) - // we cannot do it with the real (eee->sock) socket because socket does not accept any conenction from elsewhere then, - // e.g. from another edge instead of the supernode; hence, we use a temporary socket - connect(probe_sock, (struct sockaddr *)&sn_sock, sizeof(sn_sock)); - if((getsockname(probe_sock, (struct sockaddr *)&local_sock, &sock_len) == 0) - && (local_sock.sin_family == AF_INET) - && (sock_len == sizeof(local_sock))) { - memcpy(&(eee->conf.preferred_sock.addr.v4), &(local_sock.sin_addr.s_addr), IPV4_SIZE); - } - close(probe_sock); + // ... overwrite IP address, too (whole socket struct here) + memcpy(&eee->conf.preferred_sock, &local_sock, sizeof(n2n_sock_t)); + traceEvent(TRACE_INFO, "determined local socket [%s]", + sock_to_cstr(sockbuf, &local_sock)); } } diff --git a/src/n2n.c b/src/n2n.c index ad444ea..3fc78d2 100644 --- a/src/n2n.c +++ b/src/n2n.c @@ -61,6 +61,54 @@ SOCKET open_socket (int local_port, in_addr_t address, int type /* 0 = UDP, TCP } +int detect_local_ip_address (n2n_sock_t* out_sock, const n2n_edge_t* eee) { + + struct sockaddr_in local_sock; + struct sockaddr_in sn_sock; + int sock_len = sizeof(local_sock); + int port = 0; + SOCKET probe_sock; + + out_sock->family = AF_INVALID; + + + // always detetct local port even/especially if chosen by OS... + if((getsockname(eee->sock, (struct sockaddr *)&local_sock, &sock_len) == 0) + && (local_sock.sin_family == AF_INET) + && (sock_len == sizeof(local_sock))) + // remember the port number + out_sock->port = ntohs(local_sock.sin_port); + else + return -1; + + // probe for local IP address + probe_sock = socket(PF_INET, SOCK_DGRAM, 0); + // connecting the UDP socket makes getsockname read the local address it uses to connect (to the sn in this case); + // we cannot do it with the real (eee->sock) socket because socket does not accept any conenction from elsewhere then, + // e.g. from another edge instead of the supernode; as re-connecting to AF_UNSPEC might not work to release the socket + // on non-UNIXoids, we use a temporary socket + if(probe_sock >= 0) { + fill_sockaddr((struct sockaddr*)&sn_sock, sizeof(sn_sock), &eee->curr_sn->sock); + if(connect(probe_sock, (struct sockaddr *)&sn_sock, sizeof(sn_sock)) == 0) { + if((getsockname(probe_sock, (struct sockaddr *)&local_sock, &sock_len) == 0) + && (local_sock.sin_family == AF_INET) + && (sock_len == sizeof(local_sock))) { + memcpy(&(out_sock->addr.v4), &(local_sock.sin_addr.s_addr), IPV4_SIZE); + } else + return -4; + } else + return -3; + close(probe_sock); + } else + return -2; + + out_sock->family = AF_INET; + + return 0; +} + + + static int traceLevel = 2 /* NORMAL */; static int useSyslog = 0, syslog_opened = 0; static FILE *traceFile = NULL;