summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-04-15 18:09:07 -0400
committerirungentoo <irungentoo@gmail.com>2014-04-15 18:09:07 -0400
commitf9bf7b074acd29b0448d36a66db4339c6ae659c4 (patch)
tree0b46cfd4a2989f06004c5e57ed26a735ff9a5d4f
parent229b2b2dcdcab20f35063da9e69b6ef0ded70231 (diff)
Major protocol changes, this commit breaks all network compatibility.
Removed a bunch of useless space from various structs. pack_nodes() and unpack_nodes() are now used to transmit lists of nodes for the DHT and onion parts. They provide a way to transmit both ipv6 and ipv4 nodes in the same packet in a portable way that takes as little space as possible without compression. Using pack_nodes, merged the send nodes and send nodes ipv6 packets into one packet greatly reducing the risk of amplification attacks.
-rw-r--r--auto_tests/network_test.c5
-rw-r--r--docs/updates/DHT.md16
-rw-r--r--toxcore/DHT.c371
-rw-r--r--toxcore/DHT.h31
-rw-r--r--toxcore/network.h18
-rw-r--r--toxcore/onion_announce.c19
-rw-r--r--toxcore/onion_client.c58
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}
143END_TEST 142END_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
80Node format: 80Node 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```
84see also: DHT.h (Node4_format struct) 84see also: DHT.h (pack_nodes() and unpack_nodes())
85
86IPv6 Node format:
87see: DHT.h (Node_format struct)
88 85
89Valid queries and Responses: 86Valid queries and Responses:
90 87
@@ -102,12 +99,7 @@ Packet contents:
102``` 99```
103Valid replies: a send_nodes packet 100Valid replies: a send_nodes packet
104 101
105Send_nodes (response (for ipv4 addresses)): 102Send_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
110Send_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
182void 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
190void 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 */
203int 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 */
243int 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 */
325static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, 424static 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 */
914static 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
980void 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
992void 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 */
1000static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, 994static 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. */
1111static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, 1101static 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
1114static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, 1104static 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
1159static 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
1203static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) 1153static 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 */
1980static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, 1922static 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 */ 133typedef struct __attribute__ ((__packed__))
132typedef struct { 134{
133 uint8_t client_id[CLIENT_ID_SIZE];
134 IP4_Port ip_port;
135} Node4_format;
136
137typedef 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}
138Node_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 */
145int 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 */
152int 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
167typedef union __attribute__ ((__packed__)) 164typedef union __attribute__ ((__packed__))
168{ 165{
169 uint8_t uint8[4]; 166 uint8_t uint8[4];
@@ -186,8 +183,6 @@ IP6;
186typedef struct __attribute__ ((__packed__)) 183typedef 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}
196IP; 191IP;
197 192
198typedef 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}
208IP4_Port;
209
210typedef struct __attribute__ ((__packed__)) IP_Port { 193typedef 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;