diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 085f93ed..2a5b03a4 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -32,6 +32,7 @@ #include "ping.h" #include "misc_tools.h" #include "Messenger.h" +#include "util.h" /* The number of seconds for a non responsive node to become bad. */ #define BAD_NODE_TIMEOUT 70 @@ -215,15 +216,25 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list * sent anyways for backwards compatibility) * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the * partner node understands - that's true if *they* are on IPv6 + * + * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for + * our connections, instead we have to look if it is an embedded + * IPv4-in-IPv6 here and convert it down in sendnodes(). */ #ifdef TOX_ENABLE_IPV6 - ipv46x = 0; - if (sa_family == AF_INET) - ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET; - else - ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET; + IP *client_ip = &dht->close_clientlist[i].ip_port.ip; + sa_family_t ip_treat_as_family = client_ip->family; + if ((dht->c->lossless_udp->net->family == AF_INET6) && + (client_ip->family == AF_INET6)) { + /* socket is AF_INET6, address claims AF_INET6: + * check for embedded IPv4-in-IPv6 */ + if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6)) + ip_treat_as_family = AF_INET; + } + + ipv46x = !(sa_family == ip_treat_as_family); #else - ipv46x = sa_family != AF_INET; + ipv46x = !(sa_family == AF_INET); #endif /* If node isn't good or is already in list. */ @@ -267,11 +278,17 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list dht->friends_list[i].client_list[j].client_id); #ifdef TOX_ENABLE_IPV6 - ipv46x = 0; - if (sa_family == AF_INET) - ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET; - else - ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET; + IP *client_ip = &dht->friends_list[i].client_list[j].ip_port.ip; + sa_family_t ip_treat_as_family = client_ip->family; + if ((dht->c->lossless_udp->net->family == AF_INET6) && + (client_ip->family == AF_INET6)) { + /* socket is AF_INET6, address claims AF_INET6: + * check for embedded IPv4-in-IPv6 */ + if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6)) + ip_treat_as_family = AF_INET; + } + + ipv46x = !(sa_family == ip_treat_as_family); #else ipv46x = sa_family != AF_INET; #endif @@ -578,14 +595,21 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl #ifdef TOX_ENABLE_IPV6 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); int i, num_nodes_ok = 0; - for(i = 0; i < num_nodes; i++) - if (nodes_list[i].ip_port.ip.family == AF_INET) { - memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); - nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32; - nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; + for(i = 0; i < num_nodes; i++) { + memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); + nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; - num_nodes_ok++; - } + IP *node_ip = &nodes_list[i].ip_port.ip; + if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6)) + /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ + nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.s6_addr32[3]; + else if (node_ip->family == AF_INET) + nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32; + else /* shouldn't happen */ + continue; + + num_nodes_ok++; + } if (num_nodes_ok < num_nodes) { /* shouldn't happen */ @@ -1461,13 +1485,13 @@ void DHT_save(DHT *dht, uint8_t *data) int DHT_load(DHT *dht, uint8_t *data, uint32_t size) { if (size < sizeof(dht->close_clientlist)) { - fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); + fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); return -1; } - uint32_t friendlistsize = size - sizeof(dht->close_clientlist); + uint32_t friendlistsize = size - sizeof(dht->close_clientlist); if (friendlistsize % sizeof(DHT_Friend) != 0) { - fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); + fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); return -1; } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 8d0b149f..55b27353 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1220,6 +1220,7 @@ void doInbound(Messenger *m) } #ifdef LOGGING +#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60 static time_t lastdump = 0; static char IDString[CLIENT_ID_SIZE * 2 + 1]; static char *ID2String(uint8_t *client_id) @@ -1245,7 +1246,7 @@ void doMessenger(Messenger *m) LANdiscovery(m); #ifdef LOGGING - if (now() > lastdump + 60) { + if (now() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { loglog(" = = = = = = = = \n"); lastdump = now(); @@ -1292,8 +1293,9 @@ void doMessenger(Messenger *m) ping_lastrecv = lastdump - msgfptr->ping_lastrecv; if (ping_lastrecv > 999) ping_lastrecv = 999; - snprintf(logbuffer, sizeof(logbuffer), "F[%2u] <%s> %02u [%03u] %s\n", friend, msgfptr->name, - msgfptr->crypt_connection_id, ping_lastrecv, msgfptr->client_id); + snprintf(logbuffer, sizeof(logbuffer), "F[%2u] <%s> %02u [%03u] %s\n", + friend, msgfptr->name, msgfptr->crypt_connection_id, + ping_lastrecv, ID2String(msgfptr->client_id)); loglog(logbuffer); for(client = 0; client < MAX_FRIEND_CLIENTS; client++) { @@ -1304,7 +1306,7 @@ void doMessenger(Messenger *m) snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n", friend, client, ip_ntoa(&cptr->ip_port.ip), ntohs(cptr->ip_port.port), last_pinged, - cptr->client_id); + ID2String(cptr->client_id)); loglog(logbuffer); } }