diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 119 |
1 files changed, 56 insertions, 63 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index c286567f..3ce2fe84 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -120,6 +120,7 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id | |||
120 | uint32_t i; | 120 | uint32_t i; |
121 | 121 | ||
122 | for (i = 0; i < length; i++) | 122 | for (i = 0; i < length; i++) |
123 | |||
123 | /* Dead nodes are considered dead (not in the list)*/ | 124 | /* Dead nodes are considered dead (not in the list)*/ |
124 | if (!is_timeout(list[i].assoc4.timestamp, KILL_NODE_TIMEOUT) || | 125 | if (!is_timeout(list[i].assoc4.timestamp, KILL_NODE_TIMEOUT) || |
125 | !is_timeout(list[i].assoc6.timestamp, KILL_NODE_TIMEOUT)) | 126 | !is_timeout(list[i].assoc6.timestamp, KILL_NODE_TIMEOUT)) |
@@ -278,6 +279,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
278 | continue; | 279 | continue; |
279 | 280 | ||
280 | IPPTsPng *ipptp = NULL; | 281 | IPPTsPng *ipptp = NULL; |
282 | |||
281 | if (sa_family == AF_INET) | 283 | if (sa_family == AF_INET) |
282 | ipptp = &client->assoc4; | 284 | ipptp = &client->assoc4; |
283 | else | 285 | else |
@@ -806,31 +808,35 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 | |||
806 | return 0; | 808 | return 0; |
807 | } | 809 | } |
808 | 810 | ||
809 | static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 811 | static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, |
812 | size_t node_format_size, uint8_t *plain, uint32_t *num_nodes_out) | ||
810 | { | 813 | { |
811 | DHT *dht = object; | 814 | DHT *dht = object; |
812 | uint64_t ping_id; | 815 | uint64_t ping_id; |
813 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | 816 | uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; |
814 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | ||
815 | 817 | ||
816 | size_t Node4_format_size = sizeof(Node4_format); | 818 | if (length <= cid_size) /* too short */ |
819 | return 1; | ||
820 | |||
821 | uint32_t data_size = length - cid_size; | ||
817 | 822 | ||
818 | if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || | 823 | if ((data_size % node_format_size) != 0) /* invalid length */ |
819 | ((length - cid_size) % Node4_format_size) != 0 || | ||
820 | (length < cid_size + Node4_format_size)) | ||
821 | return 1; | 824 | return 1; |
822 | 825 | ||
823 | uint32_t num_nodes = (length - cid_size) / Node4_format_size; | 826 | uint32_t num_nodes = data_size / node_format_size; |
824 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; | 827 | |
828 | if (num_nodes > MAX_SENT_NODES) /* too long */ | ||
829 | return 1; | ||
825 | 830 | ||
826 | int len = decrypt_data( | 831 | int len = decrypt_data( |
827 | packet + 1, | 832 | packet + 1, |
828 | dht->c->self_secret_key, | 833 | dht->c->self_secret_key, |
829 | packet + 1 + CLIENT_ID_SIZE, | 834 | packet + 1 + CLIENT_ID_SIZE, |
830 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 835 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
831 | sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain ); | 836 | sizeof(ping_id) + num_nodes * node_format_size + ENCRYPTION_PADDING, |
837 | plain); | ||
832 | 838 | ||
833 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size) | 839 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * node_format_size) |
834 | return 1; | 840 | return 1; |
835 | 841 | ||
836 | memcpy(&ping_id, plain, sizeof(ping_id)); | 842 | memcpy(&ping_id, plain, sizeof(ping_id)); |
@@ -838,78 +844,61 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
838 | if (!is_gettingnodes(dht, source, ping_id)) | 844 | if (!is_gettingnodes(dht, source, ping_id)) |
839 | return 1; | 845 | return 1; |
840 | 846 | ||
841 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
842 | Node_format nodes_list[MAX_SENT_NODES]; | ||
843 | uint32_t i, num_nodes_ok = 0; | ||
844 | |||
845 | /* blow up from Node4 (IPv4) wire format to Node (IPv4/IPv6) structure */ | ||
846 | for (i = 0; i < num_nodes; i++) | ||
847 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { | ||
848 | memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | ||
849 | nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; | ||
850 | nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
851 | nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port; | ||
852 | |||
853 | num_nodes_ok++; | ||
854 | } | ||
855 | |||
856 | if (num_nodes_ok < num_nodes) { | ||
857 | /* shouldn't happen */ | ||
858 | num_nodes = num_nodes_ok; | ||
859 | } | ||
860 | |||
861 | addto_lists(dht, source, packet + 1); | 847 | addto_lists(dht, source, packet + 1); |
862 | 848 | ||
863 | for (i = 0; i < num_nodes; ++i) { | 849 | *num_nodes_out = num_nodes; |
864 | send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); | ||
865 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | ||
866 | } | ||
867 | 850 | ||
868 | return 0; | 851 | return 0; |
869 | } | 852 | } |
870 | 853 | ||
871 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 854 | static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
872 | { | 855 | { |
873 | DHT *dht = object; | 856 | DHT *dht = object; |
874 | uint64_t ping_id; | 857 | uint64_t ping_id; |
875 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | 858 | size_t node4_format_size = sizeof(Node4_format); |
876 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | 859 | uint8_t plain[sizeof(ping_id) + node4_format_size * MAX_SENT_NODES]; |
877 | 860 | uint32_t num_nodes; | |
878 | size_t Node_format_size = sizeof(Node_format); | ||
879 | 861 | ||
880 | if (length > (cid_size + Node_format_size * MAX_SENT_NODES) || | 862 | if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, &num_nodes)) |
881 | ((length - cid_size) % Node_format_size) != 0 || | ||
882 | (length < cid_size + Node_format_size)) | ||
883 | return 1; | 863 | return 1; |
884 | 864 | ||
885 | uint32_t num_nodes = (length - cid_size) / Node_format_size; | 865 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); |
886 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; | 866 | uint32_t i; |
887 | 867 | ||
888 | int len = decrypt_data( | 868 | IP_Port ipp; |
889 | packet + 1, | 869 | ipp.ip.family = AF_INET; |
890 | dht->c->self_secret_key, | ||
891 | packet + 1 + CLIENT_ID_SIZE, | ||
892 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | ||
893 | sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING, plain ); | ||
894 | 870 | ||
895 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size) | 871 | for (i = 0; i < num_nodes; i++) |
896 | return 1; | 872 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { |
873 | ipp.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
874 | ipp.port = nodes4_list[i].ip_port.port; | ||
897 | 875 | ||
898 | memcpy(&ping_id, plain, sizeof(ping_id)); | 876 | send_ping_request(dht->ping, ipp, nodes4_list[i].client_id); |
877 | returnedip_ports(dht, ipp, nodes4_list[i].client_id, packet + 1); | ||
878 | } | ||
899 | 879 | ||
900 | if (!is_gettingnodes(dht, source, ping_id)) | 880 | return 0; |
881 | } | ||
882 | |||
883 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
884 | { | ||
885 | DHT *dht = object; | ||
886 | uint64_t ping_id; | ||
887 | size_t node_format_size = sizeof(Node_format); | ||
888 | uint8_t plain[sizeof(ping_id) + node_format_size * MAX_SENT_NODES]; | ||
889 | uint32_t num_nodes; | ||
890 | |||
891 | if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, &num_nodes)) | ||
901 | return 1; | 892 | return 1; |
902 | 893 | ||
894 | Node_format *nodes_list = (Node_format *)(plain + sizeof(ping_id)); | ||
903 | uint32_t i; | 895 | uint32_t i; |
904 | Node_format nodes_list[MAX_SENT_NODES]; | ||
905 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | ||
906 | |||
907 | addto_lists(dht, source, packet + 1); | ||
908 | 896 | ||
909 | for (i = 0; i < num_nodes; ++i) { | 897 | for (i = 0; i < num_nodes; i++) |
910 | send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); | 898 | if (ipport_isset(&nodes_list[i].ip_port)) { |
911 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | 899 | send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); |
912 | } | 900 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); |
901 | } | ||
913 | 902 | ||
914 | return 0; | 903 | return 0; |
915 | } | 904 | } |
@@ -1193,12 +1182,15 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
1193 | 1182 | ||
1194 | #ifdef FRIEND_IPLIST_PAD | 1183 | #ifdef FRIEND_IPLIST_PAD |
1195 | memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port)); | 1184 | memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port)); |
1185 | |||
1196 | if (num_ipv6s == MAX_FRIEND_CLIENTS) | 1186 | if (num_ipv6s == MAX_FRIEND_CLIENTS) |
1197 | return MAX_FRIEND_CLIENTS; | 1187 | return MAX_FRIEND_CLIENTS; |
1198 | 1188 | ||
1199 | int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s; | 1189 | int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s; |
1190 | |||
1200 | if (num_ipv4s_used > num_ipv4s) | 1191 | if (num_ipv4s_used > num_ipv4s) |
1201 | num_ipv4s_used = num_ipv4s; | 1192 | num_ipv4s_used = num_ipv4s; |
1193 | |||
1202 | memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port)); | 1194 | memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port)); |
1203 | return num_ipv6s + num_ipv4s_used; | 1195 | return num_ipv6s + num_ipv4s_used; |
1204 | 1196 | ||
@@ -1808,6 +1800,7 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length, | |||
1808 | break; | 1800 | break; |
1809 | 1801 | ||
1810 | #ifdef DEBUG | 1802 | #ifdef DEBUG |
1803 | |||
1811 | default: | 1804 | default: |
1812 | fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n", | 1805 | fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n", |
1813 | length, type); | 1806 | length, type); |