diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 165 |
1 files changed, 90 insertions, 75 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 8557a5e0..df3b2f76 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include "network.h" | 31 | #include "network.h" |
32 | #include "ping.h" | 32 | #include "ping.h" |
33 | #include "misc_tools.h" | 33 | #include "misc_tools.h" |
34 | #include "Messenger.h" | ||
35 | #include "util.h" | 34 | #include "util.h" |
36 | 35 | ||
37 | /* 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. */ |
@@ -197,73 +196,75 @@ static int friend_number(DHT *dht, uint8_t *client_id) | |||
197 | * helper for get_close_nodes(). argument list is a monster :D | 196 | * helper for get_close_nodes(). argument list is a monster :D |
198 | */ | 197 | */ |
199 | static int get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, | 198 | static int get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, |
200 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, | 199 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, |
201 | time_t timestamp, int *num_nodes_ptr) | 200 | time_t timestamp, int *num_nodes_ptr) |
202 | { | 201 | { |
203 | int num_nodes = 0; | 202 | int num_nodes = 0; |
204 | int i, tout, inlist, ipv46x, j, closest; | 203 | int i, tout, inlist, ipv46x, j, closest; |
205 | for(i = 0; i < client_list_length; i++) { | 204 | |
206 | Client_data *client = &client_list[i]; | 205 | for (i = 0; i < client_list_length; i++) { |
207 | tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT); | 206 | Client_data *client = &client_list[i]; |
208 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); | 207 | tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT); |
208 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); | ||
209 | 209 | ||
210 | #ifdef TOX_ENABLE_IPV6 | 210 | #ifdef TOX_ENABLE_IPV6 |
211 | IP *client_ip = &client->ip_port.ip; | 211 | IP *client_ip = &client->ip_port.ip; |
212 | 212 | ||
213 | /* | 213 | /* |
214 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for | 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 | 215 | * our connections, instead we have to look if it is an embedded |
216 | * IPv4-in-IPv6 here and convert it down in sendnodes(). | 216 | * IPv4-in-IPv6 here and convert it down in sendnodes(). |
217 | */ | 217 | */ |
218 | sa_family_t ip_treat_as_family = client_ip->family; | 218 | sa_family_t ip_treat_as_family = client_ip->family; |
219 | if ((dht->c->lossless_udp->net->family == AF_INET6) && | 219 | |
220 | (client_ip->family == AF_INET6)) { | 220 | if ((dht->c->lossless_udp->net->family == AF_INET6) && |
221 | /* socket is AF_INET6, address claims AF_INET6: | 221 | (client_ip->family == AF_INET6)) { |
222 | * check for embedded IPv4-in-IPv6 */ | 222 | /* socket is AF_INET6, address claims AF_INET6: |
223 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6)) | 223 | * check for embedded IPv4-in-IPv6 */ |
224 | ip_treat_as_family = AF_INET; | 224 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6)) |
225 | } | 225 | ip_treat_as_family = AF_INET; |
226 | 226 | } | |
227 | ipv46x = !(sa_family == ip_treat_as_family); | 227 | |
228 | ipv46x = !(sa_family == ip_treat_as_family); | ||
228 | #else | 229 | #else |
229 | ipv46x = !(sa_family == AF_INET); | 230 | ipv46x = !(sa_family == AF_INET); |
230 | #endif | 231 | #endif |
231 | 232 | ||
232 | /* If node isn't good or is already in list. */ | 233 | /* If node isn't good or is already in list. */ |
233 | if (tout || inlist || ipv46x) | 234 | if (tout || inlist || ipv46x) |
234 | continue; | 235 | continue; |
235 | 236 | ||
236 | if (num_nodes < MAX_SENT_NODES) { | 237 | if (num_nodes < MAX_SENT_NODES) { |
237 | memcpy(nodes_list[num_nodes].client_id, | 238 | memcpy(nodes_list[num_nodes].client_id, |
238 | client->client_id, | 239 | client->client_id, |
239 | CLIENT_ID_SIZE ); | 240 | CLIENT_ID_SIZE ); |
240 | 241 | ||
241 | nodes_list[num_nodes].ip_port = client->ip_port; | 242 | nodes_list[num_nodes].ip_port = client->ip_port; |
242 | num_nodes++; | 243 | num_nodes++; |
243 | } else { | 244 | } else { |
244 | /* see if node_list contains a client_id that's "further away" | 245 | /* see if node_list contains a client_id that's "further away" |
245 | * compared to the one we're looking at at the moment, if there | 246 | * compared to the one we're looking at at the moment, if there |
246 | * is, replace it | 247 | * is, replace it |
247 | */ | 248 | */ |
248 | for (j = 0; j < MAX_SENT_NODES; ++j) { | 249 | for (j = 0; j < MAX_SENT_NODES; ++j) { |
249 | closest = id_closest( client_id, | 250 | closest = id_closest( client_id, |
250 | nodes_list[j].client_id, | 251 | nodes_list[j].client_id, |
251 | client->client_id ); | 252 | client->client_id ); |
252 | 253 | ||
253 | /* second client_id is closer than current: change to it */ | 254 | /* second client_id is closer than current: change to it */ |
254 | if (closest == 2) { | 255 | if (closest == 2) { |
255 | memcpy( nodes_list[j].client_id, | 256 | memcpy( nodes_list[j].client_id, |
256 | client->client_id, | 257 | client->client_id, |
257 | CLIENT_ID_SIZE); | 258 | CLIENT_ID_SIZE); |
258 | 259 | ||
259 | nodes_list[j].ip_port = client->ip_port; | 260 | nodes_list[j].ip_port = client->ip_port; |
260 | break; | 261 | break; |
261 | } | 262 | } |
262 | } | 263 | } |
263 | } | 264 | } |
264 | } | 265 | } |
265 | 266 | ||
266 | *num_nodes_ptr = num_nodes; | 267 | *num_nodes_ptr = num_nodes; |
267 | } | 268 | } |
268 | 269 | ||
269 | /* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: | 270 | /* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: |
@@ -274,15 +275,15 @@ static int get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *node | |||
274 | */ | 275 | */ |
275 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) | 276 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) |
276 | { | 277 | { |
277 | time_t timestamp = unix_time(); | 278 | time_t timestamp = unix_time(); |
278 | int num_nodes = 0, i; | 279 | int num_nodes = 0, i; |
279 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, | 280 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, |
280 | dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes); | 281 | dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes); |
281 | 282 | ||
282 | for (i = 0; i < dht->num_friends; ++i) | 283 | for (i = 0; i < dht->num_friends; ++i) |
283 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, | 284 | get_close_nodes_inner(dht, client_id, nodes_list, sa_family, |
284 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, | 285 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, |
285 | timestamp, &num_nodes); | 286 | timestamp, &num_nodes); |
286 | 287 | ||
287 | return num_nodes; | 288 | return num_nodes; |
288 | } | 289 | } |
@@ -554,11 +555,13 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl | |||
554 | #ifdef TOX_ENABLE_IPV6 | 555 | #ifdef TOX_ENABLE_IPV6 |
555 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | 556 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); |
556 | int i, num_nodes_ok = 0; | 557 | int i, num_nodes_ok = 0; |
557 | for(i = 0; i < num_nodes; i++) { | 558 | |
559 | for (i = 0; i < num_nodes; i++) { | ||
558 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); | 560 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); |
559 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; | 561 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; |
560 | 562 | ||
561 | IP *node_ip = &nodes_list[i].ip_port.ip; | 563 | IP *node_ip = &nodes_list[i].ip_port.ip; |
564 | |||
562 | if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6)) | 565 | if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6)) |
563 | /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ | 566 | /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ |
564 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.s6_addr32[3]; | 567 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.s6_addr32[3]; |
@@ -574,6 +577,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl | |||
574 | /* shouldn't happen */ | 577 | /* shouldn't happen */ |
575 | num_nodes = num_nodes_ok; | 578 | num_nodes = num_nodes_ok; |
576 | } | 579 | } |
580 | |||
577 | #else | 581 | #else |
578 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size); | 582 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size); |
579 | #endif | 583 | #endif |
@@ -620,7 +624,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ | |||
620 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; | 624 | uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; |
621 | uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 625 | uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
622 | uint8_t nonce[crypto_box_NONCEBYTES]; | 626 | uint8_t nonce[crypto_box_NONCEBYTES]; |
623 | random_nonce(nonce); | 627 | new_nonce(nonce); |
624 | 628 | ||
625 | memcpy(plain, &ping_id, sizeof(ping_id)); | 629 | memcpy(plain, &ping_id, sizeof(ping_id)); |
626 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size); | 630 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size); |
@@ -691,6 +695,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
691 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | 695 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; |
692 | 696 | ||
693 | size_t Node4_format_size = sizeof(Node4_format); | 697 | size_t Node4_format_size = sizeof(Node4_format); |
698 | |||
694 | if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || | 699 | if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || |
695 | ((length - cid_size) % Node4_format_size) != 0 || | 700 | ((length - cid_size) % Node4_format_size) != 0 || |
696 | (length < cid_size + Node4_format_size)) | 701 | (length < cid_size + Node4_format_size)) |
@@ -721,7 +726,8 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
721 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | 726 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); |
722 | 727 | ||
723 | int num_nodes_ok = 0; | 728 | int num_nodes_ok = 0; |
724 | for(i = 0; i < num_nodes; i++) | 729 | |
730 | for (i = 0; i < num_nodes; i++) | ||
725 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) { | 731 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) { |
726 | memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | 732 | memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); |
727 | nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; | 733 | nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; |
@@ -735,6 +741,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
735 | /* shouldn't happen */ | 741 | /* shouldn't happen */ |
736 | num_nodes = num_nodes_ok; | 742 | num_nodes = num_nodes_ok; |
737 | } | 743 | } |
744 | |||
738 | #else | 745 | #else |
739 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | 746 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); |
740 | #endif | 747 | #endif |
@@ -758,6 +765,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, | |||
758 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | 765 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; |
759 | 766 | ||
760 | size_t Node_format_size = sizeof(Node4_format); | 767 | size_t Node_format_size = sizeof(Node4_format); |
768 | |||
761 | if (length > (cid_size + Node_format_size * MAX_SENT_NODES) || | 769 | if (length > (cid_size + Node_format_size * MAX_SENT_NODES) || |
762 | ((length - cid_size) % Node_format_size) != 0 || | 770 | ((length - cid_size) % Node_format_size) != 0 || |
763 | (length < cid_size + Node_format_size)) | 771 | (length < cid_size + Node_format_size)) |
@@ -964,17 +972,19 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) | |||
964 | send_ping_request(dht->ping, dht->c, ip_port, public_key); | 972 | send_ping_request(dht->ping, dht->c, ip_port, public_key); |
965 | } | 973 | } |
966 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | 974 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, |
967 | uint16_t port, uint8_t *public_key) | 975 | uint16_t port, uint8_t *public_key) |
968 | { | 976 | { |
969 | IP_Port ip_port_v64, ip_port_v4; | 977 | IP_Port ip_port_v64, ip_port_v4; |
970 | IP *ip_extra = NULL; | 978 | IP *ip_extra = NULL; |
971 | #ifdef TOX_ENABLE_IPV6 | 979 | #ifdef TOX_ENABLE_IPV6 |
972 | ip_init(&ip_port_v64.ip, ipv6enabled); | 980 | ip_init(&ip_port_v64.ip, ipv6enabled); |
981 | |||
973 | if (ipv6enabled) { | 982 | if (ipv6enabled) { |
974 | ip_port_v64.ip.family = AF_UNSPEC; | 983 | ip_port_v64.ip.family = AF_UNSPEC; |
975 | ip_reset(&ip_port_v4.ip); | 984 | ip_reset(&ip_port_v4.ip); |
976 | ip_extra = &ip_port_v4.ip; | 985 | ip_extra = &ip_port_v4.ip; |
977 | } | 986 | } |
987 | |||
978 | #else | 988 | #else |
979 | ip_init(&ip_port_v64.ip, 0); | 989 | ip_init(&ip_port_v64.ip, 0); |
980 | #endif | 990 | #endif |
@@ -983,14 +993,15 @@ int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable | |||
983 | ip_port_v64.port = port; | 993 | ip_port_v64.port = port; |
984 | DHT_bootstrap(dht, ip_port_v64, public_key); | 994 | DHT_bootstrap(dht, ip_port_v64, public_key); |
985 | #ifdef TOX_ENABLE_IPV6 | 995 | #ifdef TOX_ENABLE_IPV6 |
996 | |||
986 | if ((ip_extra != NULL) && ip_isset(ip_extra)) { | 997 | if ((ip_extra != NULL) && ip_isset(ip_extra)) { |
987 | ip_port_v4.port = port; | 998 | ip_port_v4.port = port; |
988 | DHT_bootstrap(dht, ip_port_v4, public_key); | 999 | DHT_bootstrap(dht, ip_port_v4, public_key); |
989 | } | 1000 | } |
1001 | |||
990 | #endif | 1002 | #endif |
991 | return 1; | 1003 | return 1; |
992 | } | 1004 | } else |
993 | else | ||
994 | return 0; | 1005 | return 0; |
995 | } | 1006 | } |
996 | 1007 | ||
@@ -1303,6 +1314,7 @@ static void do_NAT(DHT *dht) | |||
1303 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { | 1314 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { |
1304 | 1315 | ||
1305 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); | 1316 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); |
1317 | |||
1306 | if (!ip_isset(&ip)) | 1318 | if (!ip_isset(&ip)) |
1307 | continue; | 1319 | continue; |
1308 | 1320 | ||
@@ -1443,12 +1455,13 @@ void DHT_save(DHT *dht, uint8_t *data) | |||
1443 | */ | 1455 | */ |
1444 | int DHT_load(DHT *dht, uint8_t *data, uint32_t size) | 1456 | int DHT_load(DHT *dht, uint8_t *data, uint32_t size) |
1445 | { | 1457 | { |
1446 | if (size < sizeof(dht->close_clientlist)) { | 1458 | if (size < sizeof(dht->close_clientlist)) { |
1447 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); | 1459 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); |
1448 | return -1; | 1460 | return -1; |
1449 | } | 1461 | } |
1450 | 1462 | ||
1451 | uint32_t friendlistsize = size - sizeof(dht->close_clientlist); | 1463 | uint32_t friendlistsize = size - sizeof(dht->close_clientlist); |
1464 | |||
1452 | if (friendlistsize % sizeof(DHT_Friend) != 0) { | 1465 | if (friendlistsize % sizeof(DHT_Friend) != 0) { |
1453 | fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); | 1466 | fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); |
1454 | return -1; | 1467 | return -1; |
@@ -1457,6 +1470,7 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size) | |||
1457 | uint32_t i, j; | 1470 | uint32_t i, j; |
1458 | Client_data *client; | 1471 | Client_data *client; |
1459 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend); | 1472 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend); |
1473 | |||
1460 | if (friends_num != 0) { | 1474 | if (friends_num != 0) { |
1461 | DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); | 1475 | DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); |
1462 | 1476 | ||
@@ -1473,6 +1487,7 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size) | |||
1473 | } | 1487 | } |
1474 | 1488 | ||
1475 | Client_data *tempclose_clientlist = (Client_data *)data; | 1489 | Client_data *tempclose_clientlist = (Client_data *)data; |
1490 | |||
1476 | for (i = 0; i < LCLIENT_LIST; ++i) { | 1491 | for (i = 0; i < LCLIENT_LIST; ++i) { |
1477 | if (tempclose_clientlist[i].timestamp != 0) | 1492 | if (tempclose_clientlist[i].timestamp != 0) |
1478 | DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, | 1493 | DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, |