diff --git a/src/edge.c b/src/edge.c index f185b4fe..2eaae5d1 100644 --- a/src/edge.c +++ b/src/edge.c @@ -110,11 +110,13 @@ bool dump_edges(connection_t *c) { for splay_each(node_t, n, node_tree) { for splay_each(edge_t, e, n->edge_tree) { char *address = sockaddr2hostname(&e->address); - send_request(c, "%d %d %s %s %s %x %d", + char* local_address = sockaddr2hostname(&e->local_address); + send_request(c, "%d %d %s %s %s %s %x %d", CONTROL, REQ_DUMP_EDGES, e->from->name, e->to->name, address, - e->options, e->weight); + local_address, e->options, e->weight); free(address); + free(local_address); } } diff --git a/src/edge.h b/src/edge.h index cbd9e5ac..ed46b8a4 100644 --- a/src/edge.h +++ b/src/edge.h @@ -30,6 +30,7 @@ typedef struct edge_t { struct node_t *from; struct node_t *to; sockaddr_t address; + sockaddr_t local_address; uint32_t options; /* options turned on for this edge */ int weight; /* weight of this edge */ diff --git a/src/protocol_auth.c b/src/protocol_auth.c index b8d4ee8e..778c607b 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -822,6 +822,16 @@ bool ack_h(connection_t *c, const char *request) { sockaddr2str(&c->address, &hisaddress, NULL); c->edge->address = str2sockaddr(hisaddress, hisport); free(hisaddress); + sockaddr_t local_sa; + socklen_t local_salen = sizeof local_sa; + if (getsockname(c->socket, &local_sa.sa, &local_salen) < 0) + logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get local socket address for connection with %s", c->name); + else { + char *local_address; + sockaddr2str(&local_sa, &local_address, NULL); + c->edge->local_address = str2sockaddr(local_address, myport); + free(local_address); + } c->edge->weight = (weight + c->estimated_weight) / 2; c->edge->connection = c; c->edge->options = c->options; diff --git a/src/protocol_edge.c b/src/protocol_edge.c index e285a6de..4760162c 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -37,14 +37,19 @@ bool send_add_edge(connection_t *c, const edge_t *e) { bool x; char *address, *port; + char *local_address, *local_port; sockaddr2str(&e->address, &address, &port); + sockaddr2str(&e->local_address, &local_address, &local_port); - x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(), + x = send_request(c, "%d %x %s %s %s %s %x %d %s %s", ADD_EDGE, rand(), e->from->name, e->to->name, address, port, - e->options, e->weight); + e->options, e->weight, local_address, local_port); + free(address); free(port); + free(local_address); + free(local_port); return x; } @@ -56,12 +61,15 @@ 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]; - sockaddr_t address; + char address_local[MAX_STRING_SIZE] = "unknown"; + char port_local[MAX_STRING_SIZE] = "unknown"; + sockaddr_t address, local_address; uint32_t options; int weight; - if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d", - from_name, to_name, to_address, to_port, &options, &weight) != 6) { + int parameter_count = sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d "MAX_STRING" "MAX_STRING, + from_name, to_name, to_address, to_port, &options, &weight, address_local, port_local); + if (parameter_count != 6 && parameter_count != 8) { logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, c->hostname); return false; @@ -109,13 +117,14 @@ 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); /* Check if edge already exists */ e = lookup_edge(from, to); if(e) { - if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { + if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address) || sockaddrcmp(&e->local_address, &local_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); @@ -145,6 +154,7 @@ bool add_edge_h(connection_t *c, const char *request) { e->from = from; e->to = to; e->address = address; + e->local_address = local_address; e->options = options; e->weight = weight; edge_add(e); diff --git a/src/tincctl.c b/src/tincctl.c index da66c8ff..18fc05ac 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -985,6 +985,8 @@ static int cmd_dump(int argc, char *argv[]) { char subnet[4096]; char host[4096]; char port[4096]; + char local_host[4096]; + char local_port[4096]; char via[4096]; char nexthop[4096]; int cipher, digest, maclength, compression, distance, socket, weight; @@ -1025,8 +1027,8 @@ static int cmd_dump(int argc, char *argv[]) { } break; case REQ_DUMP_EDGES: { - int n = sscanf(line, "%*d %*d %s %s %s port %s %x %d", from, to, host, port, &options, &weight); - if(n != 6) { + int n = sscanf(line, "%*d %*d %s %s %s port %s %s port %s %x %d", from, to, host, port, local_host, local_port, &options, &weight); + if(n != 8) { fprintf(stderr, "Unable to parse edge dump from tincd.\n"); return 1; } @@ -1038,7 +1040,7 @@ static int cmd_dump(int argc, char *argv[]) { else if(do_graph == 2) printf(" %s -> %s [w = %f, weight = %f];\n", node1, node2, w, w); } else { - printf("%s to %s at %s port %s options %x weight %d\n", from, to, host, port, options, weight); + printf("%s to %s at %s port %s local %s port %s options %x weight %d\n", from, to, host, port, local_host, local_port, options, weight); } } break;