diff --git a/src/invitation.c b/src/invitation.c index 38634886..1a2f93f5 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -921,16 +921,31 @@ int cmd_join(int argc, char *argv[]) { if(!ai) return 1; - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if(sock <= 0) { - fprintf(stderr, "Could not open socket: %s\n", strerror(errno)); - return 1; + struct addrinfo *aip = NULL; + +next: + if(!aip) + aip = ai; + else { + aip = aip->ai_next; + if(!aip) + return 1; } - if(connect(sock, ai->ai_addr, ai->ai_addrlen)) { - fprintf(stderr, "Could not connect to %s port %s: %s\n", address, port, strerror(errno)); + sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol); + if(sock <= 0) { + fprintf(stderr, "Could not open socket: %s\n", strerror(errno)); + goto next; + } + + if(connect(sock, aip->ai_addr, aip->ai_addrlen)) { + char *addrstr, *portstr; + sockaddr2str((sockaddr_t *)aip->ai_addr, &addrstr, &portstr); + fprintf(stderr, "Could not connect to %s port %s: %s\n", addrstr, portstr, strerror(errno)); + free(addrstr); + free(portstr); closesocket(sock); - return 1; + goto next; } fprintf(stderr, "Connected to %s port %s...\n", address, port); @@ -943,7 +958,7 @@ int cmd_join(int argc, char *argv[]) { if(!sendline(sock, "0 ?%s %d.%d", b64key, PROT_MAJOR, 1)) { fprintf(stderr, "Error sending request to %s port %s: %s\n", address, port, strerror(errno)); closesocket(sock); - return 1; + goto next; } char hisname[4096] = ""; @@ -952,7 +967,7 @@ int cmd_join(int argc, char *argv[]) { if(!recvline(sock, line, sizeof line) || sscanf(line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(sock, line, sizeof line) || !rstrip(line) || sscanf(line, "%d ", &code) != 1 || code != ACK || strlen(line) < 3) { fprintf(stderr, "Cannot read greeting from peer\n"); closesocket(sock); - return 1; + goto next; } // Check if the hash of the key he gave us matches the hash in the URL. @@ -988,8 +1003,14 @@ int cmd_join(int argc, char *argv[]) { return 1; } - if(!sptps_receive_data(&sptps, line, len)) - return 1; + char *p = line; + while(len) { + int done = sptps_receive_data(&sptps, p, len); + if(!done) + return 1; + len -= done; + p += done; + } } sptps_stop(&sptps); diff --git a/src/netutl.c b/src/netutl.c index bff734e1..701a4309 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -83,7 +83,13 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) { char *scopeid; int err; - if(sa->sa.sa_family == AF_UNKNOWN) { + if(sa->sa.sa_family == AF_UNSPEC) { + if(addrstr) + *addrstr = xstrdup("unspec"); + if(portstr) + *portstr = xstrdup("unspec"); + return; + } else if(sa->sa.sa_family == AF_UNKNOWN) { if(addrstr) *addrstr = xstrdup(sa->unknown.address); if(portstr) diff --git a/src/protocol_edge.c b/src/protocol_edge.c index dd676310..21e431ae 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -61,9 +61,9 @@ bool add_edge_h(connection_t *c, const char *request) { char to_name[MAX_STRING_SIZE]; char to_address[MAX_STRING_SIZE]; char to_port[MAX_STRING_SIZE]; - char address_local[MAX_STRING_SIZE] = "unknown"; - char port_local[MAX_STRING_SIZE] = "unknown"; - sockaddr_t address, local_address; + char address_local[MAX_STRING_SIZE]; + char port_local[MAX_STRING_SIZE]; + sockaddr_t address, local_address = {{0}}; uint32_t options; int weight; @@ -117,14 +117,15 @@ bool add_edge_h(connection_t *c, const char *request) { /* Convert addresses */ address = str2sockaddr(to_address, to_port); - local_address = str2sockaddr(address_local, port_local); + if(parameter_count >= 8) + local_address = str2sockaddr(address_local, port_local); /* Check if edge already exists */ e = lookup_edge(from, to); if(e) { - if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address) || sockaddrcmp(&e->local_address, &local_address)) { + if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { if(from == myself) { logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", "ADD_EDGE", c->name, c->hostname); @@ -136,6 +137,28 @@ bool add_edge_h(connection_t *c, const char *request) { edge_del(e); graph(); } + } else if(sockaddrcmp(&e->local_address, &local_address)) { + if(from == myself) { + if(e->local_address.sa.sa_family && local_address.sa.sa_family) { + // Someone has the wrong local address for ourself. Correct then. + logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", + "ADD_EDGE", c->name, c->hostname); + send_add_edge(c, e); + return true; + } + // Otherwise, just ignore it. + return true; + } else if(local_address.sa.sa_family) { + // We learned a new local address for this edge. + sockaddrfree(&e->local_address); + e->local_address = local_address; + + // Tell others about it. + if(!tunnelserver) + forward_request(c, request); + + return true; + } } else return true; } else if(from == myself) {