diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 613 |
1 files changed, 383 insertions, 230 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index eb50cc43..b9ba7e1d 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #define MAX_SENT_NODES 8 | 41 | #define MAX_SENT_NODES 8 |
42 | 42 | ||
43 | /* Ping timeout in seconds */ | 43 | /* Ping timeout in seconds */ |
44 | #define PING_TIMEOUT 5 | 44 | #define PING_TIMEOUT 3 |
45 | 45 | ||
46 | /* The timeout after which a node is discarded completely. */ | 46 | /* The timeout after which a node is discarded completely. */ |
47 | #define KILL_NODE_TIMEOUT 300 | 47 | #define KILL_NODE_TIMEOUT 300 |
@@ -313,7 +313,8 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
313 | if (ipv46x) | 313 | if (ipv46x) |
314 | continue; | 314 | continue; |
315 | 315 | ||
316 | if (!LAN_ip(ipptp->ip_port.ip) && !is_LAN) | 316 | /* don't send LAN ips to non LAN peers */ |
317 | if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) | ||
317 | continue; | 318 | continue; |
318 | 319 | ||
319 | if (num_nodes < MAX_SENT_NODES) { | 320 | if (num_nodes < MAX_SENT_NODES) { |
@@ -572,79 +573,58 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint | |||
572 | } | 573 | } |
573 | } | 574 | } |
574 | 575 | ||
575 | /* checks if ip/port or ping_id are already in the list to get nodes | 576 | #define NODES_ENCRYPTED_MESSAGE_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint64_t) + sizeof(Node_format) + sizeof(Node_format) + crypto_secretbox_MACBYTES) |
576 | * if both are set, both must match, otherwise the set must match | ||
577 | * | ||
578 | * returns 0 if neither is set or no match was found | ||
579 | * returns the (index + 1) of the match if one was found | ||
580 | */ | ||
581 | static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) | ||
582 | { | ||
583 | uint8_t ip_valid = ip_isset(&ip_port.ip); | ||
584 | |||
585 | if (!ip_valid && !ping_id) | ||
586 | return 0; | ||
587 | 577 | ||
588 | uint32_t i; | 578 | /* Send a getnodes request. |
589 | 579 | sendback_node is the node that it will send back the response to (set to NULL to disable this) */ | |
590 | for (i = 0; i < LSEND_NODES_ARRAY; i++) | 580 | static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, Node_format *sendback_node) |
591 | if (!is_timeout(dht->send_nodes[i].timestamp, PING_TIMEOUT)) | ||
592 | if (!ping_id || (dht->send_nodes[i].id == ping_id)) | ||
593 | if (!ip_valid || ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) | ||
594 | return i + 1; | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | /* Same but for get node requests. */ | ||
600 | static uint64_t add_gettingnodes(DHT *dht, IP_Port ip_port) | ||
601 | { | ||
602 | uint32_t i, j; | ||
603 | uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); | ||
604 | |||
605 | for (i = 0; i < PING_TIMEOUT; ++i ) { | ||
606 | for (j = 0; j < LSEND_NODES_ARRAY; ++j ) { | ||
607 | if (is_timeout(dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) { | ||
608 | dht->send_nodes[j].timestamp = unix_time(); | ||
609 | dht->send_nodes[j].ip_port = ip_port; | ||
610 | dht->send_nodes[j].id = ping_id; | ||
611 | return ping_id; | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | |||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | /* Send a getnodes request. */ | ||
620 | static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id) | ||
621 | { | 581 | { |
622 | /* Check if packet is going to be sent to ourself. */ | 582 | /* Check if packet is going to be sent to ourself. */ |
623 | if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0)) | 583 | if (id_equal(public_key, dht->c->self_public_key)) |
624 | return -1; | 584 | return -1; |
625 | 585 | ||
626 | uint64_t ping_id = add_gettingnodes(dht, ip_port); | 586 | uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH] = {0}; |
587 | uint8_t encrypted_message[NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
588 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
589 | |||
590 | new_nonce(nonce); | ||
591 | memcpy(encrypted_message, nonce, crypto_box_NONCEBYTES); | ||
627 | 592 | ||
628 | if (ping_id == 0) | 593 | uint64_t temp_time = unix_time(); |
594 | memcpy(plain_message, &temp_time, sizeof(temp_time)); | ||
595 | Node_format reciever; | ||
596 | memcpy(reciever.client_id, public_key, CLIENT_ID_SIZE); | ||
597 | reciever.ip_port = ip_port; | ||
598 | memcpy(plain_message + sizeof(temp_time), &reciever, sizeof(reciever)); | ||
599 | |||
600 | if (sendback_node != NULL) | ||
601 | memcpy(plain_message + sizeof(temp_time) + sizeof(reciever), sendback_node, sizeof(Node_format)); | ||
602 | |||
603 | int len_m = encrypt_data_symmetric(dht->secret_symmetric_key, | ||
604 | nonce, | ||
605 | plain_message, | ||
606 | sizeof(temp_time) + sizeof(reciever) + sizeof(Node_format), | ||
607 | encrypted_message + crypto_secretbox_NONCEBYTES); | ||
608 | |||
609 | if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES) | ||
629 | return -1; | 610 | return -1; |
630 | 611 | ||
631 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING]; | 612 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
632 | uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; | 613 | uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; |
633 | uint8_t encrypt[sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING]; | 614 | uint8_t encrypt[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
634 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
635 | new_nonce(nonce); | ||
636 | 615 | ||
637 | memcpy(plain, &ping_id, sizeof(ping_id)); | 616 | |
638 | memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); | 617 | memcpy(plain, client_id, CLIENT_ID_SIZE); |
618 | memcpy(plain + CLIENT_ID_SIZE, encrypted_message, NODES_ENCRYPTED_MESSAGE_LENGTH); | ||
639 | 619 | ||
640 | int len = encrypt_data( public_key, | 620 | int len = encrypt_data( public_key, |
641 | dht->c->self_secret_key, | 621 | dht->c->self_secret_key, |
642 | nonce, | 622 | nonce, |
643 | plain, | 623 | plain, |
644 | sizeof(ping_id) + CLIENT_ID_SIZE, | 624 | CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, |
645 | encrypt ); | 625 | encrypt ); |
646 | 626 | ||
647 | if (len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) | 627 | if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) |
648 | return -1; | 628 | return -1; |
649 | 629 | ||
650 | data[0] = NET_PACKET_GET_NODES; | 630 | data[0] = NET_PACKET_GET_NODES; |
@@ -655,18 +635,20 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
655 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); | 635 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); |
656 | } | 636 | } |
657 | 637 | ||
638 | |||
658 | /* Send a send nodes response. */ | 639 | /* Send a send nodes response. */ |
659 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, | 640 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, |
660 | * IPv6 nodes are sent in a different message */ | 641 | * IPv6 nodes are sent in a different message |
661 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | 642 | * encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */ |
643 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) | ||
662 | { | 644 | { |
663 | /* Check if packet is going to be sent to ourself. */ | 645 | /* Check if packet is going to be sent to ourself. */ |
664 | if (id_equal(public_key, dht->c->self_public_key)) | 646 | if (id_equal(public_key, dht->c->self_public_key)) |
665 | return -1; | 647 | return -1; |
666 | 648 | ||
667 | size_t Node4_format_size = sizeof(Node4_format); | 649 | size_t Node4_format_size = sizeof(Node4_format); |
668 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | 650 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES |
669 | + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 651 | + Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
670 | 652 | ||
671 | Node_format nodes_list[MAX_SENT_NODES]; | 653 | Node_format nodes_list[MAX_SENT_NODES]; |
672 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET, LAN_ip(ip_port.ip) == 0); | 654 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET, LAN_ip(ip_port.ip) == 0); |
@@ -674,14 +656,12 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl | |||
674 | if (num_nodes == 0) | 656 | if (num_nodes == 0) |
675 | return 0; | 657 | return 0; |
676 | 658 | ||
677 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; | 659 | uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; |
678 | uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 660 | uint8_t encrypt[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
679 | uint8_t nonce[crypto_box_NONCEBYTES]; | 661 | uint8_t nonce[crypto_box_NONCEBYTES]; |
680 | new_nonce(nonce); | 662 | new_nonce(nonce); |
681 | 663 | ||
682 | memcpy(plain, &ping_id, sizeof(ping_id)); | 664 | Node4_format *nodes4_list = (Node4_format *)(plain); |
683 | |||
684 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
685 | int i, num_nodes_ok = 0; | 665 | int i, num_nodes_ok = 0; |
686 | 666 | ||
687 | for (i = 0; i < num_nodes; i++) { | 667 | for (i = 0; i < num_nodes; i++) { |
@@ -706,17 +686,16 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl | |||
706 | num_nodes = num_nodes_ok; | 686 | num_nodes = num_nodes_ok; |
707 | } | 687 | } |
708 | 688 | ||
689 | memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); | ||
709 | int len = encrypt_data( public_key, | 690 | int len = encrypt_data( public_key, |
710 | dht->c->self_secret_key, | 691 | dht->c->self_secret_key, |
711 | nonce, | 692 | nonce, |
712 | plain, | 693 | plain, |
713 | sizeof(ping_id) + num_nodes * Node4_format_size, | 694 | num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, |
714 | encrypt ); | 695 | encrypt ); |
715 | 696 | ||
716 | if (len == -1) | 697 | if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + |
717 | return -1; | 698 | crypto_box_MACBYTES) |
718 | |||
719 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING) | ||
720 | return -1; | 699 | return -1; |
721 | 700 | ||
722 | data[0] = NET_PACKET_SEND_NODES; | 701 | data[0] = NET_PACKET_SEND_NODES; |
@@ -728,15 +707,15 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl | |||
728 | } | 707 | } |
729 | 708 | ||
730 | /* Send a send nodes response: message for IPv6 nodes */ | 709 | /* Send a send nodes response: message for IPv6 nodes */ |
731 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | 710 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) |
732 | { | 711 | { |
733 | /* Check if packet is going to be sent to ourself. */ | 712 | /* Check if packet is going to be sent to ourself. */ |
734 | if (id_equal(public_key, dht->c->self_public_key)) | 713 | if (id_equal(public_key, dht->c->self_public_key)) |
735 | return -1; | 714 | return -1; |
736 | 715 | ||
737 | size_t Node_format_size = sizeof(Node_format); | 716 | size_t Node_format_size = sizeof(Node_format); |
738 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | 717 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES |
739 | + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 718 | + Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
740 | 719 | ||
741 | Node_format nodes_list[MAX_SENT_NODES]; | 720 | Node_format nodes_list[MAX_SENT_NODES]; |
742 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6, LAN_ip(ip_port.ip) == 0); | 721 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6, LAN_ip(ip_port.ip) == 0); |
@@ -744,25 +723,21 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ | |||
744 | if (num_nodes == 0) | 723 | if (num_nodes == 0) |
745 | return 0; | 724 | return 0; |
746 | 725 | ||
747 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; | 726 | uint8_t plain[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; |
748 | uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 727 | uint8_t encrypt[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
749 | uint8_t nonce[crypto_box_NONCEBYTES]; | 728 | uint8_t nonce[crypto_box_NONCEBYTES]; |
750 | new_nonce(nonce); | 729 | new_nonce(nonce); |
751 | 730 | ||
752 | memcpy(plain, &ping_id, sizeof(ping_id)); | 731 | memcpy(plain, nodes_list, num_nodes * Node_format_size); |
753 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size); | 732 | memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); |
754 | |||
755 | int len = encrypt_data( public_key, | 733 | int len = encrypt_data( public_key, |
756 | dht->c->self_secret_key, | 734 | dht->c->self_secret_key, |
757 | nonce, | 735 | nonce, |
758 | plain, | 736 | plain, |
759 | sizeof(ping_id) + num_nodes * Node_format_size, | 737 | num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, |
760 | encrypt ); | 738 | encrypt ); |
761 | 739 | ||
762 | if (len == -1) | 740 | if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) |
763 | return -1; | ||
764 | |||
765 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING) | ||
766 | return -1; | 741 | return -1; |
767 | 742 | ||
768 | data[0] = NET_PACKET_SEND_NODES_IPV6; | 743 | data[0] = NET_PACKET_SEND_NODES_IPV6; |
@@ -776,45 +751,77 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ | |||
776 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 751 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
777 | { | 752 | { |
778 | DHT *dht = object; | 753 | DHT *dht = object; |
779 | uint64_t ping_id; | ||
780 | 754 | ||
781 | if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES | 755 | if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + |
782 | + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING )) | 756 | crypto_box_MACBYTES )) |
783 | return 1; | 757 | return 1; |
784 | 758 | ||
785 | /* Check if packet is from ourself. */ | 759 | /* Check if packet is from ourself. */ |
786 | if (id_equal(packet + 1, dht->c->self_public_key)) | 760 | if (id_equal(packet + 1, dht->c->self_public_key)) |
787 | return 1; | 761 | return 1; |
788 | 762 | ||
789 | uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; | 763 | uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; |
790 | 764 | ||
791 | int len = decrypt_data( packet + 1, | 765 | int len = decrypt_data( packet + 1, |
792 | dht->c->self_secret_key, | 766 | dht->c->self_secret_key, |
793 | packet + 1 + CLIENT_ID_SIZE, | 767 | packet + 1 + CLIENT_ID_SIZE, |
794 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 768 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
795 | sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, | 769 | CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, |
796 | plain ); | 770 | plain ); |
797 | 771 | ||
798 | if (len != sizeof(ping_id) + CLIENT_ID_SIZE) | 772 | if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) |
799 | return 1; | 773 | return 1; |
800 | 774 | ||
801 | memcpy(&ping_id, plain, sizeof(ping_id)); | 775 | sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE); |
802 | sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); | 776 | sendnodes_ipv6(dht, source, packet + 1, plain, |
803 | sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id), | 777 | plain + CLIENT_ID_SIZE); /* TODO: prevent possible amplification attacks */ |
804 | ping_id); /* TODO: prevent possible amplification attacks */ | ||
805 | 778 | ||
806 | add_toping(dht->ping, packet + 1, source); | 779 | add_toping(dht->ping, packet + 1, source); |
807 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ | 780 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ |
808 | 781 | ||
809 | return 0; | 782 | return 0; |
810 | } | 783 | } |
784 | /* return 0 if no | ||
785 | return 1 if yes | ||
786 | encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH*/ | ||
787 | static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_ip_port, uint8_t *encrypted_data, | ||
788 | Node_format *sendback_node) | ||
789 | { | ||
790 | uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
791 | |||
792 | if (decrypt_data_symmetric(dht->secret_symmetric_key, encrypted_data, encrypted_data + crypto_secretbox_NONCEBYTES, | ||
793 | NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES, | ||
794 | plain_message) != sizeof(uint64_t) + sizeof(Node_format) * 2) | ||
795 | return 0; | ||
796 | |||
797 | uint64_t comp_time; | ||
798 | memcpy(&comp_time, plain_message, sizeof(uint64_t)); | ||
799 | uint64_t temp_time = unix_time(); | ||
800 | |||
801 | if (comp_time + PING_TIMEOUT < temp_time || temp_time < comp_time) | ||
802 | return 0; | ||
803 | |||
804 | Node_format test; | ||
805 | memcpy(&test, plain_message + sizeof(uint64_t), sizeof(Node_format)); | ||
806 | |||
807 | if (!ipport_equal(&test.ip_port, &node_ip_port) || memcmp(test.client_id, client_id, CLIENT_ID_SIZE) != 0) | ||
808 | return 0; | ||
809 | |||
810 | memcpy(sendback_node, plain_message + sizeof(uint64_t) + sizeof(Node_format), sizeof(Node_format)); | ||
811 | return 1; | ||
812 | } | ||
813 | |||
814 | /* Function is needed in following functions. */ | ||
815 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, Node_format *list, uint16_t num_nodes); | ||
811 | 816 | ||
812 | static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, | 817 | static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, |
813 | size_t node_format_size, uint8_t *plain, uint32_t *num_nodes_out) | 818 | size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node) |
814 | { | 819 | { |
820 | if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) | ||
821 | return 1; | ||
822 | |||
815 | DHT *dht = object; | 823 | DHT *dht = object; |
816 | uint64_t ping_id; | 824 | uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES; |
817 | uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | ||
818 | 825 | ||
819 | if (length <= cid_size) /* too short */ | 826 | if (length <= cid_size) /* too short */ |
820 | return 1; | 827 | return 1; |
@@ -834,21 +841,17 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, | |||
834 | dht->c->self_secret_key, | 841 | dht->c->self_secret_key, |
835 | packet + 1 + CLIENT_ID_SIZE, | 842 | packet + 1 + CLIENT_ID_SIZE, |
836 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 843 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
837 | sizeof(ping_id) + num_nodes * node_format_size + ENCRYPTION_PADDING, | 844 | num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, |
838 | plain); | 845 | plain); |
839 | 846 | ||
840 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * node_format_size) | 847 | if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) |
841 | return 1; | 848 | return 1; |
842 | 849 | ||
843 | memcpy(&ping_id, plain, sizeof(ping_id)); | 850 | if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node)) |
844 | |||
845 | int send_nodes_index = is_gettingnodes(dht, source, ping_id); | ||
846 | |||
847 | if (!send_nodes_index) | ||
848 | return 1; | 851 | return 1; |
849 | 852 | ||
850 | /* store the address the *request* was sent to */ | 853 | /* store the address the *request* was sent to */ |
851 | addto_lists(dht, dht->send_nodes[send_nodes_index - 1].ip_port, packet + 1); | 854 | addto_lists(dht, source, packet + 1); |
852 | 855 | ||
853 | *num_nodes_out = num_nodes; | 856 | *num_nodes_out = num_nodes; |
854 | 857 | ||
@@ -858,20 +861,24 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, | |||
858 | static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 861 | static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
859 | { | 862 | { |
860 | DHT *dht = object; | 863 | DHT *dht = object; |
861 | uint64_t ping_id; | ||
862 | size_t node4_format_size = sizeof(Node4_format); | 864 | size_t node4_format_size = sizeof(Node4_format); |
863 | uint8_t plain[sizeof(ping_id) + node4_format_size * MAX_SENT_NODES]; | 865 | uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; |
864 | uint32_t num_nodes; | 866 | uint32_t num_nodes; |
865 | 867 | ||
866 | if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, &num_nodes)) | 868 | Node_format sendback_node; |
869 | |||
870 | if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes, | ||
871 | &sendback_node)) | ||
867 | return 1; | 872 | return 1; |
868 | 873 | ||
869 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | 874 | Node4_format *nodes4_list = (Node4_format *)(plain); |
870 | uint32_t i; | 875 | uint32_t i; |
871 | 876 | ||
872 | IP_Port ipp; | 877 | IP_Port ipp; |
873 | ipp.ip.family = AF_INET; | 878 | ipp.ip.family = AF_INET; |
874 | 879 | ||
880 | Node_format nodes_list[MAX_SENT_NODES]; | ||
881 | |||
875 | for (i = 0; i < num_nodes; i++) | 882 | for (i = 0; i < num_nodes; i++) |
876 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { | 883 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { |
877 | ipp.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | 884 | ipp.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; |
@@ -879,24 +886,31 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
879 | 886 | ||
880 | send_ping_request(dht->ping, ipp, nodes4_list[i].client_id); | 887 | send_ping_request(dht->ping, ipp, nodes4_list[i].client_id); |
881 | returnedip_ports(dht, ipp, nodes4_list[i].client_id, packet + 1); | 888 | returnedip_ports(dht, ipp, nodes4_list[i].client_id, packet + 1); |
889 | |||
890 | memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | ||
891 | ipport_copy(&nodes_list[i].ip_port, &ipp); | ||
882 | } | 892 | } |
883 | 893 | ||
894 | send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes); | ||
884 | return 0; | 895 | return 0; |
885 | } | 896 | } |
886 | 897 | ||
887 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 898 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
888 | { | 899 | { |
889 | DHT *dht = object; | 900 | DHT *dht = object; |
890 | uint64_t ping_id; | ||
891 | size_t node_format_size = sizeof(Node_format); | 901 | size_t node_format_size = sizeof(Node_format); |
892 | uint8_t plain[sizeof(ping_id) + node_format_size * MAX_SENT_NODES]; | 902 | uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; |
893 | uint32_t num_nodes; | 903 | uint32_t num_nodes; |
894 | 904 | ||
895 | if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, &num_nodes)) | 905 | Node_format sendback_node; |
906 | |||
907 | if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes, | ||
908 | &sendback_node)) | ||
896 | return 1; | 909 | return 1; |
897 | 910 | ||
898 | Node_format *nodes_list = (Node_format *)(plain + sizeof(ping_id)); | 911 | Node_format *nodes_list = (Node_format *)(plain); |
899 | uint32_t i; | 912 | uint32_t i; |
913 | send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes); | ||
900 | 914 | ||
901 | for (i = 0; i < num_nodes; i++) | 915 | for (i = 0; i < num_nodes; i++) |
902 | if (ipport_isset(&nodes_list[i].ip_port)) { | 916 | if (ipport_isset(&nodes_list[i].ip_port)) { |
@@ -924,7 +938,7 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_ | |||
924 | for (a = 0, assoc = &list[i].assoc6; a < 2; a++, assoc = &list[i].assoc4) | 938 | for (a = 0, assoc = &list[i].assoc6; a < 2; a++, assoc = &list[i].assoc4) |
925 | if (ipport_isset(&(assoc->ip_port)) && | 939 | if (ipport_isset(&(assoc->ip_port)) && |
926 | !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | 940 | !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { |
927 | getnodes(dht, assoc->ip_port, list[i].client_id, client_id); | 941 | getnodes(dht, assoc->ip_port, list[i].client_id, client_id, NULL); |
928 | ++num; | 942 | ++num; |
929 | 943 | ||
930 | if (num >= max_num) | 944 | if (num >= max_num) |
@@ -1057,7 +1071,7 @@ static void do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8 | |||
1057 | if ((num_nodes != 0) && is_timeout(*lastgetnode, GET_NODE_INTERVAL)) { | 1071 | if ((num_nodes != 0) && is_timeout(*lastgetnode, GET_NODE_INTERVAL)) { |
1058 | uint32_t rand_node = rand() % num_nodes; | 1072 | uint32_t rand_node = rand() % num_nodes; |
1059 | getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id, | 1073 | getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id, |
1060 | client_id); | 1074 | client_id, NULL); |
1061 | *lastgetnode = temp_time; | 1075 | *lastgetnode = temp_time; |
1062 | } | 1076 | } |
1063 | } | 1077 | } |
@@ -1085,7 +1099,7 @@ static void do_Close(DHT *dht) | |||
1085 | 1099 | ||
1086 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) | 1100 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) |
1087 | { | 1101 | { |
1088 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); | 1102 | getnodes(dht, ip_port, public_key, dht->c->self_public_key, NULL); |
1089 | } | 1103 | } |
1090 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | 1104 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, |
1091 | uint16_t port, uint8_t *public_key) | 1105 | uint16_t port, uint8_t *public_key) |
@@ -1528,6 +1542,251 @@ static void do_NAT(DHT *dht) | |||
1528 | /*----------------------------------------------------------------------------------*/ | 1542 | /*----------------------------------------------------------------------------------*/ |
1529 | /*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ | 1543 | /*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ |
1530 | 1544 | ||
1545 | #define HARDREQ_DATA_SIZE 768 /* Attempt to prevent amplification/other attacks*/ | ||
1546 | |||
1547 | #define CHECK_TYPE_ROUTE_REQ 0 | ||
1548 | #define CHECK_TYPE_ROUTE_RES 1 | ||
1549 | #define CHECK_TYPE_GETNODE_REQ 2 | ||
1550 | #define CHECK_TYPE_GETNODE_RES 3 | ||
1551 | #define CHECK_TYPE_TEST_REQ 4 | ||
1552 | #define CHECK_TYPE_TEST_RES 5 | ||
1553 | |||
1554 | static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length) | ||
1555 | { | ||
1556 | if (length > HARDREQ_DATA_SIZE - 1) | ||
1557 | return -1; | ||
1558 | |||
1559 | uint8_t packet[MAX_DATA_SIZE]; | ||
1560 | uint8_t data[HARDREQ_DATA_SIZE] = {0}; | ||
1561 | data[0] = type; | ||
1562 | memcpy(data + 1, contents, length); | ||
1563 | int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, sendto->client_id, data, | ||
1564 | sizeof(data), CRYPTO_PACKET_HARDENING); | ||
1565 | |||
1566 | if (len == -1) | ||
1567 | return -1; | ||
1568 | |||
1569 | return sendpacket(dht->c->lossless_udp->net, sendto->ip_port, packet, len); | ||
1570 | } | ||
1571 | |||
1572 | /* Send a get node hardening request */ | ||
1573 | static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id) | ||
1574 | { | ||
1575 | uint8_t data[sizeof(Node_format) + CLIENT_ID_SIZE]; | ||
1576 | memcpy(data, node_totest, sizeof(Node_format)); | ||
1577 | memcpy(data + sizeof(Node_format), search_id, CLIENT_ID_SIZE); | ||
1578 | return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + CLIENT_ID_SIZE); | ||
1579 | } | ||
1580 | |||
1581 | /* Send a get node hardening response */ | ||
1582 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, Node_format *list, uint16_t num_nodes) | ||
1583 | { | ||
1584 | if (!ip_isset(&sendto->ip_port.ip)) | ||
1585 | return -1; | ||
1586 | |||
1587 | uint8_t packet[MAX_DATA_SIZE]; | ||
1588 | uint8_t data[1 + num_nodes * sizeof(Node_format)]; | ||
1589 | data[0] = CHECK_TYPE_GETNODE_RES; | ||
1590 | memcpy(data + 1, list, num_nodes * sizeof(Node_format)); | ||
1591 | int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, sendto->client_id, data, | ||
1592 | sizeof(data), CRYPTO_PACKET_HARDENING); | ||
1593 | |||
1594 | if (len == -1) | ||
1595 | return -1; | ||
1596 | |||
1597 | return sendpacket(dht->c->lossless_udp->net, sendto->ip_port, packet, len); | ||
1598 | } | ||
1599 | /* | ||
1600 | * check how many nodes in nodes are also present in the closelist. | ||
1601 | * TODO: make this function better. | ||
1602 | */ | ||
1603 | static int have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num, sa_family_t sa_family) | ||
1604 | { | ||
1605 | Node_format nodes_list[MAX_SENT_NODES]; | ||
1606 | int num_nodes = get_close_nodes(dht, dht->c->self_public_key, nodes_list, sa_family, 1); | ||
1607 | |||
1608 | if (num_nodes < 1) | ||
1609 | return -1; | ||
1610 | |||
1611 | int counter = 0; | ||
1612 | uint32_t i, j; | ||
1613 | |||
1614 | for (i = 0; i < num; ++i) { | ||
1615 | if (id_equal(nodes[i].client_id, dht->c->self_public_key)) { | ||
1616 | ++counter; | ||
1617 | } | ||
1618 | |||
1619 | for (j = 0; j < (uint32_t)num_nodes; ++j) { | ||
1620 | if (id_equal(nodes[i].client_id, nodes_list[j].client_id)) { | ||
1621 | if (ipport_equal(&nodes[i].ip_port, &nodes_list[j].ip_port)) { | ||
1622 | ++counter; | ||
1623 | break; | ||
1624 | } | ||
1625 | } | ||
1626 | } | ||
1627 | } | ||
1628 | |||
1629 | return counter; | ||
1630 | } | ||
1631 | /* TODO: improve */ | ||
1632 | static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, uint8_t *client_id, sa_family_t sa_family) | ||
1633 | { | ||
1634 | uint32_t i; | ||
1635 | |||
1636 | for (i = 0; i < LCLIENT_LIST; ++i) { | ||
1637 | if (memcmp(dht->close_clientlist[i].client_id, client_id, CLIENT_ID_SIZE) != 0) | ||
1638 | continue; | ||
1639 | |||
1640 | if (sa_family == AF_INET) | ||
1641 | return &dht->close_clientlist[i].assoc4; | ||
1642 | else if (sa_family == AF_INET6) | ||
1643 | return &dht->close_clientlist[i].assoc6; | ||
1644 | } | ||
1645 | |||
1646 | return NULL; | ||
1647 | } | ||
1648 | |||
1649 | /* Interval in seconds between hardening checks */ | ||
1650 | #define HARDENING_INTERVAL 5 | ||
1651 | #define HARDEN_TIMEOUT 500 | ||
1652 | |||
1653 | /* Handle a received hardening packet */ | ||
1654 | static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) | ||
1655 | { | ||
1656 | DHT *dht = object; | ||
1657 | |||
1658 | if (length < 2) { | ||
1659 | return 1; | ||
1660 | } | ||
1661 | |||
1662 | switch (packet[0]) { | ||
1663 | case CHECK_TYPE_GETNODE_REQ: { | ||
1664 | if (length != HARDREQ_DATA_SIZE) | ||
1665 | return 1; | ||
1666 | |||
1667 | Node_format node, tocheck_node; | ||
1668 | node.ip_port = source; | ||
1669 | memcpy(node.client_id, source_pubkey, CLIENT_ID_SIZE); | ||
1670 | memcpy(&tocheck_node, packet + 1, sizeof(Node_format)); | ||
1671 | |||
1672 | if (getnodes(dht, tocheck_node.ip_port, tocheck_node.client_id, packet + 1 + sizeof(Node_format), &node) == -1) | ||
1673 | return 1; | ||
1674 | |||
1675 | return 0; | ||
1676 | } | ||
1677 | |||
1678 | case CHECK_TYPE_GETNODE_RES: { | ||
1679 | if ((length - 1) % sizeof(Node_format) != 0) | ||
1680 | return 1; | ||
1681 | |||
1682 | uint16_t num = (length - 1) / sizeof(Node_format); | ||
1683 | |||
1684 | /* TODO: MAX_SENT_NODES nodes should be returned at all times | ||
1685 | (right now we have a small network size so it could cause problems for testing and etc..) */ | ||
1686 | if (num > MAX_SENT_NODES || num == 0) | ||
1687 | return 1; | ||
1688 | |||
1689 | Node_format nodes[num]; | ||
1690 | memcpy(nodes, packet + 1, sizeof(Node_format)*num); | ||
1691 | |||
1692 | /* NOTE: This should work for now but should be changed to something better. */ | ||
1693 | if (have_nodes_closelist(dht, nodes, num, nodes[0].ip_port.ip.family) < (num + 1) / 2) | ||
1694 | return 1; | ||
1695 | |||
1696 | |||
1697 | IPPTsPng *temp = get_closelist_IPPTsPng(dht, source_pubkey, source.ip.family); | ||
1698 | |||
1699 | if (temp == NULL) | ||
1700 | return 1; | ||
1701 | |||
1702 | if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) | ||
1703 | return 1; | ||
1704 | |||
1705 | if (memcmp(temp->hardening.send_nodes_pingedid, source_pubkey, CLIENT_ID_SIZE) != 0) | ||
1706 | return 1; | ||
1707 | |||
1708 | /* If Nodes look good and the request checks out */ | ||
1709 | temp->hardening.routes_requests_ok = 1; | ||
1710 | return 0;/* success*/ | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | return 1; | ||
1715 | } | ||
1716 | |||
1717 | /* Return a random node from all the nodes we are connected to. | ||
1718 | * TODO: improve this function. | ||
1719 | */ | ||
1720 | Node_format random_node(DHT *dht, sa_family_t sa_family) | ||
1721 | { | ||
1722 | uint8_t id[CLIENT_ID_SIZE]; | ||
1723 | uint32_t i; | ||
1724 | |||
1725 | for (i = 0; i < CLIENT_ID_SIZE / 4; ++i) { /* populate the id with pseudorandom bytes.*/ | ||
1726 | uint32_t t = rand(); | ||
1727 | memcpy(id + i * sizeof(t), &t, sizeof(t)); | ||
1728 | } | ||
1729 | |||
1730 | Node_format nodes_list[MAX_SENT_NODES]; | ||
1731 | memset(nodes_list, 0, sizeof(nodes_list)); | ||
1732 | int num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1); | ||
1733 | |||
1734 | if (num_nodes < 1) | ||
1735 | return nodes_list[0]; | ||
1736 | else | ||
1737 | return nodes_list[rand() % num_nodes]; | ||
1738 | } | ||
1739 | |||
1740 | |||
1741 | void do_hardening(DHT *dht) | ||
1742 | { | ||
1743 | uint32_t i; | ||
1744 | |||
1745 | for (i = 0; i < LCLIENT_LIST * 2; ++i) { | ||
1746 | IPPTsPng *cur_iptspng; | ||
1747 | sa_family_t sa_family; | ||
1748 | uint8_t *client_id = dht->close_clientlist[i / 2].client_id; | ||
1749 | |||
1750 | if (i % 2 == 0) { | ||
1751 | cur_iptspng = &dht->close_clientlist[i / 2].assoc4; | ||
1752 | sa_family = AF_INET; | ||
1753 | } else { | ||
1754 | cur_iptspng = &dht->close_clientlist[i / 2].assoc6; | ||
1755 | sa_family = AF_INET6; | ||
1756 | } | ||
1757 | |||
1758 | if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) | ||
1759 | continue; | ||
1760 | |||
1761 | if (cur_iptspng->hardening.send_nodes_ok == 0) { | ||
1762 | if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { | ||
1763 | Node_format rand_node = random_node(dht, sa_family); | ||
1764 | |||
1765 | if (!ipport_isset(&rand_node.ip_port)) | ||
1766 | continue; | ||
1767 | |||
1768 | Node_format to_test; | ||
1769 | to_test.ip_port = cur_iptspng->ip_port; | ||
1770 | memcpy(to_test.client_id, client_id, CLIENT_ID_SIZE); | ||
1771 | |||
1772 | //TODO: The search id should maybe not be ours? | ||
1773 | if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->c->self_public_key) != -1) { | ||
1774 | memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.client_id, CLIENT_ID_SIZE); | ||
1775 | cur_iptspng->hardening.send_nodes_timestamp = unix_time(); | ||
1776 | } | ||
1777 | } | ||
1778 | } else { | ||
1779 | if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) { | ||
1780 | cur_iptspng->hardening.send_nodes_ok = 0; | ||
1781 | } | ||
1782 | } | ||
1783 | |||
1784 | //TODO: add the 2 other testers. | ||
1785 | } | ||
1786 | } | ||
1787 | |||
1788 | /*----------------------------------------------------------------------------------*/ | ||
1789 | |||
1531 | DHT *new_DHT(Net_Crypto *c) | 1790 | DHT *new_DHT(Net_Crypto *c) |
1532 | { | 1791 | { |
1533 | /* init time */ | 1792 | /* init time */ |
@@ -1552,10 +1811,11 @@ DHT *new_DHT(Net_Crypto *c) | |||
1552 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); | 1811 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); |
1553 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); | 1812 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); |
1554 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); | 1813 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); |
1555 | |||
1556 | init_cryptopackets(dht); | 1814 | init_cryptopackets(dht); |
1557 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); | 1815 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); |
1816 | cryptopacket_registerhandler(c, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); | ||
1558 | 1817 | ||
1818 | new_symmetric_key(dht->secret_symmetric_key); | ||
1559 | return dht; | 1819 | return dht; |
1560 | } | 1820 | } |
1561 | 1821 | ||
@@ -1567,6 +1827,7 @@ void do_DHT(DHT *dht) | |||
1567 | do_DHT_friends(dht); | 1827 | do_DHT_friends(dht); |
1568 | do_NAT(dht); | 1828 | do_NAT(dht); |
1569 | do_toping(dht->ping); | 1829 | do_toping(dht->ping); |
1830 | do_hardening(dht); | ||
1570 | } | 1831 | } |
1571 | void kill_DHT(DHT *dht) | 1832 | void kill_DHT(DHT *dht) |
1572 | { | 1833 | { |
@@ -1575,82 +1836,11 @@ void kill_DHT(DHT *dht) | |||
1575 | free(dht); | 1836 | free(dht); |
1576 | } | 1837 | } |
1577 | 1838 | ||
1578 | /* Get the size of the DHT (for saving). */ | ||
1579 | uint32_t DHT_size_old(DHT *dht) | ||
1580 | { | ||
1581 | return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends; | ||
1582 | } | ||
1583 | |||
1584 | /* Save the DHT in data where data is an array of size DHT_size(). */ | ||
1585 | void DHT_save_old(DHT *dht, uint8_t *data) | ||
1586 | { | ||
1587 | memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist)); | ||
1588 | memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends); | ||
1589 | } | ||
1590 | |||
1591 | /* Load the DHT from data of size size. | ||
1592 | * | ||
1593 | * return -1 if failure. | ||
1594 | * return 0 if success. | ||
1595 | */ | ||
1596 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | ||
1597 | { | ||
1598 | size_t clientlist_oldsize = sizeof(Client_data_old) * LCLIENT_LIST; | ||
1599 | |||
1600 | if (size < clientlist_oldsize) { | ||
1601 | #ifdef DEBUG | ||
1602 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); | ||
1603 | #endif | ||
1604 | return -1; | ||
1605 | } | ||
1606 | |||
1607 | uint32_t friendlistsize = size - clientlist_oldsize; | ||
1608 | |||
1609 | if (friendlistsize % sizeof(DHT_Friend_old) != 0) { | ||
1610 | #ifdef DEBUG | ||
1611 | fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); | ||
1612 | #endif | ||
1613 | return -1; | ||
1614 | } | ||
1615 | |||
1616 | uint32_t i, j; | ||
1617 | Client_data_old *client; | ||
1618 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend_old); | ||
1619 | |||
1620 | if (friends_num != 0) { | ||
1621 | DHT_Friend_old *tempfriends_list = (DHT_Friend_old *)(data + sizeof(dht->close_clientlist)); | ||
1622 | |||
1623 | for (i = 0; i < friends_num; ++i) { | ||
1624 | DHT_addfriend(dht, tempfriends_list[i].client_id); | ||
1625 | |||
1626 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | ||
1627 | client = &tempfriends_list[i].client_list[j]; | ||
1628 | |||
1629 | if (client->assoc.timestamp != 0) | ||
1630 | getnodes(dht, client->assoc.ip_port, client->client_id, tempfriends_list[i].client_id); | ||
1631 | } | ||
1632 | } | ||
1633 | } | ||
1634 | |||
1635 | Client_data_old *tempclose_clientlist = (Client_data_old *)data; | ||
1636 | |||
1637 | for (i = 0; i < LCLIENT_LIST; ++i) { | ||
1638 | if (tempclose_clientlist[i].assoc.timestamp != 0) | ||
1639 | DHT_bootstrap(dht, tempclose_clientlist[i].assoc.ip_port, | ||
1640 | tempclose_clientlist[i].client_id ); | ||
1641 | } | ||
1642 | |||
1643 | return 0; | ||
1644 | } | ||
1645 | |||
1646 | |||
1647 | /* new DHT format for load/save, more robust and forward compatible */ | 1839 | /* new DHT format for load/save, more robust and forward compatible */ |
1648 | 1840 | ||
1649 | #define DHT_STATE_COOKIE_GLOBAL 0x159000d | 1841 | #define DHT_STATE_COOKIE_GLOBAL 0x159000d |
1650 | 1842 | ||
1651 | #define DHT_STATE_COOKIE_TYPE 0x11ce | 1843 | #define DHT_STATE_COOKIE_TYPE 0x11ce |
1652 | #define DHT_STATE_TYPE_FRIENDS 1 | ||
1653 | #define DHT_STATE_TYPE_CLIENTS 2 | ||
1654 | #define DHT_STATE_TYPE_FRIENDS_ASSOC46 3 | 1844 | #define DHT_STATE_TYPE_FRIENDS_ASSOC46 3 |
1655 | #define DHT_STATE_TYPE_CLIENTS_ASSOC46 4 | 1845 | #define DHT_STATE_TYPE_CLIENTS_ASSOC46 4 |
1656 | 1846 | ||
@@ -1722,43 +1912,6 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length, | |||
1722 | uint32_t num, i, j; | 1912 | uint32_t num, i, j; |
1723 | 1913 | ||
1724 | switch (type) { | 1914 | switch (type) { |
1725 | case DHT_STATE_TYPE_FRIENDS: | ||
1726 | if (length % sizeof(DHT_Friend_old) != 0) | ||
1727 | break; | ||
1728 | |||
1729 | { /* localize declarations */ | ||
1730 | DHT_Friend_old *friend_list = (DHT_Friend_old *)data; | ||
1731 | num = length / sizeof(DHT_Friend_old); | ||
1732 | |||
1733 | for (i = 0; i < num; ++i) { | ||
1734 | DHT_addfriend(dht, friend_list[i].client_id); | ||
1735 | |||
1736 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | ||
1737 | Client_data_old *client = &friend_list[i].client_list[j]; | ||
1738 | |||
1739 | if (client->assoc.timestamp != 0) | ||
1740 | getnodes(dht, client->assoc.ip_port, client->client_id, friend_list[i].client_id); | ||
1741 | } | ||
1742 | } | ||
1743 | } /* localize declarations */ | ||
1744 | |||
1745 | break; | ||
1746 | |||
1747 | case DHT_STATE_TYPE_CLIENTS: | ||
1748 | if ((length % sizeof(Client_data_old)) != 0) | ||
1749 | break; | ||
1750 | |||
1751 | { /* localize declarations */ | ||
1752 | num = length / sizeof(Client_data_old); | ||
1753 | Client_data_old *client_list = (Client_data_old *)data; | ||
1754 | |||
1755 | for (i = 0; i < num; ++i) | ||
1756 | if (client_list[i].assoc.timestamp != 0) | ||
1757 | DHT_bootstrap(dht, client_list[i].assoc.ip_port, client_list[i].client_id); | ||
1758 | } /* localize declarations */ | ||
1759 | |||
1760 | break; | ||
1761 | |||
1762 | case DHT_STATE_TYPE_FRIENDS_ASSOC46: | 1915 | case DHT_STATE_TYPE_FRIENDS_ASSOC46: |
1763 | if (length % sizeof(DHT_Friend) != 0) | 1916 | if (length % sizeof(DHT_Friend) != 0) |
1764 | break; | 1917 | break; |
@@ -1774,10 +1927,10 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length, | |||
1774 | Client_data *client = &friend_list[i].client_list[j]; | 1927 | Client_data *client = &friend_list[i].client_list[j]; |
1775 | 1928 | ||
1776 | if (client->assoc4.timestamp != 0) | 1929 | if (client->assoc4.timestamp != 0) |
1777 | getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id); | 1930 | getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id, NULL); |
1778 | 1931 | ||
1779 | if (client->assoc6.timestamp != 0) | 1932 | if (client->assoc6.timestamp != 0) |
1780 | getnodes(dht, client->assoc6.ip_port, client->client_id, friend_list[i].client_id); | 1933 | getnodes(dht, client->assoc6.ip_port, client->client_id, friend_list[i].client_id, NULL); |
1781 | } | 1934 | } |
1782 | } | 1935 | } |
1783 | } /* localize declarations */ | 1936 | } /* localize declarations */ |
@@ -1832,7 +1985,7 @@ int DHT_load_new(DHT *dht, uint8_t *data, uint32_t length) | |||
1832 | length - cookie_len, DHT_STATE_COOKIE_TYPE); | 1985 | length - cookie_len, DHT_STATE_COOKIE_TYPE); |
1833 | } | 1986 | } |
1834 | 1987 | ||
1835 | return DHT_load_old(dht, data, length); | 1988 | return -1; |
1836 | } | 1989 | } |
1837 | /* return 0 if we are not connected to the DHT. | 1990 | /* return 0 if we are not connected to the DHT. |
1838 | * return 1 if we are. | 1991 | * return 1 if we are. |