summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c356
1 files changed, 280 insertions, 76 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index a11f1aad..085f93ed 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -28,8 +28,10 @@
28#endif 28#endif
29 29
30#include "DHT.h" 30#include "DHT.h"
31#include "network.h"
31#include "ping.h" 32#include "ping.h"
32#include "misc_tools.h" 33#include "misc_tools.h"
34#include "Messenger.h"
33 35
34/* The number of seconds for a non responsive node to become bad. */ 36/* The number of seconds for a non responsive node to become bad. */
35#define BAD_NODE_TIMEOUT 70 37#define BAD_NODE_TIMEOUT 70
@@ -115,11 +117,6 @@ static int client_id_cmp(ClientPair p1, ClientPair p2)
115 return c; 117 return c;
116} 118}
117 119
118static int ipport_equal(IP_Port a, IP_Port b)
119{
120 return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port);
121}
122
123static int id_equal(uint8_t *a, uint8_t *b) 120static int id_equal(uint8_t *a, uint8_t *b)
124{ 121{
125 return memcmp(a, b, CLIENT_ID_SIZE) == 0; 122 return memcmp(a, b, CLIENT_ID_SIZE) == 0;
@@ -142,20 +139,23 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id
142 uint32_t i; 139 uint32_t i;
143 uint64_t temp_time = unix_time(); 140 uint64_t temp_time = unix_time();
144 141
145 for (i = 0; i < length; ++i) { 142 /* if client_id is in list, find it and maybe overwrite ip_port */
146 /* If ip_port is assigned to a different client_id replace it */ 143 for (i = 0; i < length; ++i)
147 if (ipport_equal(list[i].ip_port, ip_port)) { 144 if (id_equal(list[i].client_id, client_id)) {
148 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 145 /* Refresh the client timestamp. */
146 list[i].timestamp = temp_time;
147 list[i].ip_port = ip_port;
148 return 1;
149 } 149 }
150 150
151 if (id_equal(list[i].client_id, client_id)) { 151 /* client_id not in list yet: find ip_port to overwrite */
152 for (i = 0; i < length; ++i)
153 if (ipport_equal(&list[i].ip_port, &ip_port)) {
152 /* Refresh the client timestamp. */ 154 /* Refresh the client timestamp. */
153 list[i].timestamp = temp_time; 155 list[i].timestamp = temp_time;
154 list[i].ip_port.ip.uint32 = ip_port.ip.uint32; 156 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
155 list[i].ip_port.port = ip_port.port;
156 return 1; 157 return 1;
157 } 158 }
158 }
159 159
160 return 0; 160 return 0;
161} 161}
@@ -197,18 +197,37 @@ static int friend_number(DHT *dht, uint8_t *client_id)
197 * 197 *
198 * TODO: For the love of based Allah make this function cleaner and much more efficient. 198 * TODO: For the love of based Allah make this function cleaner and much more efficient.
199 */ 199 */
200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) 200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
201{ 201{
202 uint32_t i, j, k; 202 uint32_t i, j, k;
203 uint64_t temp_time = unix_time(); 203 uint64_t temp_time = unix_time();
204 int num_nodes = 0, closest, tout, inlist; 204 int num_nodes = 0, closest, tout, inlist, ipv46x;
205 205
206 for (i = 0; i < LCLIENT_LIST; ++i) { 206 for (i = 0; i < LCLIENT_LIST; ++i) {
207 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 207 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); 208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
209 209
210 /*
211 * NET_PACKET_SEND_NODES sends ONLY AF_INET
212 * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6),
213 * it could send both, but then a) packet size is an issue and
214 * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be
215 * sent anyways for backwards compatibility)
216 * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the
217 * partner node understands - that's true if *they* are on IPv6
218 */
219#ifdef TOX_ENABLE_IPV6
220 ipv46x = 0;
221 if (sa_family == AF_INET)
222 ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET;
223 else
224 ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET;
225#else
226 ipv46x = sa_family != AF_INET;
227#endif
228
210 /* If node isn't good or is already in list. */ 229 /* If node isn't good or is already in list. */
211 if (tout || inlist) 230 if (tout || inlist || ipv46x)
212 continue; 231 continue;
213 232
214 if (num_nodes < MAX_SENT_NODES) { 233 if (num_nodes < MAX_SENT_NODES) {
@@ -247,8 +266,18 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
247 MAX_SENT_NODES, 266 MAX_SENT_NODES,
248 dht->friends_list[i].client_list[j].client_id); 267 dht->friends_list[i].client_list[j].client_id);
249 268
269#ifdef TOX_ENABLE_IPV6
270 ipv46x = 0;
271 if (sa_family == AF_INET)
272 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET;
273 else
274 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET;
275#else
276 ipv46x = sa_family != AF_INET;
277#endif
278
250 /* If node isn't good or is already in list. */ 279 /* If node isn't good or is already in list. */
251 if (tout || inlist) 280 if (tout || inlist || ipv46x)
252 continue; 281 continue;
253 282
254 if (num_nodes < MAX_SENT_NODES) { 283 if (num_nodes < MAX_SENT_NODES) {
@@ -301,7 +330,7 @@ static int replace_bad( Client_data *list,
301 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 330 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
302 list[i].ip_port = ip_port; 331 list[i].ip_port = ip_port;
303 list[i].timestamp = temp_time; 332 list[i].timestamp = temp_time;
304 list[i].ret_ip_port.ip.uint32 = 0; 333 ip_reset(&list[i].ret_ip_port.ip);
305 list[i].ret_ip_port.port = 0; 334 list[i].ret_ip_port.port = 0;
306 list[i].ret_timestamp = 0; 335 list[i].ret_timestamp = 0;
307 return 0; 336 return 0;
@@ -349,7 +378,7 @@ static int replace_good( Client_data *list,
349 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 378 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
350 list[i].ip_port = ip_port; 379 list[i].ip_port = ip_port;
351 list[i].timestamp = temp_time; 380 list[i].timestamp = temp_time;
352 list[i].ret_ip_port.ip.uint32 = 0; 381 ip_reset(&list[i].ret_ip_port.ip);
353 list[i].ret_ip_port.port = 0; 382 list[i].ret_ip_port.port = 0;
354 list[i].ret_timestamp = 0; 383 list[i].ret_timestamp = 0;
355 return 0; 384 return 0;
@@ -447,13 +476,13 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id)
447 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { 476 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
448 pinging = 0; 477 pinging = 0;
449 478
450 if (ip_port.ip.uint32 != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) 479 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id)
451 ++pinging; 480 ++pinging;
452 481
453 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) 482 if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port))
454 ++pinging; 483 ++pinging;
455 484
456 if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) 485 if (pinging == (ping_id != 0) + (ip_isset(&ip_port.ip) != 0))
457 return 1; 486 return 1;
458 } 487 }
459 } 488 }
@@ -518,44 +547,65 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
518 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 547 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
519 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 548 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
520 549
521 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); 550 return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data));
522} 551}
523 552
524/* Send a send nodes response. */ 553/* Send a send nodes response. */
554/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
555 * IPv6 nodes are sent in a different message */
525static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) 556static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
526{ 557{
527 /* Check if packet is going to be sent to ourself. */ 558 /* Check if packet is going to be sent to ourself. */
528 if (id_equal(public_key, dht->c->self_public_key)) 559 if (id_equal(public_key, dht->c->self_public_key))
529 return -1; 560 return -1;
530 561
562 size_t Node4_format_size = sizeof(Node4_format);
531 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 563 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
532 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 564 + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
533 565
534 Node_format nodes_list[MAX_SENT_NODES]; 566 Node_format nodes_list[MAX_SENT_NODES];
535 int num_nodes = get_close_nodes(dht, client_id, nodes_list); 567 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET);
536 568
537 if (num_nodes == 0) 569 if (num_nodes == 0)
538 return 0; 570 return 0;
539 571
540 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 572 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
541 uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 573 uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
542 uint8_t nonce[crypto_box_NONCEBYTES]; 574 uint8_t nonce[crypto_box_NONCEBYTES];
543 new_nonce(nonce); 575 new_nonce(nonce);
544 576
545 memcpy(plain, &ping_id, sizeof(ping_id)); 577 memcpy(plain, &ping_id, sizeof(ping_id));
546 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 578#ifdef TOX_ENABLE_IPV6
579 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
580 int i, num_nodes_ok = 0;
581 for(i = 0; i < num_nodes; i++)
582 if (nodes_list[i].ip_port.ip.family == AF_INET) {
583 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
584 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32;
585 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
586
587 num_nodes_ok++;
588 }
589
590 if (num_nodes_ok < num_nodes) {
591 /* shouldn't happen */
592 num_nodes = num_nodes_ok;
593 }
594#else
595 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
596#endif
547 597
548 int len = encrypt_data( public_key, 598 int len = encrypt_data( public_key,
549 dht->c->self_secret_key, 599 dht->c->self_secret_key,
550 nonce, 600 nonce,
551 plain, 601 plain,
552 sizeof(ping_id) + num_nodes * sizeof(Node_format), 602 sizeof(ping_id) + num_nodes * Node4_format_size,
553 encrypt ); 603 encrypt );
554 604
555 if (len == -1) 605 if (len == -1)
556 return -1; 606 return -1;
557 607
558 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 608 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING)
559 return -1; 609 return -1;
560 610
561 data[0] = NET_PACKET_SEND_NODES; 611 data[0] = NET_PACKET_SEND_NODES;
@@ -563,9 +613,57 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
563 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 613 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
564 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 614 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
565 615
566 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 616 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
567} 617}
568 618
619#ifdef TOX_ENABLE_IPV6
620/* Send a send nodes response: message for IPv6 nodes */
621static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
622{
623 /* Check if packet is going to be sent to ourself. */
624 if (id_equal(public_key, dht->c->self_public_key))
625 return -1;
626
627 size_t Node_format_size = sizeof(Node_format);
628 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
629 + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
630
631 Node_format nodes_list[MAX_SENT_NODES];
632 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6);
633
634 if (num_nodes == 0)
635 return 0;
636
637 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
638 uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
639 uint8_t nonce[crypto_box_NONCEBYTES];
640 random_nonce(nonce);
641
642 memcpy(plain, &ping_id, sizeof(ping_id));
643 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size);
644
645 int len = encrypt_data( public_key,
646 dht->c->self_secret_key,
647 nonce,
648 plain,
649 sizeof(ping_id) + num_nodes * Node_format_size,
650 encrypt );
651
652 if (len == -1)
653 return -1;
654
655 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING)
656 return -1;
657
658 data[0] = NET_PACKET_SEND_NODES_IPV6;
659 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
660 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
661 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
662
663 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
664}
665#endif
666
569static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) 667static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
570{ 668{
571 DHT *dht = object; 669 DHT *dht = object;
@@ -593,6 +691,9 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
593 691
594 memcpy(&ping_id, plain, sizeof(ping_id)); 692 memcpy(&ping_id, plain, sizeof(ping_id));
595 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); 693 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
694#ifdef TOX_ENABLE_IPV6
695 sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
696#endif
596 697
597 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ 698 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
598 699
@@ -606,22 +707,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
606 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 707 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
607 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 708 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
608 709
609 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || 710 size_t Node4_format_size = sizeof(Node4_format);
610 ((length - cid_size) % sizeof(Node_format)) != 0 || 711 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
611 (length < cid_size + sizeof(Node_format))) 712 ((length - cid_size) % Node4_format_size) != 0 ||
713 (length < cid_size + Node4_format_size))
612 return 1; 714 return 1;
613 715
614 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); 716 uint32_t num_nodes = (length - cid_size) / Node4_format_size;
615 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 717 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
616 718
617 int len = decrypt_data( 719 int len = decrypt_data(
618 packet + 1, 720 packet + 1,
619 dht->c->self_secret_key, 721 dht->c->self_secret_key,
620 packet + 1 + CLIENT_ID_SIZE, 722 packet + 1 + CLIENT_ID_SIZE,
621 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 723 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
622 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); 724 sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain );
623 725
624 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 726 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size)
625 return 1; 727 return 1;
626 728
627 memcpy(&ping_id, plain, sizeof(ping_id)); 729 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -629,12 +731,78 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
629 if (!is_gettingnodes(dht, source, ping_id)) 731 if (!is_gettingnodes(dht, source, ping_id))
630 return 1; 732 return 1;
631 733
734 uint32_t i;
632 Node_format nodes_list[MAX_SENT_NODES]; 735 Node_format nodes_list[MAX_SENT_NODES];
736
737#ifdef TOX_ENABLE_IPV6
738 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
739
740 int num_nodes_ok = 0;
741 for(i = 0; i < num_nodes; i++)
742 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) {
743 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
744 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
745 nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
746 nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
747
748 num_nodes_ok++;
749 }
750
751 if (num_nodes_ok < num_nodes) {
752 /* shouldn't happen */
753 num_nodes = num_nodes_ok;
754 }
755#else
633 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 756 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
757#endif
634 758
635 addto_lists(dht, source, packet + 1); 759 addto_lists(dht, source, packet + 1);
636 760
761 for (i = 0; i < num_nodes; ++i) {
762 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
763 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
764 }
765
766 return 0;
767}
768
769#ifdef TOX_ENABLE_IPV6
770static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
771{
772 DHT *dht = object;
773 uint64_t ping_id;
774 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
775 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
776
777 size_t Node_format_size = sizeof(Node4_format);
778 if (length > (cid_size + Node_format_size * MAX_SENT_NODES) ||
779 ((length - cid_size) % Node_format_size) != 0 ||
780 (length < cid_size + Node_format_size))
781 return 1;
782
783 uint32_t num_nodes = (length - cid_size) / Node_format_size;
784 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
785
786 int len = decrypt_data(
787 packet + 1,
788 dht->c->self_secret_key,
789 packet + 1 + CLIENT_ID_SIZE,
790 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
791 sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING, plain );
792
793 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size)
794 return 1;
795
796 memcpy(&ping_id, plain, sizeof(ping_id));
797
798 if (!is_gettingnodes(dht, source, ping_id))
799 return 1;
800
637 uint32_t i; 801 uint32_t i;
802 Node_format nodes_list[MAX_SENT_NODES];
803 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
804
805 addto_lists(dht, source, packet + 1);
638 806
639 for (i = 0; i < num_nodes; ++i) { 807 for (i = 0; i < num_nodes; ++i) {
640 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); 808 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
@@ -643,6 +811,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
643 811
644 return 0; 812 return 0;
645} 813}
814#endif
646 815
647/*----------------------------------------------------------------------------------*/ 816/*----------------------------------------------------------------------------------*/
648/*------------------------END of packet handling functions--------------------------*/ 817/*------------------------END of packet handling functions--------------------------*/
@@ -703,27 +872,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id)
703} 872}
704 873
705/* TODO: Optimize this. */ 874/* TODO: Optimize this. */
706IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) 875int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
707{ 876{
708 uint32_t i, j; 877 uint32_t i, j;
709 uint64_t temp_time = unix_time(); 878 uint64_t temp_time = unix_time();
710 IP_Port empty = {{{{0}}, 0, 0}}; 879
880 ip_reset(&ip_port->ip);
881 ip_port->port = 0;
711 882
712 for (i = 0; i < dht->num_friends; ++i) { 883 for (i = 0; i < dht->num_friends; ++i) {
713 /* Equal */ 884 /* Equal */
714 if (id_equal(dht->friends_list[i].client_id, client_id)) { 885 if (id_equal(dht->friends_list[i].client_id, client_id)) {
715 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 886 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
716 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) 887 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id)
717 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) 888 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
718 return dht->friends_list[i].client_list[j].ip_port; 889 *ip_port = dht->friends_list[i].client_list[j].ip_port;
890 return 1;
891 }
719 } 892 }
720 893
721 return empty; 894 return 0;
722 } 895 }
723 } 896 }
724 897
725 empty.ip.uint32 = 1; 898 return -1;
726 return empty;
727} 899}
728 900
729/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 901/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
@@ -808,6 +980,36 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
808 getnodes(dht, ip_port, public_key, dht->c->self_public_key); 980 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
809 send_ping_request(dht->ping, dht->c, ip_port, public_key); 981 send_ping_request(dht->ping, dht->c, ip_port, public_key);
810} 982}
983int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
984 uint16_t port, uint8_t *public_key)
985{
986 IP_Port ip_port_v64, ip_port_v4;
987 IP *ip_extra = NULL;
988#ifdef TOX_ENABLE_IPV6
989 ip_init(&ip_port_v64.ip, ipv6enabled);
990 if (ipv6enabled) {
991 ip_port_v64.ip.family = AF_UNSPEC;
992 ip_reset(&ip_port_v4.ip);
993 ip_extra = &ip_port_v4.ip;
994 }
995#else
996 ip_init(&ip_port_v64.ip, 0);
997#endif
998
999 if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
1000 ip_port_v64.port = port;
1001 DHT_bootstrap(dht, ip_port_v64, public_key);
1002#ifdef TOX_ENABLE_IPV6
1003 if ((ip_extra != NULL) && ip_isset(ip_extra)) {
1004 ip_port_v4.port = port;
1005 DHT_bootstrap(dht, ip_port_v4, public_key);
1006 }
1007#endif
1008 return 1;
1009 }
1010 else
1011 return 0;
1012}
811 1013
812/* Send the given packet to node with client_id 1014/* Send the given packet to node with client_id
813 * 1015 *
@@ -819,7 +1021,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
819 1021
820 for (i = 0; i < LCLIENT_LIST; ++i) { 1022 for (i = 0; i < LCLIENT_LIST; ++i) {
821 if (id_equal(client_id, dht->close_clientlist[i].client_id)) 1023 if (id_equal(client_id, dht->close_clientlist[i].client_id))
822 return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length); 1024 return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length);
823 } 1025 }
824 1026
825 return -1; 1027 return -1;
@@ -848,7 +1050,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
848 client = &friend->client_list[i]; 1050 client = &friend->client_list[i];
849 1051
850 /* If ip is not zero and node is good. */ 1052 /* If ip is not zero and node is good. */
851 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1053 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
852 1054
853 if (id_equal(client->client_id, friend->client_id)) 1055 if (id_equal(client->client_id, friend->client_id))
854 return 0; 1056 return 0;
@@ -890,8 +1092,8 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
890 client = &friend->client_list[i]; 1092 client = &friend->client_list[i];
891 1093
892 /* If ip is not zero and node is good. */ 1094 /* If ip is not zero and node is good. */
893 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1095 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
894 int retval = sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length); 1096 int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length);
895 1097
896 if ((unsigned int)retval == length) 1098 if ((unsigned int)retval == length)
897 ++sent; 1099 ++sent;
@@ -924,7 +1126,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
924 client = &friend->client_list[i]; 1126 client = &friend->client_list[i];
925 1127
926 /* If ip is not zero and node is good. */ 1128 /* If ip is not zero and node is good. */
927 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1129 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
928 ip_list[n] = client->ip_port; 1130 ip_list[n] = client->ip_port;
929 ++n; 1131 ++n;
930 } 1132 }
@@ -933,7 +1135,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
933 if (n < 1) 1135 if (n < 1)
934 return 0; 1136 return 0;
935 1137
936 int retval = sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length); 1138 int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length);
937 1139
938 if ((unsigned int)retval == length) 1140 if ((unsigned int)retval == length)
939 return 1; 1141 return 1;
@@ -1032,7 +1234,8 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey,
1032 */ 1234 */
1033static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) 1235static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1034{ 1236{
1035 IP zero = {{0}}; 1237 IP zero;
1238 ip_reset(&zero);
1036 1239
1037 if (len > MAX_FRIEND_CLIENTS) 1240 if (len > MAX_FRIEND_CLIENTS)
1038 return zero; 1241 return zero;
@@ -1042,7 +1245,7 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1042 1245
1043 for (i = 0; i < len; ++i) { 1246 for (i = 0; i < len; ++i) {
1044 for (j = 0; j < len; ++j) { 1247 for (j = 0; j < len; ++j) {
1045 if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) 1248 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip))
1046 ++numbers[i]; 1249 ++numbers[i];
1047 } 1250 }
1048 1251
@@ -1065,7 +1268,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1065 uint16_t num = 0; 1268 uint16_t num = 0;
1066 1269
1067 for (i = 0; i < len; ++i) { 1270 for (i = 0; i < len; ++i) {
1068 if (ip_portlist[i].ip.uint32 == ip.uint32) { 1271 if (ip_equal(&ip_portlist[i].ip, &ip)) {
1069 portlist[num] = ntohs(ip_portlist[i].port); 1272 portlist[num] = ntohs(ip_portlist[i].port);
1070 ++num; 1273 ++num;
1071 } 1274 }
@@ -1085,7 +1288,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
1085 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { 1288 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
1086 /* TODO: Improve port guessing algorithm. */ 1289 /* TODO: Improve port guessing algorithm. */
1087 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1290 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1088 IP_Port pinging = {{ip, htons(port), 0}}; 1291 IP_Port pinging;
1292 ip_copy(&pinging.ip, &ip);
1293 pinging.port = htons(port);
1089 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); 1294 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id);
1090 } 1295 }
1091 1296
@@ -1115,8 +1320,7 @@ static void do_NAT(DHT *dht)
1115 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1320 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1116 1321
1117 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1322 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1118 1323 if (!ip_isset(&ip))
1119 if (ip.uint32 == 0)
1120 continue; 1324 continue;
1121 1325
1122 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1326 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1145,16 +1349,15 @@ static void do_NAT(DHT *dht)
1145 */ 1349 */
1146int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) 1350int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1147{ 1351{
1148 if (ip_port.ip.uint32 == 0) 1352 if (!ip_isset(&ip_port.ip))
1149 return -1; 1353 return -1;
1150 1354
1151 uint32_t i; 1355 uint32_t i;
1152 1356
1153 for (i = 0; i < MAX_TOPING; ++i) { 1357 for (i = 0; i < MAX_TOPING; ++i) {
1154 if (dht->toping[i].ip_port.ip.uint32 == 0) { 1358 if (!ip_isset(&dht->toping[i].ip_port.ip)) {
1155 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1359 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1156 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1360 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1157 dht->toping[i].ip_port.port = ip_port.port;
1158 return 0; 1361 return 0;
1159 } 1362 }
1160 } 1363 }
@@ -1162,8 +1365,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1162 for (i = 0; i < MAX_TOPING; ++i) { 1365 for (i = 0; i < MAX_TOPING; ++i) {
1163 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { 1366 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) {
1164 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1367 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1165 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1368 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1166 dht->toping[i].ip_port.port = ip_port.port;
1167 return 0; 1369 return 0;
1168 } 1370 }
1169 } 1371 }
@@ -1185,11 +1387,11 @@ static void do_toping(DHT *dht)
1185 uint32_t i; 1387 uint32_t i;
1186 1388
1187 for (i = 0; i < MAX_TOPING; ++i) { 1389 for (i = 0; i < MAX_TOPING; ++i) {
1188 if (dht->toping[i].ip_port.ip.uint32 == 0) 1390 if (!ip_isset(&dht->toping[i].ip_port.ip))
1189 return; 1391 return;
1190 1392
1191 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); 1393 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id);
1192 dht->toping[i].ip_port.ip.uint32 = 0; 1394 ip_reset(&dht->toping[i].ip_port.ip);
1193 } 1395 }
1194} 1396}
1195 1397
@@ -1216,6 +1418,9 @@ DHT *new_DHT(Net_Crypto *c)
1216 networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); 1418 networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp);
1217 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); 1419 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp);
1218 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); 1420 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp);
1421#ifdef TOX_ENABLE_IPV6
1422 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, temp);
1423#endif
1219 init_cryptopackets(temp); 1424 init_cryptopackets(temp);
1220 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); 1425 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp);
1221 return temp; 1426 return temp;
@@ -1255,24 +1460,24 @@ void DHT_save(DHT *dht, uint8_t *data)
1255 */ 1460 */
1256int DHT_load(DHT *dht, uint8_t *data, uint32_t size) 1461int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1257{ 1462{
1258 if (size < sizeof(dht->close_clientlist)) 1463 if (size < sizeof(dht->close_clientlist)) {
1464 fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size);
1259 return -1; 1465 return -1;
1466 }
1260 1467
1261 if ((size - sizeof(dht->close_clientlist)) % sizeof(DHT_Friend) != 0) 1468 uint32_t friendlistsize = size - sizeof(dht->close_clientlist);
1469 if (friendlistsize % sizeof(DHT_Friend) != 0) {
1470 fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize);
1262 return -1; 1471 return -1;
1472 }
1263 1473
1264 uint32_t i, j; 1474 uint32_t i, j;
1265 uint16_t temp;
1266 /* uint64_t temp_time = unix_time(); */
1267
1268 Client_data *client; 1475 Client_data *client;
1269 1476 uint16_t friends_num = friendlistsize / sizeof(DHT_Friend);
1270 temp = (size - sizeof(dht->close_clientlist)) / sizeof(DHT_Friend); 1477 if (friends_num != 0) {
1271
1272 if (temp != 0) {
1273 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); 1478 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist));
1274 1479
1275 for (i = 0; i < temp; ++i) { 1480 for (i = 0; i < friends_num; ++i) {
1276 DHT_addfriend(dht, tempfriends_list[i].client_id); 1481 DHT_addfriend(dht, tempfriends_list[i].client_id);
1277 1482
1278 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1483 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
@@ -1285,7 +1490,6 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1285 } 1490 }
1286 1491
1287 Client_data *tempclose_clientlist = (Client_data *)data; 1492 Client_data *tempclose_clientlist = (Client_data *)data;
1288
1289 for (i = 0; i < LCLIENT_LIST; ++i) { 1493 for (i = 0; i < LCLIENT_LIST; ++i) {
1290 if (tempclose_clientlist[i].timestamp != 0) 1494 if (tempclose_clientlist[i].timestamp != 0)
1291 DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, 1495 DHT_bootstrap(dht, tempclose_clientlist[i].ip_port,