diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 479 |
1 files changed, 351 insertions, 128 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index fcd15686..1b2af12c 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -28,8 +28,10 @@ | |||
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #include "DHT.h" | 30 | #include "DHT.h" |
31 | #include "network.h" | ||
31 | #include "ping.h" | 32 | #include "ping.h" |
32 | #include "misc_tools.h" | 33 | #include "misc_tools.h" |
34 | #include "util.h" | ||
33 | 35 | ||
34 | /* The number of seconds for a non responsive node to become bad. */ | 36 | /* The number of seconds for a non responsive node to become bad. */ |
35 | #define BAD_NODE_TIMEOUT 70 | 37 | #define BAD_NODE_TIMEOUT 70 |
@@ -115,11 +117,6 @@ static int client_id_cmp(ClientPair p1, ClientPair p2) | |||
115 | return c; | 117 | return c; |
116 | } | 118 | } |
117 | 119 | ||
118 | static int ipport_equal(IP_Port a, IP_Port b) | ||
119 | { | ||
120 | return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port); | ||
121 | } | ||
122 | |||
123 | static int id_equal(uint8_t *a, uint8_t *b) | 120 | static int id_equal(uint8_t *a, uint8_t *b) |
124 | { | 121 | { |
125 | return memcmp(a, b, CLIENT_ID_SIZE) == 0; | 122 | return memcmp(a, b, CLIENT_ID_SIZE) == 0; |
@@ -142,20 +139,23 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id | |||
142 | uint32_t i; | 139 | uint32_t i; |
143 | uint64_t temp_time = unix_time(); | 140 | uint64_t temp_time = unix_time(); |
144 | 141 | ||
145 | for (i = 0; i < length; ++i) { | 142 | /* if client_id is in list, find it and maybe overwrite ip_port */ |
146 | /* If ip_port is assigned to a different client_id replace it */ | 143 | for (i = 0; i < length; ++i) |
147 | if (ipport_equal(list[i].ip_port, ip_port)) { | 144 | if (id_equal(list[i].client_id, client_id)) { |
148 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 145 | /* Refresh the client timestamp. */ |
146 | list[i].timestamp = temp_time; | ||
147 | list[i].ip_port = ip_port; | ||
148 | return 1; | ||
149 | } | 149 | } |
150 | 150 | ||
151 | if (id_equal(list[i].client_id, client_id)) { | 151 | /* client_id not in list yet: find ip_port to overwrite */ |
152 | for (i = 0; i < length; ++i) | ||
153 | if (ipport_equal(&list[i].ip_port, &ip_port)) { | ||
152 | /* Refresh the client timestamp. */ | 154 | /* Refresh the client timestamp. */ |
153 | list[i].timestamp = temp_time; | 155 | list[i].timestamp = temp_time; |
154 | list[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 156 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
155 | list[i].ip_port.port = ip_port.port; | ||
156 | return 1; | 157 | return 1; |
157 | } | 158 | } |
158 | } | ||
159 | 159 | ||
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
@@ -192,92 +192,98 @@ static int friend_number(DHT *dht, uint8_t *client_id) | |||
192 | return -1; | 192 | return -1; |
193 | } | 193 | } |
194 | 194 | ||
195 | /* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: | 195 | /* |
196 | * put them in the nodes_list and return how many were found. | 196 | * helper for get_close_nodes(). argument list is a monster :D |
197 | * | ||
198 | * TODO: For the love of based Allah make this function cleaner and much more efficient. | ||
199 | */ | 197 | */ |
200 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) | 198 | static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, |
199 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, | ||
200 | time_t timestamp, int *num_nodes_ptr) | ||
201 | { | 201 | { |
202 | uint32_t i, j, k; | 202 | int num_nodes = *num_nodes_ptr; |
203 | uint64_t temp_time = unix_time(); | 203 | int i, tout, inlist, ipv46x, j, closest; |
204 | int num_nodes = 0, closest, tout, inlist; | 204 | |
205 | for (i = 0; i < client_list_length; i++) { | ||
206 | Client_data *client = &client_list[i]; | ||
207 | tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT); | ||
208 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); | ||
209 | |||
210 | #ifdef TOX_ENABLE_IPV6 | ||
211 | IP *client_ip = &client->ip_port.ip; | ||
212 | |||
213 | /* | ||
214 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for | ||
215 | * our connections, instead we have to look if it is an embedded | ||
216 | * IPv4-in-IPv6 here and convert it down in sendnodes(). | ||
217 | */ | ||
218 | sa_family_t ip_treat_as_family = client_ip->family; | ||
219 | |||
220 | if ((dht->c->lossless_udp->net->family == AF_INET6) && | ||
221 | (client_ip->family == AF_INET6)) { | ||
222 | /* socket is AF_INET6, address claims AF_INET6: | ||
223 | * check for embedded IPv4-in-IPv6 */ | ||
224 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) | ||
225 | ip_treat_as_family = AF_INET; | ||
226 | } | ||
205 | 227 | ||
206 | for (i = 0; i < LCLIENT_LIST; ++i) { | 228 | ipv46x = !(sa_family == ip_treat_as_family); |
207 | tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); | 229 | #else |
208 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); | 230 | ipv46x = !(sa_family == AF_INET); |
231 | #endif | ||
209 | 232 | ||
210 | /* If node isn't good or is already in list. */ | 233 | /* If node isn't good or is already in list. */ |
211 | if (tout || inlist) | 234 | if (tout || inlist || ipv46x) |
212 | continue; | 235 | continue; |
213 | 236 | ||
214 | if (num_nodes < MAX_SENT_NODES) { | 237 | if (num_nodes < MAX_SENT_NODES) { |
238 | memcpy(nodes_list[num_nodes].client_id, | ||
239 | client->client_id, | ||
240 | CLIENT_ID_SIZE ); | ||
215 | 241 | ||
216 | memcpy( nodes_list[num_nodes].client_id, | 242 | nodes_list[num_nodes].ip_port = client->ip_port; |
217 | dht->close_clientlist[i].client_id, | ||
218 | CLIENT_ID_SIZE ); | ||
219 | |||
220 | nodes_list[num_nodes].ip_port = dht->close_clientlist[i].ip_port; | ||
221 | num_nodes++; | 243 | num_nodes++; |
222 | |||
223 | } else { | 244 | } else { |
224 | 245 | /* see if node_list contains a client_id that's "further away" | |
246 | * compared to the one we're looking at at the moment, if there | ||
247 | * is, replace it | ||
248 | */ | ||
225 | for (j = 0; j < MAX_SENT_NODES; ++j) { | 249 | for (j = 0; j < MAX_SENT_NODES; ++j) { |
226 | closest = id_closest( client_id, | 250 | closest = id_closest( client_id, |
227 | nodes_list[j].client_id, | 251 | nodes_list[j].client_id, |
228 | dht->close_clientlist[i].client_id ); | 252 | client->client_id ); |
229 | 253 | ||
254 | /* second client_id is closer than current: change to it */ | ||
230 | if (closest == 2) { | 255 | if (closest == 2) { |
231 | memcpy( nodes_list[j].client_id, | 256 | memcpy( nodes_list[j].client_id, |
232 | dht->close_clientlist[i].client_id, | 257 | client->client_id, |
233 | CLIENT_ID_SIZE); | 258 | CLIENT_ID_SIZE); |
234 | 259 | ||
235 | nodes_list[j].ip_port = dht->close_clientlist[i].ip_port; | 260 | nodes_list[j].ip_port = client->ip_port; |
236 | break; | 261 | break; |
237 | } | 262 | } |
238 | } | 263 | } |
239 | } | 264 | } |
240 | } | 265 | } |
241 | 266 | ||
242 | for (i = 0; i < dht->num_friends; ++i) { | 267 | *num_nodes_ptr = num_nodes; |
243 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 268 | } |
244 | |||
245 | tout = is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT); | ||
246 | inlist = client_in_nodelist( nodes_list, | ||
247 | MAX_SENT_NODES, | ||
248 | dht->friends_list[i].client_list[j].client_id); | ||
249 | |||
250 | /* If node isn't good or is already in list. */ | ||
251 | if (tout || inlist) | ||
252 | continue; | ||
253 | |||
254 | if (num_nodes < MAX_SENT_NODES) { | ||
255 | |||
256 | memcpy( nodes_list[num_nodes].client_id, | ||
257 | dht->friends_list[i].client_list[j].client_id, | ||
258 | CLIENT_ID_SIZE); | ||
259 | |||
260 | nodes_list[num_nodes].ip_port = dht->friends_list[i].client_list[j].ip_port; | ||
261 | num_nodes++; | ||
262 | } else { | ||
263 | for (k = 0; k < MAX_SENT_NODES; ++k) { | ||
264 | 269 | ||
265 | closest = id_closest( client_id, | 270 | /* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: |
266 | nodes_list[k].client_id, | 271 | * put them in the nodes_list and return how many were found. |
267 | dht->friends_list[i].client_list[j].client_id ); | 272 | * |
273 | * TODO: For the love of based <your favorite deity, in doubt use "love"> make | ||
274 | * this function cleaner and much more efficient. | ||
275 | */ | ||
276 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) | ||
277 | { | ||
278 | time_t timestamp = unix_time(); | ||
279 | int num_nodes = 0, i; | ||
280 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, | ||
281 | dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes); | ||
268 | 282 | ||
269 | if (closest == 2) { | 283 | for (i = 0; i < dht->num_friends; ++i) |
270 | memcpy( nodes_list[k].client_id, | 284 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, |
271 | dht->friends_list[i].client_list[j].client_id, | 285 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, |
272 | CLIENT_ID_SIZE ); | 286 | timestamp, &num_nodes); |
273 | |||
274 | nodes_list[k].ip_port = dht->friends_list[i].client_list[j].ip_port; | ||
275 | break; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | 287 | ||
282 | return num_nodes; | 288 | return num_nodes; |
283 | } | 289 | } |
@@ -301,7 +307,7 @@ static int replace_bad( Client_data *list, | |||
301 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 307 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
302 | list[i].ip_port = ip_port; | 308 | list[i].ip_port = ip_port; |
303 | list[i].timestamp = temp_time; | 309 | list[i].timestamp = temp_time; |
304 | list[i].ret_ip_port.ip.uint32 = 0; | 310 | ip_reset(&list[i].ret_ip_port.ip); |
305 | list[i].ret_ip_port.port = 0; | 311 | list[i].ret_ip_port.port = 0; |
306 | list[i].ret_timestamp = 0; | 312 | list[i].ret_timestamp = 0; |
307 | return 0; | 313 | return 0; |
@@ -349,7 +355,7 @@ static int replace_good( Client_data *list, | |||
349 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 355 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
350 | list[i].ip_port = ip_port; | 356 | list[i].ip_port = ip_port; |
351 | list[i].timestamp = temp_time; | 357 | list[i].timestamp = temp_time; |
352 | list[i].ret_ip_port.ip.uint32 = 0; | 358 | ip_reset(&list[i].ret_ip_port.ip); |
353 | list[i].ret_ip_port.port = 0; | 359 | list[i].ret_ip_port.port = 0; |
354 | list[i].ret_timestamp = 0; | 360 | list[i].ret_timestamp = 0; |
355 | return 0; | 361 | return 0; |
@@ -447,13 +453,13 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) | |||
447 | if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { | 453 | if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { |
448 | pinging = 0; | 454 | pinging = 0; |
449 | 455 | ||
450 | if (ip_port.ip.uint32 != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) | 456 | if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) |
451 | ++pinging; | 457 | ++pinging; |
452 | 458 | ||
453 | if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) | 459 | if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) |
454 | ++pinging; | 460 | ++pinging; |
455 | 461 | ||
456 | if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) | 462 | if (pinging == (ping_id != 0) + ip_isset(&ip_port.ip)) |
457 | return 1; | 463 | return 1; |
458 | } | 464 | } |
459 | } | 465 | } |
@@ -518,44 +524,75 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
518 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | 524 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); |
519 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | 525 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); |
520 | 526 | ||
521 | return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); | 527 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); |
522 | } | 528 | } |
523 | 529 | ||
524 | /* Send a send nodes response. */ | 530 | /* Send a send nodes response. */ |
531 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, | ||
532 | * IPv6 nodes are sent in a different message */ | ||
525 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | 533 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) |
526 | { | 534 | { |
527 | /* Check if packet is going to be sent to ourself. */ | 535 | /* Check if packet is going to be sent to ourself. */ |
528 | if (id_equal(public_key, dht->c->self_public_key)) | 536 | if (id_equal(public_key, dht->c->self_public_key)) |
529 | return -1; | 537 | return -1; |
530 | 538 | ||
539 | size_t Node4_format_size = sizeof(Node4_format); | ||
531 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | 540 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) |
532 | + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 541 | + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
533 | 542 | ||
534 | Node_format nodes_list[MAX_SENT_NODES]; | 543 | Node_format nodes_list[MAX_SENT_NODES]; |
535 | int num_nodes = get_close_nodes(dht, client_id, nodes_list); | 544 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET); |
536 | 545 | ||
537 | if (num_nodes == 0) | 546 | if (num_nodes == 0) |
538 | return 0; | 547 | return 0; |
539 | 548 | ||
540 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 549 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; |
541 | uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 550 | uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
542 | uint8_t nonce[crypto_box_NONCEBYTES]; | 551 | uint8_t nonce[crypto_box_NONCEBYTES]; |
543 | new_nonce(nonce); | 552 | new_nonce(nonce); |
544 | 553 | ||
545 | memcpy(plain, &ping_id, sizeof(ping_id)); | 554 | memcpy(plain, &ping_id, sizeof(ping_id)); |
546 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); | 555 | #ifdef TOX_ENABLE_IPV6 |
556 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
557 | int i, num_nodes_ok = 0; | ||
558 | |||
559 | for (i = 0; i < num_nodes; i++) { | ||
560 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); | ||
561 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; | ||
562 | |||
563 | IP *node_ip = &nodes_list[i].ip_port.ip; | ||
564 | |||
565 | if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6.in6_addr)) | ||
566 | /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ | ||
567 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.uint32[3]; | ||
568 | else if (node_ip->family == AF_INET) | ||
569 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32; | ||
570 | else /* shouldn't happen */ | ||
571 | continue; | ||
572 | |||
573 | num_nodes_ok++; | ||
574 | } | ||
575 | |||
576 | if (num_nodes_ok < num_nodes) { | ||
577 | /* shouldn't happen */ | ||
578 | num_nodes = num_nodes_ok; | ||
579 | } | ||
580 | |||
581 | #else | ||
582 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size); | ||
583 | #endif | ||
547 | 584 | ||
548 | int len = encrypt_data( public_key, | 585 | int len = encrypt_data( public_key, |
549 | dht->c->self_secret_key, | 586 | dht->c->self_secret_key, |
550 | nonce, | 587 | nonce, |
551 | plain, | 588 | plain, |
552 | sizeof(ping_id) + num_nodes * sizeof(Node_format), | 589 | sizeof(ping_id) + num_nodes * Node4_format_size, |
553 | encrypt ); | 590 | encrypt ); |
554 | 591 | ||
555 | if (len == -1) | 592 | if (len == -1) |
556 | return -1; | 593 | return -1; |
557 | 594 | ||
558 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) | 595 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING) |
559 | return -1; | 596 | return -1; |
560 | 597 | ||
561 | data[0] = NET_PACKET_SEND_NODES; | 598 | data[0] = NET_PACKET_SEND_NODES; |
@@ -563,9 +600,57 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl | |||
563 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | 600 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); |
564 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | 601 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); |
565 | 602 | ||
566 | return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); | 603 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); |
567 | } | 604 | } |
568 | 605 | ||
606 | #ifdef TOX_ENABLE_IPV6 | ||
607 | /* Send a send nodes response: message for IPv6 nodes */ | ||
608 | static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | ||
609 | { | ||
610 | /* Check if packet is going to be sent to ourself. */ | ||
611 | if (id_equal(public_key, dht->c->self_public_key)) | ||
612 | return -1; | ||
613 | |||
614 | size_t Node_format_size = sizeof(Node_format); | ||
615 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | ||
616 | + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | ||
617 | |||
618 | Node_format nodes_list[MAX_SENT_NODES]; | ||
619 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6); | ||
620 | |||
621 | if (num_nodes == 0) | ||
622 | return 0; | ||
623 | |||
624 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; | ||
625 | uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | ||
626 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
627 | new_nonce(nonce); | ||
628 | |||
629 | memcpy(plain, &ping_id, sizeof(ping_id)); | ||
630 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size); | ||
631 | |||
632 | int len = encrypt_data( public_key, | ||
633 | dht->c->self_secret_key, | ||
634 | nonce, | ||
635 | plain, | ||
636 | sizeof(ping_id) + num_nodes * Node_format_size, | ||
637 | encrypt ); | ||
638 | |||
639 | if (len == -1) | ||
640 | return -1; | ||
641 | |||
642 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING) | ||
643 | return -1; | ||
644 | |||
645 | data[0] = NET_PACKET_SEND_NODES_IPV6; | ||
646 | memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); | ||
647 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | ||
648 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | ||
649 | |||
650 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); | ||
651 | } | ||
652 | #endif | ||
653 | |||
569 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 654 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
570 | { | 655 | { |
571 | DHT *dht = object; | 656 | DHT *dht = object; |
@@ -593,6 +678,10 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 | |||
593 | 678 | ||
594 | memcpy(&ping_id, plain, sizeof(ping_id)); | 679 | memcpy(&ping_id, plain, sizeof(ping_id)); |
595 | sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); | 680 | sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); |
681 | #ifdef TOX_ENABLE_IPV6 | ||
682 | sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id), | ||
683 | ping_id); /* TODO: prevent possible amplification attacks */ | ||
684 | #endif | ||
596 | 685 | ||
597 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ | 686 | //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ |
598 | 687 | ||
@@ -606,22 +695,24 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
606 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | 695 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; |
607 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | 696 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; |
608 | 697 | ||
609 | if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || | 698 | size_t Node4_format_size = sizeof(Node4_format); |
610 | ((length - cid_size) % sizeof(Node_format)) != 0 || | 699 | |
611 | (length < cid_size + sizeof(Node_format))) | 700 | if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || |
701 | ((length - cid_size) % Node4_format_size) != 0 || | ||
702 | (length < cid_size + Node4_format_size)) | ||
612 | return 1; | 703 | return 1; |
613 | 704 | ||
614 | uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); | 705 | uint32_t num_nodes = (length - cid_size) / Node4_format_size; |
615 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 706 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; |
616 | 707 | ||
617 | int len = decrypt_data( | 708 | int len = decrypt_data( |
618 | packet + 1, | 709 | packet + 1, |
619 | dht->c->self_secret_key, | 710 | dht->c->self_secret_key, |
620 | packet + 1 + CLIENT_ID_SIZE, | 711 | packet + 1 + CLIENT_ID_SIZE, |
621 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 712 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
622 | sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); | 713 | sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain ); |
623 | 714 | ||
624 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) | 715 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size) |
625 | return 1; | 716 | return 1; |
626 | 717 | ||
627 | memcpy(&ping_id, plain, sizeof(ping_id)); | 718 | memcpy(&ping_id, plain, sizeof(ping_id)); |
@@ -629,12 +720,81 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
629 | if (!is_gettingnodes(dht, source, ping_id)) | 720 | if (!is_gettingnodes(dht, source, ping_id)) |
630 | return 1; | 721 | return 1; |
631 | 722 | ||
723 | uint32_t i; | ||
632 | Node_format nodes_list[MAX_SENT_NODES]; | 724 | Node_format nodes_list[MAX_SENT_NODES]; |
725 | |||
726 | #ifdef TOX_ENABLE_IPV6 | ||
727 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
728 | |||
729 | int num_nodes_ok = 0; | ||
730 | |||
731 | for (i = 0; i < num_nodes; i++) | ||
732 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) { | ||
733 | memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | ||
734 | nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; | ||
735 | nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
736 | nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port; | ||
737 | |||
738 | num_nodes_ok++; | ||
739 | } | ||
740 | |||
741 | if (num_nodes_ok < num_nodes) { | ||
742 | /* shouldn't happen */ | ||
743 | num_nodes = num_nodes_ok; | ||
744 | } | ||
745 | |||
746 | #else | ||
633 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | 747 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); |
748 | #endif | ||
634 | 749 | ||
635 | addto_lists(dht, source, packet + 1); | 750 | addto_lists(dht, source, packet + 1); |
636 | 751 | ||
752 | for (i = 0; i < num_nodes; ++i) { | ||
753 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); | ||
754 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | ||
755 | } | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | #ifdef TOX_ENABLE_IPV6 | ||
761 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | ||
762 | { | ||
763 | DHT *dht = object; | ||
764 | uint64_t ping_id; | ||
765 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | ||
766 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | ||
767 | |||
768 | size_t Node_format_size = sizeof(Node_format); | ||
769 | |||
770 | if (length > (cid_size + Node_format_size * MAX_SENT_NODES) || | ||
771 | ((length - cid_size) % Node_format_size) != 0 || | ||
772 | (length < cid_size + Node_format_size)) | ||
773 | return 1; | ||
774 | |||
775 | uint32_t num_nodes = (length - cid_size) / Node_format_size; | ||
776 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; | ||
777 | |||
778 | int len = decrypt_data( | ||
779 | packet + 1, | ||
780 | dht->c->self_secret_key, | ||
781 | packet + 1 + CLIENT_ID_SIZE, | ||
782 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | ||
783 | sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING, plain ); | ||
784 | |||
785 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size) | ||
786 | return 1; | ||
787 | |||
788 | memcpy(&ping_id, plain, sizeof(ping_id)); | ||
789 | |||
790 | if (!is_gettingnodes(dht, source, ping_id)) | ||
791 | return 1; | ||
792 | |||
637 | uint32_t i; | 793 | uint32_t i; |
794 | Node_format nodes_list[MAX_SENT_NODES]; | ||
795 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | ||
796 | |||
797 | addto_lists(dht, source, packet + 1); | ||
638 | 798 | ||
639 | for (i = 0; i < num_nodes; ++i) { | 799 | for (i = 0; i < num_nodes; ++i) { |
640 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); | 800 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); |
@@ -643,10 +803,29 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
643 | 803 | ||
644 | return 0; | 804 | return 0; |
645 | } | 805 | } |
806 | #endif | ||
646 | 807 | ||
647 | /*----------------------------------------------------------------------------------*/ | 808 | /*----------------------------------------------------------------------------------*/ |
648 | /*------------------------END of packet handling functions--------------------------*/ | 809 | /*------------------------END of packet handling functions--------------------------*/ |
649 | 810 | ||
811 | /* | ||
812 | * Send get nodes requests with client_id to max_num peers in list of length length | ||
813 | */ | ||
814 | static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_t max_num, uint8_t *client_id) | ||
815 | { | ||
816 | uint64_t temp_time = unix_time(); | ||
817 | uint32_t i, num = 0; | ||
818 | |||
819 | for (i = 0; i < length; ++i) | ||
820 | if (ipport_isset(&(list[i].ip_port)) && !is_timeout(temp_time, list[i].ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
821 | getnodes(dht, list[i].ip_port, list[i].client_id, client_id); | ||
822 | ++num; | ||
823 | |||
824 | if (num >= max_num) | ||
825 | return; | ||
826 | } | ||
827 | } | ||
828 | |||
650 | int DHT_addfriend(DHT *dht, uint8_t *client_id) | 829 | int DHT_addfriend(DHT *dht, uint8_t *client_id) |
651 | { | 830 | { |
652 | if (friend_number(dht, client_id) != -1) /* Is friend already in DHT? */ | 831 | if (friend_number(dht, client_id) != -1) /* Is friend already in DHT? */ |
@@ -664,6 +843,7 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id) | |||
664 | 843 | ||
665 | dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); | 844 | dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); |
666 | ++dht->num_friends; | 845 | ++dht->num_friends; |
846 | get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/ | ||
667 | return 0; | 847 | return 0; |
668 | } | 848 | } |
669 | 849 | ||
@@ -703,27 +883,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id) | |||
703 | } | 883 | } |
704 | 884 | ||
705 | /* TODO: Optimize this. */ | 885 | /* TODO: Optimize this. */ |
706 | IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) | 886 | int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) |
707 | { | 887 | { |
708 | uint32_t i, j; | 888 | uint32_t i, j; |
709 | uint64_t temp_time = unix_time(); | 889 | uint64_t temp_time = unix_time(); |
710 | IP_Port empty = {{{{0}}, 0, 0}}; | 890 | |
891 | ip_reset(&ip_port->ip); | ||
892 | ip_port->port = 0; | ||
711 | 893 | ||
712 | for (i = 0; i < dht->num_friends; ++i) { | 894 | for (i = 0; i < dht->num_friends; ++i) { |
713 | /* Equal */ | 895 | /* Equal */ |
714 | if (id_equal(dht->friends_list[i].client_id, client_id)) { | 896 | if (id_equal(dht->friends_list[i].client_id, client_id)) { |
715 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 897 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
716 | if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) | 898 | if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) |
717 | && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) | 899 | && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { |
718 | return dht->friends_list[i].client_list[j].ip_port; | 900 | *ip_port = dht->friends_list[i].client_list[j].ip_port; |
901 | return 1; | ||
902 | } | ||
719 | } | 903 | } |
720 | 904 | ||
721 | return empty; | 905 | return 0; |
722 | } | 906 | } |
723 | } | 907 | } |
724 | 908 | ||
725 | empty.ip.uint32 = 1; | 909 | return -1; |
726 | return empty; | ||
727 | } | 910 | } |
728 | 911 | ||
729 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request | 912 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request |
@@ -808,6 +991,40 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) | |||
808 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); | 991 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); |
809 | send_ping_request(dht->ping, dht->c, ip_port, public_key); | 992 | send_ping_request(dht->ping, dht->c, ip_port, public_key); |
810 | } | 993 | } |
994 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | ||
995 | uint16_t port, uint8_t *public_key) | ||
996 | { | ||
997 | IP_Port ip_port_v64; | ||
998 | IP *ip_extra = NULL; | ||
999 | #ifdef TOX_ENABLE_IPV6 | ||
1000 | IP_Port ip_port_v4; | ||
1001 | ip_init(&ip_port_v64.ip, ipv6enabled); | ||
1002 | |||
1003 | if (ipv6enabled) { | ||
1004 | ip_port_v64.ip.family = AF_UNSPEC; | ||
1005 | ip_reset(&ip_port_v4.ip); | ||
1006 | ip_extra = &ip_port_v4.ip; | ||
1007 | } | ||
1008 | |||
1009 | #else | ||
1010 | ip_init(&ip_port_v64.ip, 0); | ||
1011 | #endif | ||
1012 | |||
1013 | if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) { | ||
1014 | ip_port_v64.port = port; | ||
1015 | DHT_bootstrap(dht, ip_port_v64, public_key); | ||
1016 | #ifdef TOX_ENABLE_IPV6 | ||
1017 | |||
1018 | if ((ip_extra != NULL) && ip_isset(ip_extra)) { | ||
1019 | ip_port_v4.port = port; | ||
1020 | DHT_bootstrap(dht, ip_port_v4, public_key); | ||
1021 | } | ||
1022 | |||
1023 | #endif | ||
1024 | return 1; | ||
1025 | } else | ||
1026 | return 0; | ||
1027 | } | ||
811 | 1028 | ||
812 | /* Send the given packet to node with client_id | 1029 | /* Send the given packet to node with client_id |
813 | * | 1030 | * |
@@ -819,7 +1036,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
819 | 1036 | ||
820 | for (i = 0; i < LCLIENT_LIST; ++i) { | 1037 | for (i = 0; i < LCLIENT_LIST; ++i) { |
821 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) | 1038 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) |
822 | return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length); | 1039 | return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length); |
823 | } | 1040 | } |
824 | 1041 | ||
825 | return -1; | 1042 | return -1; |
@@ -848,7 +1065,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
848 | client = &friend->client_list[i]; | 1065 | client = &friend->client_list[i]; |
849 | 1066 | ||
850 | /* If ip is not zero and node is good. */ | 1067 | /* If ip is not zero and node is good. */ |
851 | if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1068 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { |
852 | 1069 | ||
853 | if (id_equal(client->client_id, friend->client_id)) | 1070 | if (id_equal(client->client_id, friend->client_id)) |
854 | return 0; | 1071 | return 0; |
@@ -890,8 +1107,8 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt | |||
890 | client = &friend->client_list[i]; | 1107 | client = &friend->client_list[i]; |
891 | 1108 | ||
892 | /* If ip is not zero and node is good. */ | 1109 | /* If ip is not zero and node is good. */ |
893 | if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1110 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { |
894 | int retval = sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length); | 1111 | int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); |
895 | 1112 | ||
896 | if ((unsigned int)retval == length) | 1113 | if ((unsigned int)retval == length) |
897 | ++sent; | 1114 | ++sent; |
@@ -924,7 +1141,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
924 | client = &friend->client_list[i]; | 1141 | client = &friend->client_list[i]; |
925 | 1142 | ||
926 | /* If ip is not zero and node is good. */ | 1143 | /* If ip is not zero and node is good. */ |
927 | if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1144 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { |
928 | ip_list[n] = client->ip_port; | 1145 | ip_list[n] = client->ip_port; |
929 | ++n; | 1146 | ++n; |
930 | } | 1147 | } |
@@ -933,7 +1150,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
933 | if (n < 1) | 1150 | if (n < 1) |
934 | return 0; | 1151 | return 0; |
935 | 1152 | ||
936 | int retval = sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length); | 1153 | int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length); |
937 | 1154 | ||
938 | if ((unsigned int)retval == length) | 1155 | if ((unsigned int)retval == length) |
939 | return 1; | 1156 | return 1; |
@@ -1032,7 +1249,8 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, | |||
1032 | */ | 1249 | */ |
1033 | static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) | 1250 | static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) |
1034 | { | 1251 | { |
1035 | IP zero = {{0}}; | 1252 | IP zero; |
1253 | ip_reset(&zero); | ||
1036 | 1254 | ||
1037 | if (len > MAX_FRIEND_CLIENTS) | 1255 | if (len > MAX_FRIEND_CLIENTS) |
1038 | return zero; | 1256 | return zero; |
@@ -1042,7 +1260,7 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) | |||
1042 | 1260 | ||
1043 | for (i = 0; i < len; ++i) { | 1261 | for (i = 0; i < len; ++i) { |
1044 | for (j = 0; j < len; ++j) { | 1262 | for (j = 0; j < len; ++j) { |
1045 | if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) | 1263 | if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) |
1046 | ++numbers[i]; | 1264 | ++numbers[i]; |
1047 | } | 1265 | } |
1048 | 1266 | ||
@@ -1065,7 +1283,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t | |||
1065 | uint16_t num = 0; | 1283 | uint16_t num = 0; |
1066 | 1284 | ||
1067 | for (i = 0; i < len; ++i) { | 1285 | for (i = 0; i < len; ++i) { |
1068 | if (ip_portlist[i].ip.uint32 == ip.uint32) { | 1286 | if (ip_equal(&ip_portlist[i].ip, &ip)) { |
1069 | portlist[num] = ntohs(ip_portlist[i].port); | 1287 | portlist[num] = ntohs(ip_portlist[i].port); |
1070 | ++num; | 1288 | ++num; |
1071 | } | 1289 | } |
@@ -1085,7 +1303,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, | |||
1085 | for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { | 1303 | for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { |
1086 | /* TODO: Improve port guessing algorithm. */ | 1304 | /* TODO: Improve port guessing algorithm. */ |
1087 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); | 1305 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); |
1088 | IP_Port pinging = {{ip, htons(port), 0}}; | 1306 | IP_Port pinging; |
1307 | ip_copy(&pinging.ip, &ip); | ||
1308 | pinging.port = htons(port); | ||
1089 | send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); | 1309 | send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); |
1090 | } | 1310 | } |
1091 | 1311 | ||
@@ -1116,7 +1336,7 @@ static void do_NAT(DHT *dht) | |||
1116 | 1336 | ||
1117 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); | 1337 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); |
1118 | 1338 | ||
1119 | if (ip.uint32 == 0) | 1339 | if (!ip_isset(&ip)) |
1120 | continue; | 1340 | continue; |
1121 | 1341 | ||
1122 | uint16_t port_list[MAX_FRIEND_CLIENTS]; | 1342 | uint16_t port_list[MAX_FRIEND_CLIENTS]; |
@@ -1145,16 +1365,15 @@ static void do_NAT(DHT *dht) | |||
1145 | */ | 1365 | */ |
1146 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) | 1366 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) |
1147 | { | 1367 | { |
1148 | if (ip_port.ip.uint32 == 0) | 1368 | if (!ip_isset(&ip_port.ip)) |
1149 | return -1; | 1369 | return -1; |
1150 | 1370 | ||
1151 | uint32_t i; | 1371 | uint32_t i; |
1152 | 1372 | ||
1153 | for (i = 0; i < MAX_TOPING; ++i) { | 1373 | for (i = 0; i < MAX_TOPING; ++i) { |
1154 | if (dht->toping[i].ip_port.ip.uint32 == 0) { | 1374 | if (!ip_isset(&dht->toping[i].ip_port.ip)) { |
1155 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); | 1375 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); |
1156 | dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 1376 | ipport_copy(&dht->toping[i].ip_port, &ip_port); |
1157 | dht->toping[i].ip_port.port = ip_port.port; | ||
1158 | return 0; | 1377 | return 0; |
1159 | } | 1378 | } |
1160 | } | 1379 | } |
@@ -1162,8 +1381,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) | |||
1162 | for (i = 0; i < MAX_TOPING; ++i) { | 1381 | for (i = 0; i < MAX_TOPING; ++i) { |
1163 | if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { | 1382 | if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { |
1164 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); | 1383 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); |
1165 | dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 1384 | ipport_copy(&dht->toping[i].ip_port, &ip_port); |
1166 | dht->toping[i].ip_port.port = ip_port.port; | ||
1167 | return 0; | 1385 | return 0; |
1168 | } | 1386 | } |
1169 | } | 1387 | } |
@@ -1185,11 +1403,11 @@ static void do_toping(DHT *dht) | |||
1185 | uint32_t i; | 1403 | uint32_t i; |
1186 | 1404 | ||
1187 | for (i = 0; i < MAX_TOPING; ++i) { | 1405 | for (i = 0; i < MAX_TOPING; ++i) { |
1188 | if (dht->toping[i].ip_port.ip.uint32 == 0) | 1406 | if (!ip_isset(&dht->toping[i].ip_port.ip)) |
1189 | return; | 1407 | return; |
1190 | 1408 | ||
1191 | send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); | 1409 | send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); |
1192 | dht->toping[i].ip_port.ip.uint32 = 0; | 1410 | ip_reset(&dht->toping[i].ip_port.ip); |
1193 | } | 1411 | } |
1194 | } | 1412 | } |
1195 | 1413 | ||
@@ -1216,6 +1434,9 @@ DHT *new_DHT(Net_Crypto *c) | |||
1216 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); | 1434 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); |
1217 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); | 1435 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); |
1218 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); | 1436 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); |
1437 | #ifdef TOX_ENABLE_IPV6 | ||
1438 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, temp); | ||
1439 | #endif | ||
1219 | init_cryptopackets(temp); | 1440 | init_cryptopackets(temp); |
1220 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); | 1441 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); |
1221 | return temp; | 1442 | return temp; |
@@ -1255,24 +1476,26 @@ void DHT_save_old(DHT *dht, uint8_t *data) | |||
1255 | */ | 1476 | */ |
1256 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | 1477 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) |
1257 | { | 1478 | { |
1258 | if (size < sizeof(dht->close_clientlist)) | 1479 | if (size < sizeof(dht->close_clientlist)) { |
1480 | fprintf(stderr, "DHT_load: Expected at least %lu bytes, got %u.\n", sizeof(dht->close_clientlist), size); | ||
1259 | return -1; | 1481 | return -1; |
1482 | } | ||
1483 | |||
1484 | uint32_t friendlistsize = size - sizeof(dht->close_clientlist); | ||
1260 | 1485 | ||
1261 | if ((size - sizeof(dht->close_clientlist)) % sizeof(DHT_Friend) != 0) | 1486 | if (friendlistsize % sizeof(DHT_Friend) != 0) { |
1487 | fprintf(stderr, "DHT_load: Expected a multiple of %lu, got %u.\n", sizeof(DHT_Friend), friendlistsize); | ||
1262 | return -1; | 1488 | return -1; |
1489 | } | ||
1263 | 1490 | ||
1264 | uint32_t i, j; | 1491 | uint32_t i, j; |
1265 | uint16_t temp; | ||
1266 | /* uint64_t temp_time = unix_time(); */ | ||
1267 | |||
1268 | Client_data *client; | 1492 | Client_data *client; |
1493 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend); | ||
1269 | 1494 | ||
1270 | temp = (size - sizeof(dht->close_clientlist)) / sizeof(DHT_Friend); | 1495 | if (friends_num != 0) { |
1271 | |||
1272 | if (temp != 0) { | ||
1273 | DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); | 1496 | DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); |
1274 | 1497 | ||
1275 | for (i = 0; i < temp; ++i) { | 1498 | for (i = 0; i < friends_num; ++i) { |
1276 | DHT_addfriend(dht, tempfriends_list[i].client_id); | 1499 | DHT_addfriend(dht, tempfriends_list[i].client_id); |
1277 | 1500 | ||
1278 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1501 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |