allowed edge to optionally auto-detetct local IP address ('-e auto') for advertising as preferred (#776)

This commit is contained in:
Logan oos Even 2021-09-12 00:22:05 +05:45 committed by GitHub
parent defad50f87
commit 7f1fe9a499
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 20 deletions

5
edge.8
View File

@ -44,10 +44,11 @@ TOS for packets, e.g. 0x48 for SSH like priority
enable PMTU discovery, it can reduce fragmentation but enable PMTU discovery, it can reduce fragmentation but
causes connections to stall if not properly supported causes connections to stall if not properly supported
.TP .TP
\fB\-e \fR<\fIlocal ip\fR> \fB\-e \fR<\fIlocal_ip_address\fR>
advertises the provided local IP address as preferred, advertises the provided local IP address as preferred,
useful if multicast peer detection is not available, e.g. useful if multicast peer detection is not available, e.g.
disabled on routers disabled on routers. \fB\-e auto\fR tries auto-detection of
local IP address.
.TP .TP
\fB\-S1\fR ... \fB\-S2\fR \fB\-S1\fR ... \fB\-S2\fR
do not connect p2p, always use the supernode, do not connect p2p, always use the supernode,

View File

@ -652,6 +652,7 @@ typedef struct n2n_edge_conf {
int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */ int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */
in_addr_t bind_address; /**< The address to bind to if provided (-b) */ in_addr_t bind_address; /**< The address to bind to if provided (-b) */
n2n_sock_t preferred_sock; /**< propagated local sock for better p2p in LAN (-e) */ n2n_sock_t preferred_sock; /**< propagated local sock for better p2p in LAN (-e) */
uint8_t preferred_sock_auto; /**< indicates desired auto detect for preferred sock */
int local_port; int local_port;
int mgmt_port; int mgmt_port;
uint8_t connect_tcp; /** connection to supernode 0 = UDP; 1 = TCP */ uint8_t connect_tcp; /** connection to supernode 0 = UDP; 1 = TCP */

View File

@ -255,7 +255,8 @@ static void help (int level) {
" | causes connections to stall if not properly supported\n"); " | causes connections to stall if not properly supported\n");
#endif #endif
printf(" -e <local ip> | advertises the provided local IP address as preferred,\n" printf(" -e <local ip> | advertises the provided local IP address as preferred,\n"
" | useful if multicast peer detection is not available\n"); " | useful if multicast peer detection is not available,\n"
" | '-e auto' tries IP address auto-detection\n");
printf(" -S1 ... -S2 | do not connect p2p, always use the supernode,\n" printf(" -S1 ... -S2 | do not connect p2p, always use the supernode,\n"
" | -S1 = via UDP" " | -S1 = via UDP"
@ -615,8 +616,16 @@ static int setOption (int optkey, char *optargument, n2n_tuntap_priv_config_t *e
} }
case 'e': { case 'e': {
in_addr_t address_tmp;
if(optargument) { if(optargument) {
in_addr_t address_tmp = inet_addr(optargument);
if(!strcmp(optargument, "auto")) {
address_tmp = INADDR_ANY;
conf->preferred_sock_auto = 1;
} else {
address_tmp = inet_addr(optargument);
}
memcpy(&(conf->preferred_sock.addr.v4), &(address_tmp), IPV4_SIZE); memcpy(&(conf->preferred_sock.addr.v4), &(address_tmp), IPV4_SIZE);
@ -1098,7 +1107,6 @@ int main (int argc, char* argv[]) {
eee->last_sup = 0; /* if it wasn't zero yet */ eee->last_sup = 0; /* if it wasn't zero yet */
eee->curr_sn = eee->conf.supernodes; eee->curr_sn = eee->conf.supernodes;
supernode_connect(eee); supernode_connect(eee);
while(runlevel < 5) { while(runlevel < 5) {
now = time(NULL); now = time(NULL);

View File

@ -203,8 +203,10 @@ void reset_sup_attempts (n2n_edge_t *eee) {
int supernode_connect(n2n_edge_t *eee) { int supernode_connect(n2n_edge_t *eee) {
int sockopt; int sockopt;
struct sockaddr_in sock; struct sockaddr_in sn_sock;
int sock_len = sizeof(sock); struct sockaddr_in local_sock;
int sock_len = sizeof(local_sock);
SOCKET probe_sock;
if((eee->conf.connect_tcp) && (eee->sock >= 0)) { if((eee->conf.connect_tcp) && (eee->sock >= 0)) {
closesocket(eee->sock); closesocket(eee->sock);
@ -227,18 +229,7 @@ int supernode_connect(n2n_edge_t *eee) {
return -1; return -1;
} }
// detetct local port, even/especially if chosen by OS... fill_sockaddr((struct sockaddr*)&sn_sock, sizeof(sn_sock), &eee->curr_sn->sock);
if((getsockname(eee->sock, (struct sockaddr *)&sock, &sock_len) == 0)
&& (sock.sin_family == AF_INET)
&& (sock_len == sizeof(sock))) {
// ... and write to local preferred socket -- no matter if used or not
eee->conf.preferred_sock.port = ntohs(sock.sin_port);
}
// variable 'sock' gets re-used from here on (for sn)
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);
// set tcp socket to O_NONBLOCK so connect does not hang // set tcp socket to O_NONBLOCK so connect does not hang
// requires checking the socket for readiness before sending and receving // requires checking the socket for readiness before sending and receving
@ -249,7 +240,7 @@ int supernode_connect(n2n_edge_t *eee) {
#else #else
fcntl(eee->sock, F_SETFL, O_NONBLOCK); fcntl(eee->sock, F_SETFL, O_NONBLOCK);
#endif #endif
if((connect(eee->sock, (struct sockaddr*)&(sock), sizeof(struct sockaddr)) < 0) if((connect(eee->sock, (struct sockaddr*)&(sn_sock), sizeof(struct sockaddr)) < 0)
&& (errno != EINPROGRESS)) { && (errno != EINPROGRESS)) {
eee->sock = -1; eee->sock = -1;
return -1; return -1;
@ -275,6 +266,28 @@ int supernode_connect(n2n_edge_t *eee) {
traceEvent(TRACE_INFO, "PMTU discovery %s", (eee->conf.disable_pmtu_discovery) ? "disabled" : "enabled"); traceEvent(TRACE_INFO, "PMTU discovery %s", (eee->conf.disable_pmtu_discovery) ? "disabled" : "enabled");
#endif #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
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);
}
}
if(eee->cb.sock_opened) if(eee->cb.sock_opened)
eee->cb.sock_opened(eee); eee->cb.sock_opened(eee);
} }