diff options
-rw-r--r-- | auto_tests/network_test.c | 5 | ||||
-rw-r--r-- | docs/updates/DHT.md | 16 | ||||
-rw-r--r-- | toxcore/DHT.c | 371 | ||||
-rw-r--r-- | toxcore/DHT.h | 31 | ||||
-rw-r--r-- | toxcore/network.h | 18 | ||||
-rw-r--r-- | toxcore/onion_announce.c | 19 | ||||
-rw-r--r-- | toxcore/onion_client.c | 58 |
7 files changed, 219 insertions, 299 deletions
diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c index 3b4b50cd..afd90e7a 100644 --- a/auto_tests/network_test.c +++ b/auto_tests/network_test.c | |||
@@ -136,9 +136,8 @@ START_TEST(test_struct_sizes) | |||
136 | { | 136 | { |
137 | ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4)); | 137 | ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4)); |
138 | ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6)); | 138 | ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6)); |
139 | ck_assert_msg(sizeof(IP) == 20, "sizeof(IP): expected result 20, got %u.", sizeof(IP)); | 139 | ck_assert_msg(sizeof(IP) == 17, "sizeof(IP): expected result 17, got %u.", sizeof(IP)); |
140 | ck_assert_msg(sizeof(IP_Port) == 24, "sizeof(IP_Port): expected result 24, got %u.", sizeof(IP_Port)); | 140 | ck_assert_msg(sizeof(IP_Port) == 19, "sizeof(IP_Port): expected result 19, got %u.", sizeof(IP_Port)); |
141 | ck_assert_msg(sizeof(IP4_Port) == 8, "sizeof(IP4_Port): expected result 8, got %u.", sizeof(IP4_Port)); | ||
142 | } | 141 | } |
143 | END_TEST | 142 | END_TEST |
144 | 143 | ||
diff --git a/docs/updates/DHT.md b/docs/updates/DHT.md index db825a3c..9e94ab11 100644 --- a/docs/updates/DHT.md +++ b/docs/updates/DHT.md | |||
@@ -79,12 +79,9 @@ Protocol | |||
79 | 79 | ||
80 | Node format: | 80 | Node format: |
81 | ``` | 81 | ``` |
82 | [char array (node_id), length=32 bytes][ip (in network byte order), length=4 bytes][port (in network byte order), length=2 bytes][Padding , length=2 bytes] | 82 | [uint8_t family (2 == IPv4, 10 == IPv6, 130 == TCP IPv4, 138 == TCP IPv6)][ip (in network byte order), length=4 bytes if ipv4, 16 bytes if ipv6][port (in network byte order), length=2 bytes][char array (node_id), length=32 bytes] |
83 | ``` | 83 | ``` |
84 | see also: DHT.h (Node4_format struct) | 84 | see also: DHT.h (pack_nodes() and unpack_nodes()) |
85 | |||
86 | IPv6 Node format: | ||
87 | see: DHT.h (Node_format struct) | ||
88 | 85 | ||
89 | Valid queries and Responses: | 86 | Valid queries and Responses: |
90 | 87 | ||
@@ -102,12 +99,7 @@ Packet contents: | |||
102 | ``` | 99 | ``` |
103 | Valid replies: a send_nodes packet | 100 | Valid replies: a send_nodes packet |
104 | 101 | ||
105 | Send_nodes (response (for ipv4 addresses)): | 102 | Send_nodes (response (for all addresses)): |
106 | ``` | ||
107 | [byte with value: 03][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=40 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] | ||
108 | ``` | ||
109 | |||
110 | Send_nodes_IPv6 (response (for ipv6 addresses)): | ||
111 | ``` | 103 | ``` |
112 | [byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in ipv6_node format, length=56 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] | 104 | [byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=?? * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] |
113 | ``` | 105 | ``` |
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 1089e2ff..98b488a2 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -179,6 +179,105 @@ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id) | |||
179 | return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id); | 179 | return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id); |
180 | } | 180 | } |
181 | 181 | ||
182 | void to_net_family(IP *ip) | ||
183 | { | ||
184 | if (ip->family == AF_INET) | ||
185 | ip->family = TOX_AF_INET; | ||
186 | else if (ip->family == AF_INET6) | ||
187 | ip->family = TOX_AF_INET6; | ||
188 | } | ||
189 | |||
190 | void to_host_family(IP *ip) | ||
191 | { | ||
192 | if (ip->family == TOX_AF_INET) | ||
193 | ip->family = AF_INET; | ||
194 | else if (ip->family == TOX_AF_INET6) | ||
195 | ip->family = AF_INET6; | ||
196 | } | ||
197 | |||
198 | /* Pack number of nodes into data of maxlength length. | ||
199 | * | ||
200 | * return length of packed nodes on success. | ||
201 | * return -1 on failure. | ||
202 | */ | ||
203 | int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number) | ||
204 | { | ||
205 | uint32_t i, packed_length = 0; | ||
206 | |||
207 | for (i = 0; i < number; ++i) { | ||
208 | if (nodes[i].ip_port.ip.family == AF_INET) { | ||
209 | uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
210 | |||
211 | if (packed_length + size > length) | ||
212 | return -1; | ||
213 | |||
214 | data[packed_length] = TOX_AF_INET; | ||
215 | memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4)); | ||
216 | memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t)); | ||
217 | memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); | ||
218 | packed_length += size; | ||
219 | } else if (nodes[i].ip_port.ip.family == AF_INET6) { | ||
220 | uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
221 | |||
222 | if (packed_length + size > length) | ||
223 | return -1; | ||
224 | |||
225 | data[packed_length] = TOX_AF_INET6; | ||
226 | memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6)); | ||
227 | memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t)); | ||
228 | memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); | ||
229 | packed_length += size; | ||
230 | } else { | ||
231 | return -1; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return packed_length; | ||
236 | } | ||
237 | |||
238 | /* Unpack data of length into nodes of size (in number of nodes). | ||
239 | * | ||
240 | * return number of unpacked nodes on success. | ||
241 | * return -1 on failure. | ||
242 | */ | ||
243 | int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length) | ||
244 | { | ||
245 | uint32_t num = 0, len_processed = 0; | ||
246 | |||
247 | while (num < size && len_processed < length) { | ||
248 | if (data[len_processed] == TOX_AF_INET) { | ||
249 | uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
250 | |||
251 | if (len_processed + size > length) | ||
252 | return -1; | ||
253 | |||
254 | nodes[num].ip_port.ip.family = AF_INET; | ||
255 | memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4)); | ||
256 | memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t)); | ||
257 | memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), CLIENT_ID_SIZE); | ||
258 | len_processed += size; | ||
259 | ++num; | ||
260 | } else if (data[len_processed] == TOX_AF_INET6) { | ||
261 | uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; | ||
262 | |||
263 | if (len_processed + size > length) | ||
264 | return -1; | ||
265 | |||
266 | nodes[num].ip_port.ip.family = AF_INET6; | ||
267 | memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6)); | ||
268 | memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t)); | ||
269 | memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), CLIENT_ID_SIZE); | ||
270 | len_processed += size; | ||
271 | ++num; | ||
272 | } else { | ||
273 | return -1; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | return num; | ||
278 | } | ||
279 | |||
280 | |||
182 | 281 | ||
183 | /* Check if client with client_id is already in list of length length. | 282 | /* Check if client with client_id is already in list of length length. |
184 | * If it is then set its corresponding timestamp to current time. | 283 | * If it is then set its corresponding timestamp to current time. |
@@ -322,15 +421,15 @@ static uint8_t hardening_correct(Hardening *h) | |||
322 | /* | 421 | /* |
323 | * helper for get_close_nodes(). argument list is a monster :D | 422 | * helper for get_close_nodes(). argument list is a monster :D |
324 | */ | 423 | */ |
325 | static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, | 424 | static void get_close_nodes_inner(uint8_t *client_id, Node_format *nodes_list, |
326 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, | 425 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, |
327 | uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) | 426 | uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) |
328 | { | 427 | { |
329 | if ((sa_family != AF_INET) && (sa_family != AF_INET6)) | 428 | if ((sa_family != AF_INET) && (sa_family != AF_INET6) && (sa_family != 0)) |
330 | return; | 429 | return; |
331 | 430 | ||
332 | uint32_t num_nodes = *num_nodes_ptr; | 431 | uint32_t num_nodes = *num_nodes_ptr; |
333 | int ipv46x, j, closest; | 432 | int j, closest; |
334 | uint32_t i; | 433 | uint32_t i; |
335 | 434 | ||
336 | for (i = 0; i < client_list_length; i++) { | 435 | for (i = 0; i < client_list_length; i++) { |
@@ -342,39 +441,22 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
342 | 441 | ||
343 | IPPTsPng *ipptp = NULL; | 442 | IPPTsPng *ipptp = NULL; |
344 | 443 | ||
345 | if (sa_family == AF_INET) | 444 | if (sa_family == AF_INET) { |
346 | ipptp = &client->assoc4; | 445 | ipptp = &client->assoc4; |
347 | else | 446 | } else if (sa_family == AF_INET6) { |
348 | ipptp = &client->assoc6; | 447 | ipptp = &client->assoc6; |
448 | } else { | ||
449 | if (client->assoc4.timestamp >= client->assoc6.timestamp) { | ||
450 | ipptp = &client->assoc4; | ||
451 | } else { | ||
452 | ipptp = &client->assoc6; | ||
453 | } | ||
454 | } | ||
349 | 455 | ||
350 | /* node not in a good condition? */ | 456 | /* node not in a good condition? */ |
351 | if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) | 457 | if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) |
352 | continue; | 458 | continue; |
353 | 459 | ||
354 | IP *client_ip = &ipptp->ip_port.ip; | ||
355 | |||
356 | /* | ||
357 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for | ||
358 | * our connections, instead we have to look if it is an embedded | ||
359 | * IPv4-in-IPv6 here and convert it down in sendnodes(). | ||
360 | */ | ||
361 | sa_family_t ip_treat_as_family = client_ip->family; | ||
362 | |||
363 | if ((dht->net->family == AF_INET6) && | ||
364 | (client_ip->family == AF_INET6)) { | ||
365 | /* socket is AF_INET6, address claims AF_INET6: | ||
366 | * check for embedded IPv4-in-IPv6 (shouldn't happen anymore, | ||
367 | * all storing functions should already convert down to IPv4) */ | ||
368 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) | ||
369 | ip_treat_as_family = AF_INET; | ||
370 | } | ||
371 | |||
372 | ipv46x = !(sa_family == ip_treat_as_family); | ||
373 | |||
374 | /* node address of the wrong family? */ | ||
375 | if (ipv46x) | ||
376 | continue; | ||
377 | |||
378 | /* don't send LAN ips to non LAN peers */ | 460 | /* don't send LAN ips to non LAN peers */ |
379 | if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) | 461 | if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) |
380 | continue; | 462 | continue; |
@@ -428,7 +510,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n | |||
428 | uint8_t is_LAN, uint8_t want_good) | 510 | uint8_t is_LAN, uint8_t want_good) |
429 | { | 511 | { |
430 | uint32_t num_nodes = 0, i; | 512 | uint32_t num_nodes = 0, i; |
431 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, | 513 | get_close_nodes_inner(client_id, nodes_list, sa_family, |
432 | dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good); | 514 | dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good); |
433 | 515 | ||
434 | /*TODO uncomment this when hardening is added to close friend clients | 516 | /*TODO uncomment this when hardening is added to close friend clients |
@@ -438,7 +520,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n | |||
438 | &num_nodes, is_LAN, want_good); | 520 | &num_nodes, is_LAN, want_good); |
439 | */ | 521 | */ |
440 | for (i = 0; i < dht->num_friends; ++i) | 522 | for (i = 0; i < dht->num_friends; ++i) |
441 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, | 523 | get_close_nodes_inner(client_id, nodes_list, sa_family, |
442 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, | 524 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, |
443 | &num_nodes, is_LAN, 0); | 525 | &num_nodes, is_LAN, 0); |
444 | 526 | ||
@@ -456,6 +538,7 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa | |||
456 | return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); | 538 | return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); |
457 | 539 | ||
458 | #ifdef ENABLE_ASSOC_DHT | 540 | #ifdef ENABLE_ASSOC_DHT |
541 | //TODO: assoc, sa_family 0 (don't care if ipv4 or ipv6) support. | ||
459 | Client_data *result[MAX_SENT_NODES]; | 542 | Client_data *result[MAX_SENT_NODES]; |
460 | 543 | ||
461 | Assoc_close_entries request; | 544 | Assoc_close_entries request; |
@@ -907,95 +990,6 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
907 | return sendpacket(dht->net, ip_port, data, sizeof(data)); | 990 | return sendpacket(dht->net, ip_port, data, sizeof(data)); |
908 | } | 991 | } |
909 | 992 | ||
910 | /* Send a send nodes response. */ | ||
911 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, | ||
912 | * IPv6 nodes are sent in a different message | ||
913 | * encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */ | ||
914 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, | ||
915 | uint8_t *shared_encryption_key) | ||
916 | { | ||
917 | /* Check if packet is going to be sent to ourself. */ | ||
918 | if (id_equal(public_key, dht->self_public_key)) | ||
919 | return -1; | ||
920 | |||
921 | size_t Node4_format_size = sizeof(Node4_format); | ||
922 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES | ||
923 | + Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | ||
924 | |||
925 | Node_format nodes_list[MAX_SENT_NODES]; | ||
926 | uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET, LAN_ip(ip_port.ip) == 0, 1); | ||
927 | |||
928 | if (num_nodes == 0) | ||
929 | return 0; | ||
930 | |||
931 | uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
932 | uint8_t encrypt[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | ||
933 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
934 | new_nonce(nonce); | ||
935 | |||
936 | Node4_format *nodes4_list = (Node4_format *)(plain); | ||
937 | uint32_t i, num_nodes_ok = 0; | ||
938 | |||
939 | for (i = 0; i < num_nodes; i++) { | ||
940 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); | ||
941 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; | ||
942 | |||
943 | IP *node_ip = &nodes_list[i].ip_port.ip; | ||
944 | |||
945 | if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6.in6_addr)) | ||
946 | /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ | ||
947 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.uint32[3]; | ||
948 | else if (node_ip->family == AF_INET) | ||
949 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32; | ||
950 | else /* shouldn't happen */ | ||
951 | continue; | ||
952 | |||
953 | num_nodes_ok++; | ||
954 | } | ||
955 | |||
956 | if (num_nodes_ok < num_nodes) { | ||
957 | /* shouldn't happen */ | ||
958 | num_nodes = num_nodes_ok; | ||
959 | } | ||
960 | |||
961 | memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); | ||
962 | int len = encrypt_data_fast( shared_encryption_key, | ||
963 | nonce, | ||
964 | plain, | ||
965 | num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, | ||
966 | encrypt ); | ||
967 | |||
968 | if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + | ||
969 | crypto_box_MACBYTES) | ||
970 | return -1; | ||
971 | |||
972 | data[0] = NET_PACKET_SEND_NODES; | ||
973 | memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); | ||
974 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | ||
975 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | ||
976 | |||
977 | return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); | ||
978 | } | ||
979 | |||
980 | void to_net_family(IP *ip) | ||
981 | { | ||
982 | ip->padding[0] = 0; | ||
983 | ip->padding[1] = 0; | ||
984 | ip->padding[2] = 0; | ||
985 | |||
986 | if (ip->family == AF_INET) | ||
987 | ip->family = TOX_AF_INET; | ||
988 | else if (ip->family == AF_INET6) | ||
989 | ip->family = TOX_AF_INET6; | ||
990 | } | ||
991 | |||
992 | void to_host_family(IP *ip) | ||
993 | { | ||
994 | if (ip->family == TOX_AF_INET) | ||
995 | ip->family = AF_INET; | ||
996 | else if (ip->family == TOX_AF_INET6) | ||
997 | ip->family = AF_INET6; | ||
998 | } | ||
999 | /* Send a send nodes response: message for IPv6 nodes */ | 993 | /* Send a send nodes response: message for IPv6 nodes */ |
1000 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, | 994 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, |
1001 | uint8_t *shared_encryption_key) | 995 | uint8_t *shared_encryption_key) |
@@ -1009,7 +1003,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ | |||
1009 | + Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; | 1003 | + Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; |
1010 | 1004 | ||
1011 | Node_format nodes_list[MAX_SENT_NODES]; | 1005 | Node_format nodes_list[MAX_SENT_NODES]; |
1012 | uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6, LAN_ip(ip_port.ip) == 0, 1); | 1006 | uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1); |
1013 | 1007 | ||
1014 | if (num_nodes == 0) | 1008 | if (num_nodes == 0) |
1015 | return 0; | 1009 | return 0; |
@@ -1019,20 +1013,19 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ | |||
1019 | uint8_t nonce[crypto_box_NONCEBYTES]; | 1013 | uint8_t nonce[crypto_box_NONCEBYTES]; |
1020 | new_nonce(nonce); | 1014 | new_nonce(nonce); |
1021 | 1015 | ||
1022 | uint32_t i; | 1016 | int nodes_length = pack_nodes(plain, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes); |
1023 | 1017 | ||
1024 | for (i = 0; i < num_nodes; ++i) | 1018 | if (nodes_length <= 0) |
1025 | to_net_family(&nodes_list[i].ip_port.ip); | 1019 | return -1; |
1026 | 1020 | ||
1027 | memcpy(plain, nodes_list, num_nodes * Node_format_size); | 1021 | memcpy(plain + nodes_length, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); |
1028 | memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); | ||
1029 | int len = encrypt_data_fast( shared_encryption_key, | 1022 | int len = encrypt_data_fast( shared_encryption_key, |
1030 | nonce, | 1023 | nonce, |
1031 | plain, | 1024 | plain, |
1032 | num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, | 1025 | nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH, |
1033 | encrypt ); | 1026 | encrypt ); |
1034 | 1027 | ||
1035 | if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) | 1028 | if ((unsigned int)len != nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) |
1036 | return -1; | 1029 | return -1; |
1037 | 1030 | ||
1038 | data[0] = NET_PACKET_SEND_NODES_IPV6; | 1031 | data[0] = NET_PACKET_SEND_NODES_IPV6; |
@@ -1068,12 +1061,9 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 | |||
1068 | if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) | 1061 | if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) |
1069 | return 1; | 1062 | return 1; |
1070 | 1063 | ||
1071 | sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key); | 1064 | sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key); |
1072 | sendnodes_ipv6(dht, source, packet + 1, plain, | ||
1073 | plain + CLIENT_ID_SIZE, shared_key); /* TODO: prevent possible amplification attacks */ | ||
1074 | 1065 | ||
1075 | add_to_ping(dht->ping, packet + 1, source); | 1066 | add_to_ping(dht->ping, packet + 1, source); |
1076 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ | ||
1077 | 1067 | ||
1078 | return 0; | 1068 | return 0; |
1079 | } | 1069 | } |
@@ -1108,15 +1098,12 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i | |||
1108 | } | 1098 | } |
1109 | 1099 | ||
1110 | /* Function is needed in following functions. */ | 1100 | /* Function is needed in following functions. */ |
1111 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, | 1101 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data, |
1112 | uint16_t num_nodes); | 1102 | uint16_t nodes_data_length); |
1113 | 1103 | ||
1114 | static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, | 1104 | static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, |
1115 | size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node) | 1105 | Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) |
1116 | { | 1106 | { |
1117 | if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) | ||
1118 | return 1; | ||
1119 | |||
1120 | DHT *dht = object; | 1107 | DHT *dht = object; |
1121 | uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES; | 1108 | uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES; |
1122 | 1109 | ||
@@ -1125,107 +1112,62 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, | |||
1125 | 1112 | ||
1126 | uint32_t data_size = length - cid_size; | 1113 | uint32_t data_size = length - cid_size; |
1127 | 1114 | ||
1128 | if ((data_size % node_format_size) != 0) /* invalid length */ | 1115 | if (data_size == 0) |
1129 | return 1; | 1116 | return 1; |
1130 | 1117 | ||
1131 | uint32_t num_nodes = data_size / node_format_size; | 1118 | if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */ |
1132 | |||
1133 | if (num_nodes > MAX_SENT_NODES) /* too long */ | ||
1134 | return 1; | 1119 | return 1; |
1135 | 1120 | ||
1121 | uint8_t plain[data_size + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
1136 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 1122 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
1137 | DHT_get_shared_key_sent(dht, shared_key, packet + 1); | 1123 | DHT_get_shared_key_sent(dht, shared_key, packet + 1); |
1138 | int len = decrypt_data_fast( | 1124 | int len = decrypt_data_fast( |
1139 | shared_key, | 1125 | shared_key, |
1140 | packet + 1 + CLIENT_ID_SIZE, | 1126 | packet + 1 + CLIENT_ID_SIZE, |
1141 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 1127 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
1142 | num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, | 1128 | data_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, |
1143 | plain); | 1129 | plain); |
1144 | 1130 | ||
1145 | if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) | 1131 | if ((unsigned int)len != sizeof(plain)) |
1146 | return 1; | ||
1147 | |||
1148 | if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node)) | ||
1149 | return 1; | 1132 | return 1; |
1150 | 1133 | ||
1151 | /* store the address the *request* was sent to */ | ||
1152 | addto_lists(dht, source, packet + 1); | ||
1153 | |||
1154 | *num_nodes_out = num_nodes; | ||
1155 | |||
1156 | return 0; | ||
1157 | } | ||
1158 | |||
1159 | static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
1160 | { | ||
1161 | DHT *dht = object; | ||
1162 | size_t node4_format_size = sizeof(Node4_format); | ||
1163 | uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
1164 | uint32_t num_nodes; | ||
1165 | |||
1166 | Node_format sendback_node; | 1134 | Node_format sendback_node; |
1167 | 1135 | ||
1168 | if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes, | 1136 | if (!sent_getnode_to_node(dht, packet + 1, source, plain + data_size, &sendback_node)) |
1169 | &sendback_node)) | ||
1170 | return 1; | 1137 | return 1; |
1171 | 1138 | ||
1172 | if (num_nodes == 0) | 1139 | int num_nodes = unpack_nodes(plain_nodes, size_plain_nodes, plain, data_size); |
1173 | return 0; | ||
1174 | |||
1175 | Node4_format *nodes4_list = (Node4_format *)(plain); | ||
1176 | |||
1177 | uint64_t time_now = unix_time(); | ||
1178 | IPPTs ippts; | ||
1179 | ippts.ip_port.ip.family = AF_INET; | ||
1180 | ippts.timestamp = time_now; | ||
1181 | |||
1182 | uint32_t i; | ||
1183 | |||
1184 | Node_format nodes_list[MAX_SENT_NODES]; | ||
1185 | |||
1186 | for (i = 0; i < num_nodes; i++) | ||
1187 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { | ||
1188 | ippts.ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
1189 | ippts.ip_port.port = nodes4_list[i].ip_port.port; | ||
1190 | 1140 | ||
1191 | send_ping_request(dht->ping, ippts.ip_port, nodes4_list[i].client_id); | 1141 | if (num_nodes <= 0) |
1192 | returnedip_ports(dht, ippts.ip_port, nodes4_list[i].client_id, packet + 1); | 1142 | return 1; |
1193 | 1143 | ||
1194 | memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | 1144 | /* store the address the *request* was sent to */ |
1195 | ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port); | 1145 | addto_lists(dht, source, packet + 1); |
1196 | 1146 | ||
1197 | } | 1147 | *num_nodes_out = num_nodes; |
1198 | 1148 | ||
1199 | send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes); | 1149 | send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain, data_size); |
1200 | return 0; | 1150 | return 0; |
1201 | } | 1151 | } |
1202 | 1152 | ||
1203 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 1153 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
1204 | { | 1154 | { |
1205 | DHT *dht = object; | 1155 | DHT *dht = object; |
1206 | size_t node_format_size = sizeof(Node_format); | 1156 | Node_format plain_nodes[MAX_SENT_NODES]; |
1207 | uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; | ||
1208 | uint32_t num_nodes; | 1157 | uint32_t num_nodes; |
1209 | 1158 | ||
1210 | Node_format sendback_node; | 1159 | if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) |
1211 | |||
1212 | if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes, | ||
1213 | &sendback_node)) | ||
1214 | return 1; | 1160 | return 1; |
1215 | 1161 | ||
1216 | if (num_nodes == 0) | 1162 | if (num_nodes == 0) |
1217 | return 0; | 1163 | return 0; |
1218 | 1164 | ||
1219 | Node_format *nodes_list = (Node_format *)(plain); | ||
1220 | uint32_t i; | 1165 | uint32_t i; |
1221 | send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes); | ||
1222 | 1166 | ||
1223 | for (i = 0; i < num_nodes; i++) { | 1167 | for (i = 0; i < num_nodes; i++) { |
1224 | to_host_family(&nodes_list[i].ip_port.ip); | 1168 | if (ipport_isset(&plain_nodes[i].ip_port)) { |
1225 | 1169 | send_ping_request(dht->ping, plain_nodes[i].ip_port, plain_nodes[i].client_id); | |
1226 | if (ipport_isset(&nodes_list[i].ip_port)) { | 1170 | returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].client_id, packet + 1); |
1227 | send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); | ||
1228 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | ||
1229 | } | 1171 | } |
1230 | } | 1172 | } |
1231 | 1173 | ||
@@ -1977,17 +1919,17 @@ static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format * | |||
1977 | } | 1919 | } |
1978 | 1920 | ||
1979 | /* Send a get node hardening response */ | 1921 | /* Send a get node hardening response */ |
1980 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, | 1922 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data, |
1981 | uint16_t num_nodes) | 1923 | uint16_t nodes_data_length) |
1982 | { | 1924 | { |
1983 | if (!ip_isset(&sendto->ip_port.ip)) | 1925 | if (!ip_isset(&sendto->ip_port.ip)) |
1984 | return -1; | 1926 | return -1; |
1985 | 1927 | ||
1986 | uint8_t packet[MAX_DATA_SIZE]; | 1928 | uint8_t packet[MAX_DATA_SIZE]; |
1987 | uint8_t data[1 + CLIENT_ID_SIZE + num_nodes * sizeof(Node_format)]; | 1929 | uint8_t data[1 + CLIENT_ID_SIZE + nodes_data_length]; |
1988 | data[0] = CHECK_TYPE_GETNODE_RES; | 1930 | data[0] = CHECK_TYPE_GETNODE_RES; |
1989 | memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); | 1931 | memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); |
1990 | memcpy(data + 1 + CLIENT_ID_SIZE, list, num_nodes * sizeof(Node_format)); | 1932 | memcpy(data + 1 + CLIENT_ID_SIZE, nodes_data, nodes_data_length); |
1991 | int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, | 1933 | int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, |
1992 | sizeof(data), CRYPTO_PACKET_HARDENING); | 1934 | sizeof(data), CRYPTO_PACKET_HARDENING); |
1993 | 1935 | ||
@@ -2075,28 +2017,22 @@ static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey | |||
2075 | if (length <= CLIENT_ID_SIZE + 1) | 2017 | if (length <= CLIENT_ID_SIZE + 1) |
2076 | return 1; | 2018 | return 1; |
2077 | 2019 | ||
2078 | if ((length - 1 - CLIENT_ID_SIZE) % sizeof(Node_format) != 0) | 2020 | if (length > 1 + CLIENT_ID_SIZE + sizeof(Node_format) * MAX_SENT_NODES) |
2079 | return 1; | 2021 | return 1; |
2080 | 2022 | ||
2081 | uint16_t num = (length - 1 - CLIENT_ID_SIZE) / sizeof(Node_format); | 2023 | uint16_t length_nodes = length - 1 - CLIENT_ID_SIZE; |
2024 | Node_format nodes[MAX_SENT_NODES]; | ||
2025 | int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, packet + 1 + CLIENT_ID_SIZE, length_nodes); | ||
2082 | 2026 | ||
2083 | /* TODO: MAX_SENT_NODES nodes should be returned at all times | 2027 | /* TODO: MAX_SENT_NODES nodes should be returned at all times |
2084 | (right now we have a small network size so it could cause problems for testing and etc..) */ | 2028 | (right now we have a small network size so it could cause problems for testing and etc..) */ |
2085 | if (num > MAX_SENT_NODES || num == 0) | 2029 | if (num_nodes <= 0) |
2086 | return 1; | 2030 | return 1; |
2087 | 2031 | ||
2088 | Node_format nodes[num]; | ||
2089 | memcpy(nodes, packet + 1 + CLIENT_ID_SIZE, sizeof(Node_format)*num); | ||
2090 | uint32_t i; | ||
2091 | |||
2092 | for (i = 0; i < num; ++i) | ||
2093 | to_host_family(&nodes[i].ip_port.ip); | ||
2094 | |||
2095 | /* NOTE: This should work for now but should be changed to something better. */ | 2032 | /* NOTE: This should work for now but should be changed to something better. */ |
2096 | if (have_nodes_closelist(dht, nodes, num) < (uint32_t)((num + 2) / 2)) | 2033 | if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) |
2097 | return 1; | 2034 | return 1; |
2098 | 2035 | ||
2099 | |||
2100 | IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); | 2036 | IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); |
2101 | 2037 | ||
2102 | if (temp == NULL) | 2038 | if (temp == NULL) |
@@ -2329,7 +2265,6 @@ DHT *new_DHT(Net_Crypto *c) | |||
2329 | } | 2265 | } |
2330 | 2266 | ||
2331 | networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); | 2267 | networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); |
2332 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); | ||
2333 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); | 2268 | networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); |
2334 | init_cryptopackets(dht); | 2269 | init_cryptopackets(dht); |
2335 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); | 2270 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); |
diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 3d2722f8..73c44e9b 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h | |||
@@ -52,6 +52,8 @@ | |||
52 | /* Redefinitions of variables for safe transfer over wire. */ | 52 | /* Redefinitions of variables for safe transfer over wire. */ |
53 | #define TOX_AF_INET 2 | 53 | #define TOX_AF_INET 2 |
54 | #define TOX_AF_INET6 10 | 54 | #define TOX_AF_INET6 10 |
55 | #define TOX_TCP_INET 130 | ||
56 | #define TOX_TCP_INET6 138 | ||
55 | 57 | ||
56 | /* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */ | 58 | /* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */ |
57 | #define DHT_FAKE_FRIEND_NUMBER 4 | 59 | #define DHT_FAKE_FRIEND_NUMBER 4 |
@@ -128,16 +130,27 @@ typedef struct { | |||
128 | NAT nat; | 130 | NAT nat; |
129 | } DHT_Friend; | 131 | } DHT_Friend; |
130 | 132 | ||
131 | /* this must be kept even if IP_Port is expanded: wire compatibility */ | 133 | typedef struct __attribute__ ((__packed__)) |
132 | typedef struct { | 134 | { |
133 | uint8_t client_id[CLIENT_ID_SIZE]; | ||
134 | IP4_Port ip_port; | ||
135 | } Node4_format; | ||
136 | |||
137 | typedef struct { | ||
138 | uint8_t client_id[CLIENT_ID_SIZE]; | 135 | uint8_t client_id[CLIENT_ID_SIZE]; |
139 | IP_Port ip_port; | 136 | IP_Port ip_port; |
140 | } Node_format; | 137 | } |
138 | Node_format; | ||
139 | |||
140 | /* Pack number of nodes into data of maxlength length. | ||
141 | * | ||
142 | * return length of packed nodes on success. | ||
143 | * return -1 on failure. | ||
144 | */ | ||
145 | int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number); | ||
146 | |||
147 | /* Unpack data of length into nodes of size (in number of nodes). | ||
148 | * | ||
149 | * return number of unpacked nodes on success. | ||
150 | * return -1 on failure. | ||
151 | */ | ||
152 | int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length); | ||
153 | |||
141 | 154 | ||
142 | /*----------------------------------------------------------------------------------*/ | 155 | /*----------------------------------------------------------------------------------*/ |
143 | /* struct to store some shared keys so we don't have to regenerate them for each request. */ | 156 | /* struct to store some shared keys so we don't have to regenerate them for each request. */ |
@@ -251,7 +264,7 @@ int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2); | |||
251 | /* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know | 264 | /* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know |
252 | * and put them in nodes_list (must be MAX_SENT_NODES big). | 265 | * and put them in nodes_list (must be MAX_SENT_NODES big). |
253 | * | 266 | * |
254 | * sa_family = family (IPv4 or IPv6)? | 267 | * sa_family = family (IPv4 or IPv6) (0 if we don't care)? |
255 | * is_LAN = return some LAN ips (true or false) | 268 | * is_LAN = return some LAN ips (true or false) |
256 | * want_good = do we want tested nodes or not? (TODO) | 269 | * want_good = do we want tested nodes or not? (TODO) |
257 | * | 270 | * |
diff --git a/toxcore/network.h b/toxcore/network.h index ef040bf3..4fca795b 100644 --- a/toxcore/network.h +++ b/toxcore/network.h | |||
@@ -161,9 +161,6 @@ typedef int sock_t; | |||
161 | #define TOX_PORTRANGE_TO 33545 | 161 | #define TOX_PORTRANGE_TO 33545 |
162 | #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM | 162 | #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM |
163 | 163 | ||
164 | |||
165 | /* TODO: remove padding bytes next time we need to break compatibility with old versions of core. */ | ||
166 | |||
167 | typedef union __attribute__ ((__packed__)) | 164 | typedef union __attribute__ ((__packed__)) |
168 | { | 165 | { |
169 | uint8_t uint8[4]; | 166 | uint8_t uint8[4]; |
@@ -186,8 +183,6 @@ IP6; | |||
186 | typedef struct __attribute__ ((__packed__)) | 183 | typedef struct __attribute__ ((__packed__)) |
187 | { | 184 | { |
188 | uint8_t family; | 185 | uint8_t family; |
189 | /* Not used for anything right now. */ | ||
190 | uint8_t padding[3]; | ||
191 | union { | 186 | union { |
192 | IP4 ip4; | 187 | IP4 ip4; |
193 | IP6 ip6; | 188 | IP6 ip6; |
@@ -195,22 +190,9 @@ typedef struct __attribute__ ((__packed__)) | |||
195 | } | 190 | } |
196 | IP; | 191 | IP; |
197 | 192 | ||
198 | typedef union __attribute__ ((__packed__)) | ||
199 | { | ||
200 | struct { | ||
201 | IP4 ip; | ||
202 | uint16_t port; | ||
203 | /* Not used for anything right now. */ | ||
204 | uint16_t padding; | ||
205 | }; | ||
206 | uint8_t uint8[8]; | ||
207 | } | ||
208 | IP4_Port; | ||
209 | |||
210 | typedef struct __attribute__ ((__packed__)) IP_Port { | 193 | typedef struct __attribute__ ((__packed__)) IP_Port { |
211 | IP ip; | 194 | IP ip; |
212 | uint16_t port; | 195 | uint16_t port; |
213 | uint16_t padding; | ||
214 | } IP_Port; | 196 | } IP_Port; |
215 | 197 | ||
216 | #define TOX_ENABLE_IPV6_DEFAULT 1 | 198 | #define TOX_ENABLE_IPV6_DEFAULT 1 |
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 331e54d8..a1e5495e 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c | |||
@@ -247,14 +247,8 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet | |||
247 | 247 | ||
248 | /*Respond with a announce response packet*/ | 248 | /*Respond with a announce response packet*/ |
249 | Node_format nodes_list[MAX_SENT_NODES]; | 249 | Node_format nodes_list[MAX_SENT_NODES]; |
250 | uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family, | 250 | uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0, LAN_ip(source.ip) == 0, |
251 | LAN_ip(source.ip) == 0, 1); | 251 | 1); |
252 | |||
253 | uint32_t i; | ||
254 | |||
255 | for (i = 0; i < num_nodes; ++i) | ||
256 | to_net_family(&nodes_list[i].ip_port.ip); | ||
257 | |||
258 | uint8_t nonce[crypto_box_NONCEBYTES]; | 252 | uint8_t nonce[crypto_box_NONCEBYTES]; |
259 | random_nonce(nonce); | 253 | random_nonce(nonce); |
260 | 254 | ||
@@ -274,13 +268,16 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet | |||
274 | } | 268 | } |
275 | } | 269 | } |
276 | 270 | ||
277 | memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format)); | 271 | int nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes); |
272 | |||
273 | if (nodes_length <= 0) | ||
274 | return 1; | ||
278 | 275 | ||
279 | uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; | 276 | uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; |
280 | len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format), | 277 | len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, |
281 | data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); | 278 | data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); |
282 | 279 | ||
283 | if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES) | 280 | if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES) |
284 | return 1; | 281 | return 1; |
285 | 282 | ||
286 | data[0] = NET_PACKET_ANNOUNCE_RESPONSE; | 283 | data[0] = NET_PACKET_ANNOUNCE_RESPONSE; |
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 329b1d13..439a80c7 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c | |||
@@ -345,8 +345,6 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n | |||
345 | if (*ping_nodes_sent_second > MAX_PING_NODES_SECOND_PEER) | 345 | if (*ping_nodes_sent_second > MAX_PING_NODES_SECOND_PEER) |
346 | return 0; | 346 | return 0; |
347 | 347 | ||
348 | to_host_family(&nodes[i].ip_port.ip); | ||
349 | |||
350 | if (!lan_ips_accepted) | 348 | if (!lan_ips_accepted) |
351 | if (LAN_ip(nodes[i].ip_port.ip) == 0) | 349 | if (LAN_ip(nodes[i].ip_port.ip) == 0) |
352 | continue; | 350 | continue; |
@@ -377,10 +375,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe | |||
377 | if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) | 375 | if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) |
378 | return 1; | 376 | return 1; |
379 | 377 | ||
380 | if ((length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) % sizeof(Node_format) != 0) | 378 | uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE; |
381 | return 1; | ||
382 | |||
383 | uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format); | ||
384 | 379 | ||
385 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 380 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; |
386 | IP_Port ip_port; | 381 | IP_Port ip_port; |
@@ -389,7 +384,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe | |||
389 | if (num > onion_c->num_friends) | 384 | if (num > onion_c->num_friends) |
390 | return 1; | 385 | return 1; |
391 | 386 | ||
392 | uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)]; | 387 | uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes]; |
393 | int len = -1; | 388 | int len = -1; |
394 | 389 | ||
395 | if (num == 0) { | 390 | if (num == 0) { |
@@ -409,15 +404,19 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe | |||
409 | if ((uint32_t)len != sizeof(plain)) | 404 | if ((uint32_t)len != sizeof(plain)) |
410 | return 1; | 405 | return 1; |
411 | 406 | ||
412 | |||
413 | if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1) | 407 | if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1) |
414 | return 1; | 408 | return 1; |
415 | 409 | ||
416 | Node_format nodes[MAX_SENT_NODES]; | 410 | if (len_nodes != 0) { |
417 | memcpy(nodes, plain + 1 + ONION_PING_ID_SIZE, num_nodes * sizeof(Node_format)); | 411 | Node_format nodes[MAX_SENT_NODES]; |
412 | int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, plain + 1 + ONION_PING_ID_SIZE, len_nodes); | ||
418 | 413 | ||
419 | if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) | 414 | if (num_nodes <= 0) |
420 | return 1; | 415 | return 1; |
416 | |||
417 | if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) | ||
418 | return 1; | ||
419 | } | ||
421 | 420 | ||
422 | return 0; | 421 | return 0; |
423 | } | 422 | } |
@@ -469,9 +468,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t | |||
469 | if (length > FAKEID_DATA_MAX_LENGTH) | 468 | if (length > FAKEID_DATA_MAX_LENGTH) |
470 | return 1; | 469 | return 1; |
471 | 470 | ||
472 | if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0) | ||
473 | return 1; | ||
474 | |||
475 | int friend_num = onion_friend_num(onion_c, source_pubkey); | 471 | int friend_num = onion_friend_num(onion_c, source_pubkey); |
476 | 472 | ||
477 | if (friend_num == -1) | 473 | if (friend_num == -1) |
@@ -500,14 +496,20 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t | |||
500 | memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); | 496 | memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); |
501 | } | 497 | } |
502 | 498 | ||
503 | uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format); | 499 | uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH; |
504 | Node_format nodes[num_nodes]; | ||
505 | memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes)); | ||
506 | uint32_t i; | ||
507 | 500 | ||
508 | for (i = 0; i < num_nodes; ++i) { | 501 | if (len_nodes != 0) { |
509 | to_host_family(&nodes[i].ip_port.ip); | 502 | Node_format nodes[MAX_SENT_NODES]; |
510 | DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); | 503 | int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, len_nodes); |
504 | |||
505 | if (num_nodes <= 0) | ||
506 | return 1; | ||
507 | |||
508 | int i; | ||
509 | |||
510 | for (i = 0; i < num_nodes; ++i) { | ||
511 | DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); | ||
512 | } | ||
511 | } | 513 | } |
512 | 514 | ||
513 | return 0; | 515 | return 0; |
@@ -658,19 +660,19 @@ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint | |||
658 | memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); | 660 | memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); |
659 | Node_format nodes[MAX_SENT_NODES]; | 661 | Node_format nodes[MAX_SENT_NODES]; |
660 | uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES); | 662 | uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES); |
661 | uint32_t i; | 663 | int nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes, |
664 | num_nodes); | ||
662 | 665 | ||
663 | for (i = 0; i < num_nodes; ++i) | 666 | if (nodes_len <= 0) |
664 | to_net_family(&nodes[i].ip_port.ip); | 667 | return -1; |
665 | 668 | ||
666 | memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes); | ||
667 | int num1 = -1, num2 = -1; | 669 | int num1 = -1, num2 = -1; |
668 | 670 | ||
669 | if (onion_dht_both != 1) | 671 | if (onion_dht_both != 1) |
670 | num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); | 672 | num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); |
671 | 673 | ||
672 | if (onion_dht_both != 0) | 674 | if (onion_dht_both != 0) |
673 | num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); | 675 | num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); |
674 | 676 | ||
675 | if (num1 == -1) | 677 | if (num1 == -1) |
676 | return num2; | 678 | return num2; |