summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c2850
1 files changed, 1583 insertions, 1267 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 6d9479a6..6b2715ee 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -1,51 +1,44 @@
1/* DHT.c 1/*
2 *
3 * An implementation of the DHT as seen in docs/updates/DHT.md 2 * An implementation of the DHT as seen in docs/updates/DHT.md
3 */
4
5/*
6 * Copyright © 2016-2018 The TokTok team.
7 * Copyright © 2013 Tox project.
4 * 8 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 9 * This file is part of Tox, the free peer to peer instant messenger.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * 10 *
14 * Tox is distributed in the hope that it will be useful, 11 * Tox is free software: you can redistribute it and/or modify
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * it under the terms of the GNU General Public License as published by
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * the Free Software Foundation, either version 3 of the License, or
17 * GNU General Public License for more details. 14 * (at your option) any later version.
18 * 15 *
19 * You should have received a copy of the GNU General Public License 16 * Tox is distributed in the hope that it will be useful,
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * 20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 */ 23 */
23
24/*----------------------------------------------------------------------------------*/
25
26#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
27#include "config.h" 25#include "config.h"
28#endif 26#endif
29 27
30#ifdef DEBUG
31#include <assert.h>
32#endif
33
34#include "logger.h"
35
36#include "DHT.h" 28#include "DHT.h"
37 29
38#ifdef ENABLE_ASSOC_DHT
39#include "assoc.h"
40#endif
41
42#include "ping.h"
43
44#include "network.h"
45#include "LAN_discovery.h" 30#include "LAN_discovery.h"
46#include "misc_tools.h" 31#include "logger.h"
32#include "mono_time.h"
33#include "network.h"
34#include "ping.h"
35#include "state.h"
47#include "util.h" 36#include "util.h"
48 37
38#include <assert.h>
39#include <stdlib.h>
40#include <string.h>
41
49/* The timeout after which a node is discarded completely. */ 42/* The timeout after which a node is discarded completely. */
50#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL) 43#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
51 44
@@ -57,6 +50,9 @@
57/* Interval in seconds between punching attempts*/ 50/* Interval in seconds between punching attempts*/
58#define PUNCH_INTERVAL 3 51#define PUNCH_INTERVAL 3
59 52
53/* Time in seconds after which punching parameters will be reset */
54#define PUNCH_RESET_TIME 40
55
60#define MAX_NORMAL_PUNCHING_TRIES 5 56#define MAX_NORMAL_PUNCHING_TRIES 5
61 57
62#define NAT_PING_REQUEST 0 58#define NAT_PING_REQUEST 0
@@ -65,6 +61,133 @@
65/* Number of get node requests to send to quickly find close nodes. */ 61/* Number of get node requests to send to quickly find close nodes. */
66#define MAX_BOOTSTRAP_TIMES 5 62#define MAX_BOOTSTRAP_TIMES 5
67 63
64typedef struct DHT_Friend_Callback {
65 dht_ip_cb *ip_callback;
66 void *data;
67 int32_t number;
68} DHT_Friend_Callback;
69
70struct DHT_Friend {
71 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
72 Client_data client_list[MAX_FRIEND_CLIENTS];
73
74 /* Time at which the last get_nodes request was sent. */
75 uint64_t lastgetnode;
76 /* number of times get_node packets were sent. */
77 uint32_t bootstrap_times;
78
79 /* Symmetric NAT hole punching stuff. */
80 NAT nat;
81
82 uint16_t lock_count;
83 DHT_Friend_Callback callbacks[DHT_FRIEND_MAX_LOCKS];
84
85 Node_format to_bootstrap[MAX_SENT_NODES];
86 unsigned int num_to_bootstrap;
87};
88
89typedef struct Cryptopacket_Handler {
90 cryptopacket_handler_cb *function;
91 void *object;
92} Cryptopacket_Handler;
93
94struct DHT {
95 const Logger *log;
96 Mono_Time *mono_time;
97 Networking_Core *net;
98
99 bool hole_punching_enabled;
100
101 Client_data close_clientlist[LCLIENT_LIST];
102 uint64_t close_lastgetnodes;
103 uint32_t close_bootstrap_times;
104
105 /* DHT keypair */
106 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
107 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
108
109 DHT_Friend *friends_list;
110 uint16_t num_friends;
111
112 Node_format *loaded_nodes_list;
113 uint32_t loaded_num_nodes;
114 unsigned int loaded_nodes_index;
115
116 Shared_Keys shared_keys_recv;
117 Shared_Keys shared_keys_sent;
118
119 struct Ping *ping;
120 Ping_Array *dht_ping_array;
121 Ping_Array *dht_harden_ping_array;
122 uint64_t last_run;
123
124 Cryptopacket_Handler cryptopackethandlers[256];
125
126 Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
127 unsigned int num_to_bootstrap;
128};
129
130const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend)
131{
132 return dht_friend->public_key;
133}
134
135const Client_data *dht_friend_client(const DHT_Friend *dht_friend, size_t index)
136{
137 return &dht_friend->client_list[index];
138}
139
140const uint8_t *dht_get_self_public_key(const DHT *dht)
141{
142 return dht->self_public_key;
143}
144const uint8_t *dht_get_self_secret_key(const DHT *dht)
145{
146 return dht->self_secret_key;
147}
148
149void dht_set_self_public_key(DHT *dht, const uint8_t *key)
150{
151 memcpy(dht->self_public_key, key, CRYPTO_PUBLIC_KEY_SIZE);
152}
153void dht_set_self_secret_key(DHT *dht, const uint8_t *key)
154{
155 memcpy(dht->self_secret_key, key, CRYPTO_SECRET_KEY_SIZE);
156}
157
158Networking_Core *dht_get_net(const DHT *dht)
159{
160 return dht->net;
161}
162struct Ping *dht_get_ping(const DHT *dht)
163{
164 return dht->ping;
165}
166const Client_data *dht_get_close_clientlist(const DHT *dht)
167{
168 return dht->close_clientlist;
169}
170const Client_data *dht_get_close_client(const DHT *dht, uint32_t client_num)
171{
172 assert(client_num < sizeof(dht->close_clientlist) / sizeof(dht->close_clientlist[0]));
173 return &dht->close_clientlist[client_num];
174}
175uint16_t dht_get_num_friends(const DHT *dht)
176{
177 return dht->num_friends;
178}
179
180DHT_Friend *dht_get_friend(DHT *dht, uint32_t friend_num)
181{
182 assert(friend_num < dht->num_friends);
183 return &dht->friends_list[friend_num];
184}
185const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num)
186{
187 assert(friend_num < dht->num_friends);
188 return dht->friends_list[friend_num].public_key;
189}
190
68/* Compares pk1 and pk2 with pk. 191/* Compares pk1 and pk2 with pk.
69 * 192 *
70 * return 0 if both are same distance. 193 * return 0 if both are same distance.
@@ -73,19 +196,17 @@
73 */ 196 */
74int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2) 197int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
75{ 198{
76 size_t i; 199 for (size_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
77 uint8_t distance1, distance2; 200 const uint8_t distance1 = pk[i] ^ pk1[i];
78 201 const uint8_t distance2 = pk[i] ^ pk2[i];
79 for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
80 202
81 distance1 = pk[i] ^ pk1[i]; 203 if (distance1 < distance2) {
82 distance2 = pk[i] ^ pk2[i];
83
84 if (distance1 < distance2)
85 return 1; 204 return 1;
205 }
86 206
87 if (distance1 > distance2) 207 if (distance1 > distance2) {
88 return 2; 208 return 2;
209 }
89 } 210 }
90 211
91 return 0; 212 return 0;
@@ -95,15 +216,20 @@ int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
95 */ 216 */
96static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2) 217static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
97{ 218{
98 unsigned int i, j = 0; 219 unsigned int i;
220 unsigned int j = 0;
99 221
100 for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) { 222 for (i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
101 if (pk1[i] == pk2[i]) 223 if (pk1[i] == pk2[i]) {
102 continue; 224 continue;
225 }
103 226
104 for (j = 0; j < 8; ++j) { 227 for (j = 0; j < 8; ++j) {
105 if ((pk1[i] & (1 << (7 - j))) != (pk2[i] & (1 << (7 - j)))) 228 const uint8_t mask = 1 << (7 - j);
229
230 if ((pk1[i] & mask) != (pk2[i] & mask)) {
106 break; 231 break;
232 }
107 } 233 }
108 234
109 break; 235 break;
@@ -112,113 +238,316 @@ static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
112 return i * 8 + j; 238 return i * 8 + j;
113} 239}
114 240
115/* Shared key generations are costly, it is therefor smart to store commonly used 241/* Shared key generations are costly, it is therefore smart to store commonly used
116 * ones so that they can re used later without being computed again. 242 * ones so that they can re used later without being computed again.
117 * 243 *
118 * If shared key is already in shared_keys, copy it to shared_key. 244 * If shared key is already in shared_keys, copy it to shared_key.
119 * else generate it into shared_key and copy it to shared_keys 245 * else generate it into shared_key and copy it to shared_keys
120 */ 246 */
121void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key) 247void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_t *shared_key,
248 const uint8_t *secret_key, const uint8_t *public_key)
122{ 249{
123 uint32_t i, num = ~0, curr = 0; 250 uint32_t num = ~0;
251 uint32_t curr = 0;
124 252
125 for (i = 0; i < MAX_KEYS_PER_SLOT; ++i) { 253 for (uint32_t i = 0; i < MAX_KEYS_PER_SLOT; ++i) {
126 int index = public_key[30] * MAX_KEYS_PER_SLOT + i; 254 const int index = public_key[30] * MAX_KEYS_PER_SLOT + i;
255 Shared_Key *const key = &shared_keys->keys[index];
127 256
128 if (shared_keys->keys[index].stored) { 257 if (key->stored) {
129 if (public_key_cmp(public_key, shared_keys->keys[index].public_key) == 0) { 258 if (id_equal(public_key, key->public_key)) {
130 memcpy(shared_key, shared_keys->keys[index].shared_key, crypto_box_BEFORENMBYTES); 259 memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE);
131 ++shared_keys->keys[index].times_requested; 260 ++key->times_requested;
132 shared_keys->keys[index].time_last_requested = unix_time(); 261 key->time_last_requested = mono_time_get(mono_time);
133 return; 262 return;
134 } 263 }
135 264
136 if (num != 0) { 265 if (num != 0) {
137 if (is_timeout(shared_keys->keys[index].time_last_requested, KEYS_TIMEOUT)) { 266 if (mono_time_is_timeout(mono_time, key->time_last_requested, KEYS_TIMEOUT)) {
138 num = 0; 267 num = 0;
139 curr = index; 268 curr = index;
140 } else if (num > shared_keys->keys[index].times_requested) { 269 } else if (num > key->times_requested) {
141 num = shared_keys->keys[index].times_requested; 270 num = key->times_requested;
142 curr = index; 271 curr = index;
143 } 272 }
144 } 273 }
145 } else { 274 } else if (num != 0) {
146 if (num != 0) { 275 num = 0;
147 num = 0; 276 curr = index;
148 curr = index;
149 }
150 } 277 }
151 } 278 }
152 279
153 encrypt_precompute(public_key, secret_key, shared_key); 280 encrypt_precompute(public_key, secret_key, shared_key);
154 281
155 if (num != (uint32_t)~0) { 282 if (num != UINT32_MAX) {
156 shared_keys->keys[curr].stored = 1; 283 Shared_Key *const key = &shared_keys->keys[curr];
157 shared_keys->keys[curr].times_requested = 1; 284 key->stored = true;
158 memcpy(shared_keys->keys[curr].public_key, public_key, crypto_box_PUBLICKEYBYTES); 285 key->times_requested = 1;
159 memcpy(shared_keys->keys[curr].shared_key, shared_key, crypto_box_BEFORENMBYTES); 286 memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
160 shared_keys->keys[curr].time_last_requested = unix_time(); 287 memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE);
288 key->time_last_requested = mono_time_get(mono_time);
161 } 289 }
162} 290}
163 291
164/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key 292/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
165 * for packets that we receive. 293 * for packets that we receive.
166 */ 294 */
167void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) 295void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
168{ 296{
169 get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key); 297 get_shared_key(dht->mono_time, &dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key);
170} 298}
171 299
172/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key 300/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
173 * for packets that we send. 301 * for packets that we send.
174 */ 302 */
175void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) 303void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
176{ 304{
177 get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key); 305 get_shared_key(dht->mono_time, &dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key);
178} 306}
179 307
180void to_net_family(IP *ip) 308#define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE
309
310/* Create a request to peer.
311 * send_public_key and send_secret_key are the pub/secret keys of the sender.
312 * recv_public_key is public key of receiver.
313 * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
314 * Data represents the data we send with the request with length being the length of the data.
315 * request_id is the id of the request (32 = friend request, 254 = ping request).
316 *
317 * return -1 on failure.
318 * return the length of the created packet on success.
319 */
320int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
321 const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id)
181{ 322{
182 if (ip->family == AF_INET) 323 if (!send_public_key || !packet || !recv_public_key || !data) {
183 ip->family = TOX_AF_INET; 324 return -1;
184 else if (ip->family == AF_INET6) 325 }
185 ip->family = TOX_AF_INET6; 326
327 if (MAX_CRYPTO_REQUEST_SIZE < length + CRYPTO_SIZE + 1 + CRYPTO_MAC_SIZE) {
328 return -1;
329 }
330
331 uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
332 random_nonce(nonce);
333 uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
334 memcpy(temp + 1, data, length);
335 temp[0] = request_id;
336 const int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
337 CRYPTO_SIZE + packet);
338
339 if (len == -1) {
340 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
341 return -1;
342 }
343
344 packet[0] = NET_PACKET_CRYPTO;
345 memcpy(packet + 1, recv_public_key, CRYPTO_PUBLIC_KEY_SIZE);
346 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, send_public_key, CRYPTO_PUBLIC_KEY_SIZE);
347
348 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
349 return len + CRYPTO_SIZE;
186} 350}
187 351
188int to_host_family(IP *ip) 352/* Puts the senders public key in the request in public_key, the data from the request
353 * in data if a friend or ping request was sent to us and returns the length of the data.
354 * packet is the request packet and length is its length.
355 *
356 * return -1 if not valid request.
357 */
358int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
359 uint8_t *request_id, const uint8_t *packet, uint16_t length)
189{ 360{
190 if (ip->family == TOX_AF_INET) { 361 if (!self_public_key || !public_key || !data || !request_id || !packet) {
191 ip->family = AF_INET; 362 return -1;
192 return 0; 363 }
193 } else if (ip->family == TOX_AF_INET6) { 364
194 ip->family = AF_INET6; 365 if (length <= CRYPTO_SIZE + CRYPTO_MAC_SIZE || length > MAX_CRYPTO_REQUEST_SIZE) {
195 return 0; 366 return -1;
196 } else { 367 }
368
369 if (!id_equal(packet + 1, self_public_key)) {
370 return -1;
371 }
372
373 memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
374 const uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
375 uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
376 int len1 = decrypt_data(public_key, self_secret_key, nonce,
377 packet + CRYPTO_SIZE, length - CRYPTO_SIZE, temp);
378
379 if (len1 == -1 || len1 == 0) {
380 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
197 return -1; 381 return -1;
198 } 382 }
383
384 request_id[0] = temp[0];
385 --len1;
386 memcpy(data, temp + 1, len1);
387 crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
388 return len1;
199} 389}
200 390
201#define PACKED_NODE_SIZE_IP4 (1 + SIZE_IP4 + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES) 391#define PACKED_NODE_SIZE_IP4 (1 + SIZE_IP4 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
202#define PACKED_NODE_SIZE_IP6 (1 + SIZE_IP6 + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES) 392#define PACKED_NODE_SIZE_IP6 (1 + SIZE_IP6 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
203 393
204/* Return packet size of packed node with ip_family on success. 394/* Return packet size of packed node with ip_family on success.
205 * Return -1 on failure. 395 * Return -1 on failure.
206 */ 396 */
207int packed_node_size(uint8_t ip_family) 397int packed_node_size(Family ip_family)
208{ 398{
209 if (ip_family == AF_INET) { 399 if (net_family_is_ipv4(ip_family) || net_family_is_tcp_ipv4(ip_family)) {
210 return PACKED_NODE_SIZE_IP4;
211 } else if (ip_family == TCP_INET) {
212 return PACKED_NODE_SIZE_IP4; 400 return PACKED_NODE_SIZE_IP4;
213 } else if (ip_family == AF_INET6) { 401 }
214 return PACKED_NODE_SIZE_IP6; 402
215 } else if (ip_family == TCP_INET6) { 403 if (net_family_is_ipv6(ip_family) || net_family_is_tcp_ipv6(ip_family)) {
216 return PACKED_NODE_SIZE_IP6; 404 return PACKED_NODE_SIZE_IP6;
405 }
406
407 return -1;
408}
409
410
411/* Packs an IP_Port structure into data of max size length.
412 *
413 * Returns size of packed IP_Port data on success
414 * Return -1 on failure.
415 */
416int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port)
417{
418 if (data == nullptr) {
419 return -1;
420 }
421
422 bool is_ipv4;
423 uint8_t net_family;
424
425 if (net_family_is_ipv4(ip_port->ip.family)) {
426 // TODO(irungentoo): use functions to convert endianness
427 is_ipv4 = true;
428 net_family = TOX_AF_INET;
429 } else if (net_family_is_tcp_ipv4(ip_port->ip.family)) {
430 is_ipv4 = true;
431 net_family = TOX_TCP_INET;
432 } else if (net_family_is_ipv6(ip_port->ip.family)) {
433 is_ipv4 = false;
434 net_family = TOX_AF_INET6;
435 } else if (net_family_is_tcp_ipv6(ip_port->ip.family)) {
436 is_ipv4 = false;
437 net_family = TOX_TCP_INET6;
217 } else { 438 } else {
218 return -1; 439 return -1;
219 } 440 }
441
442 if (is_ipv4) {
443 const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
444
445 if (size > length) {
446 return -1;
447 }
448
449 data[0] = net_family;
450 memcpy(data + 1, &ip_port->ip.ip.v4, SIZE_IP4);
451 memcpy(data + 1 + SIZE_IP4, &ip_port->port, sizeof(uint16_t));
452 return size;
453 } else {
454 const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
455
456 if (size > length) {
457 return -1;
458 }
459
460 data[0] = net_family;
461 memcpy(data + 1, &ip_port->ip.ip.v6, SIZE_IP6);
462 memcpy(data + 1 + SIZE_IP6, &ip_port->port, sizeof(uint16_t));
463 return size;
464 }
220} 465}
221 466
467static int dht_create_packet(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
468 const uint8_t *shared_key, const uint8_t type, uint8_t *plain, size_t plain_length, uint8_t *packet)
469{
470 VLA(uint8_t, encrypted, plain_length + CRYPTO_MAC_SIZE);
471 uint8_t nonce[CRYPTO_NONCE_SIZE];
472
473 random_nonce(nonce);
474
475 const int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted);
476
477 if (encrypted_length == -1) {
478 return -1;
479 }
480
481 packet[0] = type;
482 memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
483 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
484 memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypted, encrypted_length);
485
486 return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length;
487}
488
489/* Unpack IP_Port structure from data of max size length into ip_port.
490 *
491 * Return size of unpacked ip_port on success.
492 * Return -1 on failure.
493 */
494int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled)
495{
496 if (data == nullptr) {
497 return -1;
498 }
499
500 bool is_ipv4;
501 Family host_family;
502
503 if (data[0] == TOX_AF_INET) {
504 is_ipv4 = true;
505 host_family = net_family_ipv4;
506 } else if (data[0] == TOX_TCP_INET) {
507 if (!tcp_enabled) {
508 return -1;
509 }
510
511 is_ipv4 = true;
512 host_family = net_family_tcp_ipv4;
513 } else if (data[0] == TOX_AF_INET6) {
514 is_ipv4 = false;
515 host_family = net_family_ipv6;
516 } else if (data[0] == TOX_TCP_INET6) {
517 if (!tcp_enabled) {
518 return -1;
519 }
520
521 is_ipv4 = false;
522 host_family = net_family_tcp_ipv6;
523 } else {
524 return -1;
525 }
526
527 if (is_ipv4) {
528 const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
529
530 if (size > length) {
531 return -1;
532 }
533
534 ip_port->ip.family = host_family;
535 memcpy(&ip_port->ip.ip.v4, data + 1, SIZE_IP4);
536 memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t));
537 return size;
538 } else {
539 const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
540
541 if (size > length) {
542 return -1;
543 }
544
545 ip_port->ip.family = host_family;
546 memcpy(&ip_port->ip.ip.v6, data + 1, SIZE_IP6);
547 memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t));
548 return size;
549 }
550}
222 551
223/* Pack number of nodes into data of maxlength length. 552/* Pack number of nodes into data of maxlength length.
224 * 553 *
@@ -227,54 +556,28 @@ int packed_node_size(uint8_t ip_family)
227 */ 556 */
228int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number) 557int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number)
229{ 558{
230 uint32_t i, packed_length = 0; 559 uint32_t packed_length = 0;
231
232 for (i = 0; i < number; ++i) {
233 int ipv6 = -1;
234 uint8_t net_family;
235
236 // FIXME use functions to convert endianness
237 if (nodes[i].ip_port.ip.family == AF_INET) {
238 ipv6 = 0;
239 net_family = TOX_AF_INET;
240 } else if (nodes[i].ip_port.ip.family == TCP_INET) {
241 ipv6 = 0;
242 net_family = TOX_TCP_INET;
243 } else if (nodes[i].ip_port.ip.family == AF_INET6) {
244 ipv6 = 1;
245 net_family = TOX_AF_INET6;
246 } else if (nodes[i].ip_port.ip.family == TCP_INET6) {
247 ipv6 = 1;
248 net_family = TOX_TCP_INET6;
249 } else {
250 return -1;
251 }
252
253 if (ipv6 == 0) {
254 uint32_t size = PACKED_NODE_SIZE_IP4;
255 560
256 if (packed_length + size > length) 561 for (uint32_t i = 0; i < number && packed_length < length; ++i) {
257 return -1; 562 const int ipp_size = pack_ip_port(data + packed_length, length - packed_length, &nodes[i].ip_port);
258 563
259 data[packed_length] = net_family; 564 if (ipp_size == -1) {
260 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, SIZE_IP4); 565 return -1;
261 memcpy(data + packed_length + 1 + SIZE_IP4, &nodes[i].ip_port.port, sizeof(uint16_t)); 566 }
262 memcpy(data + packed_length + 1 + SIZE_IP4 + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES);
263 packed_length += size;
264 } else if (ipv6 == 1) {
265 uint32_t size = PACKED_NODE_SIZE_IP6;
266 567
267 if (packed_length + size > length) 568 packed_length += ipp_size;
268 return -1;
269 569
270 data[packed_length] = net_family; 570 if (packed_length + CRYPTO_PUBLIC_KEY_SIZE > length) {
271 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, SIZE_IP6);
272 memcpy(data + packed_length + 1 + SIZE_IP6, &nodes[i].ip_port.port, sizeof(uint16_t));
273 memcpy(data + packed_length + 1 + SIZE_IP6 + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES);
274 packed_length += size;
275 } else {
276 return -1; 571 return -1;
277 } 572 }
573
574 memcpy(data + packed_length, nodes[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
575 packed_length += CRYPTO_PUBLIC_KEY_SIZE;
576
577#ifndef NDEBUG
578 const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
579#endif
580 assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
278 } 581 }
279 582
280 return packed_length; 583 return packed_length;
@@ -288,214 +591,197 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_
288 * return -1 on failure. 591 * return -1 on failure.
289 */ 592 */
290int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data, 593int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
291 uint16_t length, uint8_t tcp_enabled) 594 uint16_t length, bool tcp_enabled)
292{ 595{
293 uint32_t num = 0, len_processed = 0; 596 uint32_t num = 0, len_processed = 0;
294 597
295 while (num < max_num_nodes && len_processed < length) { 598 while (num < max_num_nodes && len_processed < length) {
296 int ipv6 = -1; 599 const int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled);
297 uint8_t host_family; 600
298 601 if (ipp_size == -1) {
299 if (data[len_processed] == TOX_AF_INET) {
300 ipv6 = 0;
301 host_family = AF_INET;
302 } else if (data[len_processed] == TOX_TCP_INET) {
303 if (!tcp_enabled)
304 return -1;
305
306 ipv6 = 0;
307 host_family = TCP_INET;
308 } else if (data[len_processed] == TOX_AF_INET6) {
309 ipv6 = 1;
310 host_family = AF_INET6;
311 } else if (data[len_processed] == TOX_TCP_INET6) {
312 if (!tcp_enabled)
313 return -1;
314
315 ipv6 = 1;
316 host_family = TCP_INET6;
317 } else {
318 return -1; 602 return -1;
319 } 603 }
320 604
321 if (ipv6 == 0) { 605 len_processed += ipp_size;
322 uint32_t size = PACKED_NODE_SIZE_IP4;
323
324 if (len_processed + size > length)
325 return -1;
326
327 nodes[num].ip_port.ip.family = host_family;
328 memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, SIZE_IP4);
329 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + SIZE_IP4, sizeof(uint16_t));
330 memcpy(nodes[num].public_key, data + len_processed + 1 + SIZE_IP4 + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES);
331 len_processed += size;
332 ++num;
333 } else if (ipv6 == 1) {
334 uint32_t size = PACKED_NODE_SIZE_IP6;
335 606
336 if (len_processed + size > length) 607 if (len_processed + CRYPTO_PUBLIC_KEY_SIZE > length) {
337 return -1;
338
339 nodes[num].ip_port.ip.family = host_family;
340 memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, SIZE_IP6);
341 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + SIZE_IP6, sizeof(uint16_t));
342 memcpy(nodes[num].public_key, data + len_processed + 1 + SIZE_IP6 + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES);
343 len_processed += size;
344 ++num;
345 } else {
346 return -1; 608 return -1;
347 } 609 }
610
611 memcpy(nodes[num].public_key, data + len_processed, CRYPTO_PUBLIC_KEY_SIZE);
612 len_processed += CRYPTO_PUBLIC_KEY_SIZE;
613 ++num;
614
615#ifndef NDEBUG
616 const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
617#endif
618 assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
348 } 619 }
349 620
350 if (processed_data_len) 621 if (processed_data_len) {
351 *processed_data_len = len_processed; 622 *processed_data_len = len_processed;
623 }
352 624
353 return num; 625 return num;
354} 626}
355 627
356 628/* Find index of ##type with public_key equal to pk.
357
358/* Check if client with public_key is already in list of length length.
359 * If it is then set its corresponding timestamp to current time.
360 * If the id is already in the list with a different ip_port, update it.
361 * TODO: Maybe optimize this.
362 * 629 *
363 * return True(1) or False(0) 630 * return index or UINT32_MAX if not found.
364 */ 631 */
365static int client_or_ip_port_in_list(Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port) 632#define INDEX_OF_PK(array, size, pk) \
366{ 633 do { \
367 uint32_t i; 634 for (uint32_t i = 0; i < size; ++i) { \
368 uint64_t temp_time = unix_time(); 635 if (id_equal(array[i].public_key, pk)) { \
636 return i; \
637 } \
638 } \
639 \
640 return UINT32_MAX; \
641 } while (0)
369 642
370 /* if public_key is in list, find it and maybe overwrite ip_port */ 643static uint32_t index_of_client_pk(const Client_data *array, uint32_t size, const uint8_t *pk)
371 for (i = 0; i < length; ++i) 644{
372 if (id_equal(list[i].public_key, public_key)) { 645 INDEX_OF_PK(array, size, pk);
373 /* Refresh the client timestamp. */ 646}
374 if (ip_port.ip.family == AF_INET) {
375
376 LOGGER_SCOPE( if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
377 LOGGER_TRACE("coipil[%u]: switching ipv4 from %s:%u to %s:%u", i,
378 ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port),
379 ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
380 }
381 );
382
383 if (LAN_ip(list[i].assoc4.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0)
384 return 1;
385
386 list[i].assoc4.ip_port = ip_port;
387 list[i].assoc4.timestamp = temp_time;
388 } else if (ip_port.ip.family == AF_INET6) {
389
390 LOGGER_SCOPE( if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
391 LOGGER_TRACE("coipil[%u]: switching ipv6 from %s:%u to %s:%u", i,
392 ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port),
393 ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
394 }
395 );
396 647
397 if (LAN_ip(list[i].assoc6.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) 648static uint32_t index_of_friend_pk(const DHT_Friend *array, uint32_t size, const uint8_t *pk)
398 return 1; 649{
650 INDEX_OF_PK(array, size, pk);
651}
399 652
400 list[i].assoc6.ip_port = ip_port; 653static uint32_t index_of_node_pk(const Node_format *array, uint32_t size, const uint8_t *pk)
401 list[i].assoc6.timestamp = temp_time; 654{
402 } 655 INDEX_OF_PK(array, size, pk);
656}
403 657
404 return 1; 658/* Find index of Client_data with ip_port equal to param ip_port.
659 *
660 * return index or UINT32_MAX if not found.
661 */
662static uint32_t index_of_client_ip_port(const Client_data *array, uint32_t size, const IP_Port *ip_port)
663{
664 for (uint32_t i = 0; i < size; ++i) {
665 if ((net_family_is_ipv4(ip_port->ip.family) && ipport_equal(&array[i].assoc4.ip_port, ip_port)) ||
666 (net_family_is_ipv6(ip_port->ip.family) && ipport_equal(&array[i].assoc6.ip_port, ip_port))) {
667 return i;
405 } 668 }
669 }
406 670
407 /* public_key not in list yet: see if we can find an identical ip_port, in 671 return UINT32_MAX;
408 * that case we kill the old public_key by overwriting it with the new one 672}
409 * TODO: maybe we SHOULDN'T do that if that public_key is in a friend_list 673
410 * and the one who is the actual friend's public_key/address set? */ 674/* Update ip_port of client if it's needed.
411 for (i = 0; i < length; ++i) { 675 */
412 /* MAYBE: check the other address, if valid, don't nuke? */ 676static void update_client(const Logger *log, const Mono_Time *mono_time, int index, Client_data *client,
413 if ((ip_port.ip.family == AF_INET) && ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { 677 IP_Port ip_port)
414 /* Initialize client timestamp. */ 678{
415 list[i].assoc4.timestamp = temp_time; 679 IPPTsPng *assoc;
416 memcpy(list[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); 680 int ip_version;
417 681
418 LOGGER_DEBUG("coipil[%u]: switching public_key (ipv4)", i); 682 if (net_family_is_ipv4(ip_port.ip.family)) {
419 683 assoc = &client->assoc4;
420 /* kill the other address, if it was set */ 684 ip_version = 4;
421 memset(&list[i].assoc6, 0, sizeof(list[i].assoc6)); 685 } else if (net_family_is_ipv6(ip_port.ip.family)) {
422 return 1; 686 assoc = &client->assoc6;
423 } else if ((ip_port.ip.family == AF_INET6) && ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { 687 ip_version = 6;
424 /* Initialize client timestamp. */ 688 } else {
425 list[i].assoc6.timestamp = temp_time; 689 return;
426 memcpy(list[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); 690 }
427 691
428 LOGGER_DEBUG("coipil[%u]: switching public_key (ipv6)", i); 692 if (!ipport_equal(&assoc->ip_port, &ip_port)) {
693 char ip_str[IP_NTOA_LEN];
694 LOGGER_TRACE(log, "coipil[%u]: switching ipv%d from %s:%u to %s:%u",
695 index, ip_version,
696 ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
697 net_ntohs(assoc->ip_port.port),
698 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)),
699 net_ntohs(ip_port.port));
700 }
429 701
430 /* kill the other address, if it was set */ 702 if (!ip_is_lan(assoc->ip_port.ip) && ip_is_lan(ip_port.ip)) {
431 memset(&list[i].assoc4, 0, sizeof(list[i].assoc4)); 703 return;
432 return 1;
433 }
434 } 704 }
435 705
436 return 0; 706 assoc->ip_port = ip_port;
707 assoc->timestamp = mono_time_get(mono_time);
437} 708}
438 709
439/* Check if client with public_key is already in node format list of length length. 710/* Check if client with public_key is already in list of length length.
711 * If it is then set its corresponding timestamp to current time.
712 * If the id is already in the list with a different ip_port, update it.
713 * TODO(irungentoo): Maybe optimize this.
440 * 714 *
441 * return 1 if true. 715 * return True(1) or False(0)
442 * return 0 if false.
443 */ 716 */
444static int client_in_nodelist(const Node_format *list, uint16_t length, const uint8_t *public_key) 717static int client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_time, Client_data *list, uint16_t length,
718 const uint8_t *public_key, IP_Port ip_port)
445{ 719{
446 uint32_t i; 720 const uint64_t temp_time = mono_time_get(mono_time);
721 uint32_t index = index_of_client_pk(list, length, public_key);
447 722
448 for (i = 0; i < length; ++i) { 723 /* if public_key is in list, find it and maybe overwrite ip_port */
449 if (id_equal(list[i].public_key, public_key)) 724 if (index != UINT32_MAX) {
450 return 1; 725 update_client(log, mono_time, index, &list[index], ip_port);
726 return 1;
451 } 727 }
452 728
453 return 0; 729 /* public_key not in list yet: see if we can find an identical ip_port, in
454} 730 * that case we kill the old public_key by overwriting it with the new one
731 * TODO(irungentoo): maybe we SHOULDN'T do that if that public_key is in a friend_list
732 * and the one who is the actual friend's public_key/address set?
733 * MAYBE: check the other address, if valid, don't nuke? */
734 index = index_of_client_ip_port(list, length, &ip_port);
455 735
456/* return friend number from the public_key. 736 if (index == UINT32_MAX) {
457 * return -1 if a failure occurs. 737 return 0;
458 */ 738 }
459static int friend_number(const DHT *dht, const uint8_t *public_key)
460{
461 uint32_t i;
462 739
463 for (i = 0; i < dht->num_friends; ++i) { 740 IPPTsPng *assoc;
464 if (id_equal(dht->friends_list[i].public_key, public_key)) 741 int ip_version;
465 return i; 742
743 if (net_family_is_ipv4(ip_port.ip.family)) {
744 assoc = &list[index].assoc4;
745 ip_version = 4;
746 } else {
747 assoc = &list[index].assoc6;
748 ip_version = 6;
466 } 749 }
467 750
468 return -1; 751 /* Initialize client timestamp. */
469} 752 assoc->timestamp = temp_time;
753 memcpy(list[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
470 754
471/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list. 755 LOGGER_DEBUG(log, "coipil[%u]: switching public_key (ipv%d)", index, ip_version);
472 */
473_Bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
474 const uint8_t *cmp_pk)
475{
476 uint8_t pk_bak[crypto_box_PUBLICKEYBYTES];
477 IP_Port ip_port_bak;
478 756
479 unsigned int i; 757 /* kill the other address, if it was set */
758 memset(assoc, 0, sizeof(IPPTsPng));
759 return 1;
760}
480 761
481 for (i = 0; i < length; ++i) { 762bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, IP_Port ip_port,
763 const uint8_t *cmp_pk)
764{
765 for (uint32_t i = 0; i < length; ++i) {
482 if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) { 766 if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) {
483 memcpy(pk_bak, nodes_list[i].public_key, crypto_box_PUBLICKEYBYTES); 767 uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];
484 ip_port_bak = nodes_list[i].ip_port; 768 memcpy(pk_bak, nodes_list[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
485 memcpy(nodes_list[i].public_key, pk, crypto_box_PUBLICKEYBYTES); 769 const IP_Port ip_port_bak = nodes_list[i].ip_port;
770 memcpy(nodes_list[i].public_key, pk, CRYPTO_PUBLIC_KEY_SIZE);
486 nodes_list[i].ip_port = ip_port; 771 nodes_list[i].ip_port = ip_port;
487 772
488 if (i != (length - 1)) 773 if (i != length - 1) {
489 add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk); 774 add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk);
775 }
490 776
491 return 1; 777 return true;
492 } 778 }
493 } 779 }
494 780
495 return 0; 781 return false;
496} 782}
497 783
498/*TODO: change this to 7 when done*/ 784/* TODO(irungentoo): change this to 7 when done*/
499#define HARDENING_ALL_OK 2 785#define HARDENING_ALL_OK 2
500/* return 0 if not. 786/* return 0 if not.
501 * return 1 if route request are ok 787 * return 1 if route request are ok
@@ -510,56 +796,55 @@ static uint8_t hardening_correct(const Hardening *h)
510/* 796/*
511 * helper for get_close_nodes(). argument list is a monster :D 797 * helper for get_close_nodes(). argument list is a monster :D
512 */ 798 */
513static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list, 799static void get_close_nodes_inner(const Mono_Time *mono_time, const uint8_t *public_key, Node_format *nodes_list,
514 sa_family_t sa_family, const Client_data *client_list, uint32_t client_list_length, 800 Family sa_family, const Client_data *client_list, uint32_t client_list_length,
515 uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) 801 uint32_t *num_nodes_ptr, bool is_LAN, uint8_t want_good)
516{ 802{
517 if ((sa_family != AF_INET) && (sa_family != AF_INET6) && (sa_family != 0)) 803 if (!net_family_is_ipv4(sa_family) && !net_family_is_ipv6(sa_family) && !net_family_is_unspec(sa_family)) {
518 return; 804 return;
805 }
519 806
520 uint32_t num_nodes = *num_nodes_ptr; 807 uint32_t num_nodes = *num_nodes_ptr;
521 uint32_t i;
522 808
523 for (i = 0; i < client_list_length; i++) { 809 for (uint32_t i = 0; i < client_list_length; ++i) {
524 const Client_data *client = &client_list[i]; 810 const Client_data *const client = &client_list[i];
525 811
526 /* node already in list? */ 812 /* node already in list? */
527 if (client_in_nodelist(nodes_list, MAX_SENT_NODES, client->public_key)) 813 if (index_of_node_pk(nodes_list, MAX_SENT_NODES, client->public_key) != UINT32_MAX) {
528 continue; 814 continue;
815 }
529 816
530 const IPPTsPng *ipptp = NULL; 817 const IPPTsPng *ipptp = nullptr;
531 818
532 if (sa_family == AF_INET) { 819 if (net_family_is_ipv4(sa_family)) {
533 ipptp = &client->assoc4; 820 ipptp = &client->assoc4;
534 } else if (sa_family == AF_INET6) { 821 } else if (net_family_is_ipv6(sa_family)) {
535 ipptp = &client->assoc6; 822 ipptp = &client->assoc6;
823 } else if (client->assoc4.timestamp >= client->assoc6.timestamp) {
824 ipptp = &client->assoc4;
536 } else { 825 } else {
537 if (client->assoc4.timestamp >= client->assoc6.timestamp) { 826 ipptp = &client->assoc6;
538 ipptp = &client->assoc4;
539 } else {
540 ipptp = &client->assoc6;
541 }
542 } 827 }
543 828
544 /* node not in a good condition? */ 829 /* node not in a good condition? */
545 if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) 830 if (mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) {
546 continue; 831 continue;
832 }
547 833
548 /* don't send LAN ips to non LAN peers */ 834 /* don't send LAN ips to non LAN peers */
549 if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) 835 if (ip_is_lan(ipptp->ip_port.ip) && !is_LAN) {
550 continue; 836 continue;
837 }
551 838
552 if (LAN_ip(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK 839 if (!ip_is_lan(ipptp->ip_port.ip) && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK
553 && !id_equal(public_key, client->public_key)) 840 && !id_equal(public_key, client->public_key)) {
554 continue; 841 continue;
842 }
555 843
556 if (num_nodes < MAX_SENT_NODES) { 844 if (num_nodes < MAX_SENT_NODES) {
557 memcpy(nodes_list[num_nodes].public_key, 845 memcpy(nodes_list[num_nodes].public_key, client->public_key, CRYPTO_PUBLIC_KEY_SIZE);
558 client->public_key,
559 crypto_box_PUBLICKEYBYTES );
560
561 nodes_list[num_nodes].ip_port = ipptp->ip_port; 846 nodes_list[num_nodes].ip_port = ipptp->ip_port;
562 num_nodes++; 847 ++num_nodes;
563 } else { 848 } else {
564 add_to_list(nodes_list, MAX_SENT_NODES, client->public_key, ipptp->ip_port, public_key); 849 add_to_list(nodes_list, MAX_SENT_NODES, client->public_key, ipptp->ip_port, public_key);
565 } 850 }
@@ -571,130 +856,105 @@ static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_
571/* Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request: 856/* Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request:
572 * put them in the nodes_list and return how many were found. 857 * put them in the nodes_list and return how many were found.
573 * 858 *
574 * TODO: For the love of based <your favorite deity, in doubt use "love"> make 859 * TODO(irungentoo): For the love of based <your favorite deity, in doubt use
575 * this function cleaner and much more efficient. 860 * "love"> make this function cleaner and much more efficient.
576 * 861 *
577 * want_good : do we want only good nodes as checked with the hardening returned or not? 862 * want_good : do we want only good nodes as checked with the hardening returned or not?
578 */ 863 */
579static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, 864static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list,
580 sa_family_t sa_family, uint8_t is_LAN, uint8_t want_good) 865 Family sa_family, bool is_LAN, uint8_t want_good)
581{ 866{
582 uint32_t num_nodes = 0, i; 867 uint32_t num_nodes = 0;
583 get_close_nodes_inner(public_key, nodes_list, sa_family, 868 get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
584 dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0); 869 dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0);
585 870
586 /*TODO uncomment this when hardening is added to close friend clients 871 /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */
587 for (i = 0; i < dht->num_friends; ++i) 872#if 0
588 get_close_nodes_inner(dht, public_key, nodes_list, sa_family, 873
589 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 874 for (uint32_t i = 0; i < dht->num_friends; ++i) {
590 &num_nodes, is_LAN, want_good); 875 get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
591 */ 876 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
592 for (i = 0; i < dht->num_friends; ++i) 877 &num_nodes, is_LAN, want_good);
593 get_close_nodes_inner(public_key, nodes_list, sa_family, 878 }
879
880#endif
881
882 for (uint32_t i = 0; i < dht->num_friends; ++i) {
883 get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
594 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 884 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
595 &num_nodes, is_LAN, 0); 885 &num_nodes, is_LAN, 0);
886 }
596 887
597 return num_nodes; 888 return num_nodes;
598} 889}
599 890
600int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, sa_family_t sa_family, 891int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
601 uint8_t is_LAN, uint8_t want_good) 892 bool is_LAN, uint8_t want_good)
602{ 893{
603 memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format)); 894 memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format));
604#ifdef ENABLE_ASSOC_DHT 895 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
605 896}
606 if (!dht->assoc)
607#endif
608 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
609
610#ifdef ENABLE_ASSOC_DHT
611 //TODO: assoc, sa_family 0 (don't care if ipv4 or ipv6) support.
612 Client_data *result[MAX_SENT_NODES];
613
614 Assoc_close_entries request;
615 memset(&request, 0, sizeof(request));
616 request.count = MAX_SENT_NODES;
617 request.count_good = MAX_SENT_NODES - 2; /* allow 2 'indirect' nodes */
618 request.result = result;
619 request.wanted_id = public_key;
620 request.flags = (is_LAN ? LANOk : 0) + (sa_family == AF_INET ? ProtoIPv4 : ProtoIPv6);
621
622 uint8_t num_found = Assoc_get_close_entries(dht->assoc, &request);
623
624 if (!num_found) {
625 LOGGER_DEBUG("get_close_nodes(): Assoc_get_close_entries() returned zero nodes");
626 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
627 }
628
629 LOGGER_DEBUG("get_close_nodes(): Assoc_get_close_entries() returned %i 'direct' and %i 'indirect' nodes",
630 request.count_good, num_found - request.count_good);
631
632 uint8_t i, num_returned = 0;
633
634 for (i = 0; i < num_found; i++) {
635 Client_data *client = result[i];
636 897
637 if (client) { 898typedef struct DHT_Cmp_data {
638 id_copy(nodes_list[num_returned].public_key, client->public_key); 899 const Mono_Time *mono_time;
900 const uint8_t *base_public_key;
901 Client_data entry;
902} DHT_Cmp_data;
639 903
640 if (sa_family == AF_INET) 904static bool assoc_timeout(const Mono_Time *mono_time, const IPPTsPng *assoc)
641 if (ipport_isset(&client->assoc4.ip_port)) { 905{
642 nodes_list[num_returned].ip_port = client->assoc4.ip_port; 906 return mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT);
643 num_returned++; 907}
644 continue;
645 }
646
647 if (sa_family == AF_INET6)
648 if (ipport_isset(&client->assoc6.ip_port)) {
649 nodes_list[num_returned].ip_port = client->assoc6.ip_port;
650 num_returned++;
651 continue;
652 }
653 }
654 }
655 908
656 return num_returned; 909static bool incorrect_hardening(const IPPTsPng *assoc)
657#endif 910{
911 return hardening_correct(&assoc->hardening) != HARDENING_ALL_OK;
658} 912}
659 913
660static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES];
661static int cmp_dht_entry(const void *a, const void *b) 914static int cmp_dht_entry(const void *a, const void *b)
662{ 915{
663 Client_data entry1, entry2; 916 DHT_Cmp_data cmp1, cmp2;
664 memcpy(&entry1, a, sizeof(Client_data)); 917 memcpy(&cmp1, a, sizeof(DHT_Cmp_data));
665 memcpy(&entry2, b, sizeof(Client_data)); 918 memcpy(&cmp2, b, sizeof(DHT_Cmp_data));
666 int t1 = is_timeout(entry1.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry1.assoc6.timestamp, BAD_NODE_TIMEOUT); 919 const Client_data entry1 = cmp1.entry;
667 int t2 = is_timeout(entry2.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry2.assoc6.timestamp, BAD_NODE_TIMEOUT); 920 const Client_data entry2 = cmp2.entry;
921 const uint8_t *cmp_public_key = cmp1.base_public_key;
922
923 bool t1 = assoc_timeout(cmp1.mono_time, &entry1.assoc4) && assoc_timeout(cmp1.mono_time, &entry1.assoc6);
924 bool t2 = assoc_timeout(cmp2.mono_time, &entry2.assoc4) && assoc_timeout(cmp2.mono_time, &entry2.assoc6);
668 925
669 if (t1 && t2) 926 if (t1 && t2) {
670 return 0; 927 return 0;
928 }
671 929
672 if (t1) 930 if (t1) {
673 return -1; 931 return -1;
932 }
674 933
675 if (t2) 934 if (t2) {
676 return 1; 935 return 1;
936 }
677 937
678 t1 = hardening_correct(&entry1.assoc4.hardening) != HARDENING_ALL_OK 938 t1 = incorrect_hardening(&entry1.assoc4) && incorrect_hardening(&entry1.assoc6);
679 && hardening_correct(&entry1.assoc6.hardening) != HARDENING_ALL_OK; 939 t2 = incorrect_hardening(&entry2.assoc4) && incorrect_hardening(&entry2.assoc6);
680 t2 = hardening_correct(&entry2.assoc4.hardening) != HARDENING_ALL_OK
681 && hardening_correct(&entry2.assoc6.hardening) != HARDENING_ALL_OK;
682 940
683 if (t1 != t2) { 941 if (t1 && !t2) {
684 if (t1) 942 return -1;
685 return -1; 943 }
686 944
687 if (t2) 945 if (!t1 && t2) {
688 return 1; 946 return 1;
689 } 947 }
690 948
691 int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); 949 const int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
692 950
693 if (close == 1) 951 if (close == 1) {
694 return 1; 952 return 1;
953 }
695 954
696 if (close == 2) 955 if (close == 2) {
697 return -1; 956 return -1;
957 }
698 958
699 return 0; 959 return 0;
700} 960}
@@ -704,20 +964,56 @@ static int cmp_dht_entry(const void *a, const void *b)
704 * return 0 if node can't be stored. 964 * return 0 if node can't be stored.
705 * return 1 if it can. 965 * return 1 if it can.
706 */ 966 */
707static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key) 967static unsigned int store_node_ok(const Client_data *client, const Mono_Time *mono_time, const uint8_t *public_key,
968 const uint8_t *comp_public_key)
708{ 969{
709 if ((is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) 970 return (mono_time_is_timeout(mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)
710 || (id_closest(comp_public_key, client->public_key, public_key) == 2)) { 971 && mono_time_is_timeout(mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT))
711 return 1; 972 || id_closest(comp_public_key, client->public_key, public_key) == 2;
712 } else { 973}
713 return 0; 974
975static void sort_client_list(Client_data *list, const Mono_Time *mono_time, unsigned int length,
976 const uint8_t *comp_public_key)
977{
978 // Pass comp_public_key to qsort with each Client_data entry, so the
979 // comparison function can use it as the base of comparison.
980 VLA(DHT_Cmp_data, cmp_list, length);
981
982 for (uint32_t i = 0; i < length; ++i) {
983 cmp_list[i].mono_time = mono_time;
984 cmp_list[i].base_public_key = comp_public_key;
985 cmp_list[i].entry = list[i];
986 }
987
988 qsort(cmp_list, length, sizeof(DHT_Cmp_data), cmp_dht_entry);
989
990 for (uint32_t i = 0; i < length; ++i) {
991 list[i] = cmp_list[i].entry;
714 } 992 }
715} 993}
716 994
717static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) 995static void update_client_with_reset(const Mono_Time *mono_time, Client_data *client, const IP_Port *ip_port)
718{ 996{
719 memcpy(cmp_public_key, comp_public_key, crypto_box_PUBLICKEYBYTES); 997 IPPTsPng *ipptp_write = nullptr;
720 qsort(list, length, sizeof(Client_data), cmp_dht_entry); 998 IPPTsPng *ipptp_clear = nullptr;
999
1000 if (net_family_is_ipv4(ip_port->ip.family)) {
1001 ipptp_write = &client->assoc4;
1002 ipptp_clear = &client->assoc6;
1003 } else {
1004 ipptp_write = &client->assoc6;
1005 ipptp_clear = &client->assoc4;
1006 }
1007
1008 ipptp_write->ip_port = *ip_port;
1009 ipptp_write->timestamp = mono_time_get(mono_time);
1010
1011 ip_reset(&ipptp_write->ret_ip_port.ip);
1012 ipptp_write->ret_ip_port.port = 0;
1013 ipptp_write->ret_timestamp = 0;
1014
1015 /* zero out other address */
1016 memset(ipptp_clear, 0, sizeof(*ipptp_clear));
721} 1017}
722 1018
723/* Replace a first bad (or empty) node with this one 1019/* Replace a first bad (or empty) node with this one
@@ -732,47 +1028,30 @@ static void sort_client_list(Client_data *list, unsigned int length, const uint8
732 * and all nodes in the list are closer to comp_public_key 1028 * and all nodes in the list are closer to comp_public_key
733 * than public_key. 1029 * than public_key.
734 * 1030 *
735 * returns True(1) when the item was stored, False(0) otherwise */ 1031 * returns true when the item was stored, false otherwise */
736static int replace_all( Client_data *list, 1032static bool replace_all(const Mono_Time *mono_time,
737 uint16_t length, 1033 Client_data *list,
738 const uint8_t *public_key, 1034 uint16_t length,
739 IP_Port ip_port, 1035 const uint8_t *public_key,
740 const uint8_t *comp_public_key ) 1036 IP_Port ip_port,
741{ 1037 const uint8_t *comp_public_key)
742 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) 1038{
743 return 0; 1039 if (!net_family_is_ipv4(ip_port.ip.family) && !net_family_is_ipv6(ip_port.ip.family)) {
744 1040 return false;
745 if (store_node_ok(&list[1], public_key, comp_public_key) || store_node_ok(&list[0], public_key, comp_public_key)) { 1041 }
746 sort_client_list(list, length, comp_public_key);
747
748 IPPTsPng *ipptp_write = NULL;
749 IPPTsPng *ipptp_clear = NULL;
750
751 Client_data *client = &list[0];
752
753 if (ip_port.ip.family == AF_INET) {
754 ipptp_write = &client->assoc4;
755 ipptp_clear = &client->assoc6;
756 } else {
757 ipptp_write = &client->assoc6;
758 ipptp_clear = &client->assoc4;
759 }
760 1042
761 id_copy(client->public_key, public_key); 1043 if (!store_node_ok(&list[1], mono_time, public_key, comp_public_key) &&
762 ipptp_write->ip_port = ip_port; 1044 !store_node_ok(&list[0], mono_time, public_key, comp_public_key)) {
763 ipptp_write->timestamp = unix_time(); 1045 return false;
1046 }
764 1047
765 ip_reset(&ipptp_write->ret_ip_port.ip); 1048 sort_client_list(list, mono_time, length, comp_public_key);
766 ipptp_write->ret_ip_port.port = 0;
767 ipptp_write->ret_timestamp = 0;
768 1049
769 /* zero out other address */ 1050 Client_data *const client = &list[0];
770 memset(ipptp_clear, 0, sizeof(*ipptp_clear)); 1051 id_copy(client->public_key, public_key);
771 1052
772 return 1; 1053 update_client_with_reset(mono_time, client, &ip_port);
773 } 1054 return true;
774
775 return 0;
776} 1055}
777 1056
778/* Add node to close list. 1057/* Add node to close list.
@@ -782,45 +1061,31 @@ static int replace_all( Client_data *list,
782 * return -1 on failure. 1061 * return -1 on failure.
783 * return 0 on success. 1062 * return 0 on success.
784 */ 1063 */
785static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, _Bool simulate) 1064static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bool simulate)
786{ 1065{
787 unsigned int i;
788
789 unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key); 1066 unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
790 1067
791 if (index > LCLIENT_LENGTH) 1068 if (index >= LCLIENT_LENGTH) {
792 index = LCLIENT_LENGTH - 1; 1069 index = LCLIENT_LENGTH - 1;
1070 }
793 1071
794 for (i = 0; i < LCLIENT_NODES; ++i) { 1072 for (uint32_t i = 0; i < LCLIENT_NODES; ++i) {
795 Client_data *client = &dht->close_clientlist[(index * LCLIENT_NODES) + i]; 1073 /* TODO(iphydf): write bounds checking test to catch the case that
796 1074 * index is left as >= LCLIENT_LENGTH */
797 if (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { 1075 Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
798 if (!simulate) {
799 IPPTsPng *ipptp_write = NULL;
800 IPPTsPng *ipptp_clear = NULL;
801
802 if (ip_port.ip.family == AF_INET) {
803 ipptp_write = &client->assoc4;
804 ipptp_clear = &client->assoc6;
805 } else {
806 ipptp_write = &client->assoc6;
807 ipptp_clear = &client->assoc4;
808 }
809
810 id_copy(client->public_key, public_key);
811 ipptp_write->ip_port = ip_port;
812 ipptp_write->timestamp = unix_time();
813
814 ip_reset(&ipptp_write->ret_ip_port.ip);
815 ipptp_write->ret_ip_port.port = 0;
816 ipptp_write->ret_timestamp = 0;
817 1076
818 /* zero out other address */ 1077 if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
819 memset(ipptp_clear, 0, sizeof(*ipptp_clear)); 1078 !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
820 } 1079 continue;
1080 }
821 1081
1082 if (simulate) {
822 return 0; 1083 return 0;
823 } 1084 }
1085
1086 id_copy(client->public_key, public_key);
1087 update_client_with_reset(dht->mono_time, client, &ip_port);
1088 return 0;
824 } 1089 }
825 1090
826 return -1; 1091 return -1;
@@ -828,83 +1093,99 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, _B
828 1093
829/* Return 1 if node can be added to close list, 0 if it can't. 1094/* Return 1 if node can be added to close list, 0 if it can't.
830 */ 1095 */
831_Bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port) 1096bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
832{ 1097{
833 if (add_to_close(dht, public_key, ip_port, 1) == 0) { 1098 return add_to_close(dht, public_key, ip_port, 1) == 0;
834 return 1; 1099}
1100
1101static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const Mono_Time *mono_time,
1102 const uint8_t *public_key, IP_Port ip_port)
1103{
1104 const uint32_t index = index_of_client_pk(list, client_list_length, public_key);
1105
1106 if (index == UINT32_MAX) {
1107 return 0;
835 } 1108 }
836 1109
837 return 0; 1110 const IPPTsPng *assoc = net_family_is_ipv4(ip_port.ip.family)
1111 ? &list[index].assoc4
1112 : &list[index].assoc6;
1113
1114 return !mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT);
838} 1115}
839 1116
840static _Bool is_pk_in_client_list(Client_data *list, unsigned int client_list_length, const uint8_t *public_key, 1117static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
841 IP_Port ip_port)
842{ 1118{
843 unsigned int i; 1119 unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
844 1120
845 for (i = 0; i < client_list_length; ++i) { 1121 if (index >= LCLIENT_LENGTH) {
846 if ((ip_port.ip.family == AF_INET && !is_timeout(list[i].assoc4.timestamp, BAD_NODE_TIMEOUT)) 1122 index = LCLIENT_LENGTH - 1;
847 || (ip_port.ip.family == AF_INET6 && !is_timeout(list[i].assoc6.timestamp, BAD_NODE_TIMEOUT))) {
848 if (public_key_cmp(list[i].public_key, public_key) == 0) {
849 return 1;
850 }
851 }
852 } 1123 }
853 1124
854 return 0; 1125 return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->mono_time, public_key,
1126 ip_port);
855} 1127}
856 1128
857/* Check if the node obtained with a get_nodes with public_key should be pinged. 1129/* Check if the node obtained with a get_nodes with public_key should be pinged.
858 * NOTE: for best results call it after addto_lists; 1130 * NOTE: for best results call it after addto_lists;
859 * 1131 *
860 * return 0 if the node should not be pinged. 1132 * return false if the node should not be pinged.
861 * return 1 if it should. 1133 * return true if it should.
862 */ 1134 */
863static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port) 1135static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
864{ 1136{
865 _Bool ret = 0; 1137 bool ret = false;
866 1138
867 if (add_to_close(dht, public_key, ip_port, 1) == 0) { 1139 if (add_to_close(dht, public_key, ip_port, 1) == 0) {
868 ret = 1; 1140 ret = true;
869 } 1141 }
870 1142
871 if (ret && !client_in_nodelist(dht->to_bootstrap, dht->num_to_bootstrap, public_key)) { 1143 {
872 if (dht->num_to_bootstrap < MAX_CLOSE_TO_BOOTSTRAP_NODES) { 1144 unsigned int *const num = &dht->num_to_bootstrap;
873 memcpy(dht->to_bootstrap[dht->num_to_bootstrap].public_key, public_key, crypto_box_PUBLICKEYBYTES); 1145 const uint32_t index = index_of_node_pk(dht->to_bootstrap, *num, public_key);
874 dht->to_bootstrap[dht->num_to_bootstrap].ip_port = ip_port; 1146 const bool in_close_list = is_pk_in_close_list(dht, public_key, ip_port);
875 ++dht->num_to_bootstrap; 1147
876 } else { 1148 if (ret && index == UINT32_MAX && !in_close_list) {
877 //TODO: ipv6 vs v4 1149 if (*num < MAX_CLOSE_TO_BOOTSTRAP_NODES) {
878 add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key); 1150 memcpy(dht->to_bootstrap[*num].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1151 dht->to_bootstrap[*num].ip_port = ip_port;
1152 ++*num;
1153 } else {
1154 // TODO(irungentoo): ipv6 vs v4
1155 add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key);
1156 }
879 } 1157 }
880 } 1158 }
881 1159
882 unsigned int i; 1160 for (uint32_t i = 0; i < dht->num_friends; ++i) {
883 1161 DHT_Friend *dht_friend = &dht->friends_list[i];
884 for (i = 0; i < dht->num_friends; ++i) {
885 _Bool store_ok = 0;
886 1162
887 DHT_Friend *friend = &dht->friends_list[i]; 1163 bool store_ok = false;
888 1164
889 if (store_node_ok(&friend->client_list[1], public_key, friend->public_key)) { 1165 if (store_node_ok(&dht_friend->client_list[1], dht->mono_time, public_key, dht_friend->public_key)) {
890 store_ok = 1; 1166 store_ok = true;
891 } 1167 }
892 1168
893 if (store_node_ok(&friend->client_list[0], public_key, friend->public_key)) { 1169 if (store_node_ok(&dht_friend->client_list[0], dht->mono_time, public_key, dht_friend->public_key)) {
894 store_ok = 1; 1170 store_ok = true;
895 } 1171 }
896 1172
897 if (store_ok && !client_in_nodelist(friend->to_bootstrap, friend->num_to_bootstrap, public_key) 1173 unsigned int *const friend_num = &dht_friend->num_to_bootstrap;
898 && !is_pk_in_client_list(friend->client_list, MAX_FRIEND_CLIENTS, public_key, ip_port)) { 1174 const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key);
899 if (friend->num_to_bootstrap < MAX_SENT_NODES) { 1175 const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->mono_time, public_key,
900 memcpy(friend->to_bootstrap[friend->num_to_bootstrap].public_key, public_key, crypto_box_PUBLICKEYBYTES); 1176 ip_port);
901 friend->to_bootstrap[friend->num_to_bootstrap].ip_port = ip_port; 1177
902 ++friend->num_to_bootstrap; 1178 if (store_ok && index == UINT32_MAX && !pk_in_list) {
1179 if (*friend_num < MAX_SENT_NODES) {
1180 Node_format *const format = &dht_friend->to_bootstrap[*friend_num];
1181 memcpy(format->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1182 format->ip_port = ip_port;
1183 ++*friend_num;
903 } else { 1184 } else {
904 add_to_list(friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, friend->public_key); 1185 add_to_list(dht_friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, dht_friend->public_key);
905 } 1186 }
906 1187
907 ret = 1; 1188 ret = true;
908 } 1189 }
909 } 1190 }
910 1191
@@ -916,143 +1197,112 @@ static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_k
916 * 1197 *
917 * returns 1+ if the item is used in any list, 0 else 1198 * returns 1+ if the item is used in any list, 0 else
918 */ 1199 */
919int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key) 1200uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
920{ 1201{
921 uint32_t i, used = 0; 1202 uint32_t used = 0;
922 1203
923 /* convert IPv4-in-IPv6 to IPv4 */ 1204 /* convert IPv4-in-IPv6 to IPv4 */
924 if ((ip_port.ip.family == AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) { 1205 if (net_family_is_ipv6(ip_port.ip.family) && ipv6_ipv4_in_v6(ip_port.ip.ip.v6)) {
925 ip_port.ip.family = AF_INET; 1206 ip_port.ip.family = net_family_ipv4;
926 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; 1207 ip_port.ip.ip.v4.uint32 = ip_port.ip.ip.v6.uint32[3];
927 } 1208 }
928 1209
929 /* NOTE: Current behavior if there are two clients with the same id is 1210 /* NOTE: Current behavior if there are two clients with the same id is
930 * to replace the first ip by the second. 1211 * to replace the first ip by the second.
931 */ 1212 */
932 if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) { 1213 const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->close_clientlist, LCLIENT_LIST,
933 if (add_to_close(dht, public_key, ip_port, 0)) 1214 public_key, ip_port);
934 used++;
935 } else
936 used++;
937 1215
938 DHT_Friend *friend_foundip = 0; 1216 /* add_to_close should be called only if !in_list (don't extract to variable) */
939 1217 if (in_close_list || add_to_close(dht, public_key, ip_port, 0)) {
940 for (i = 0; i < dht->num_friends; ++i) { 1218 ++used;
941 if (!client_or_ip_port_in_list(dht->friends_list[i].client_list, 1219 }
942 MAX_FRIEND_CLIENTS, public_key, ip_port)) {
943 if (replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
944 public_key, ip_port, dht->friends_list[i].public_key)) {
945 1220
946 DHT_Friend *friend = &dht->friends_list[i]; 1221 DHT_Friend *friend_foundip = nullptr;
947 1222
948 if (public_key_cmp(public_key, friend->public_key) == 0) { 1223 for (uint32_t i = 0; i < dht->num_friends; ++i) {
949 friend_foundip = friend; 1224 const bool in_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->friends_list[i].client_list,
950 } 1225 MAX_FRIEND_CLIENTS, public_key, ip_port);
951 1226
952 used++; 1227 /* replace_all should be called only if !in_list (don't extract to variable) */
953 } 1228 if (in_list
954 } else { 1229 || replace_all(dht->mono_time, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port,
955 DHT_Friend *friend = &dht->friends_list[i]; 1230 dht->friends_list[i].public_key)) {
1231 DHT_Friend *dht_friend = &dht->friends_list[i];
956 1232
957 if (public_key_cmp(public_key, friend->public_key) == 0) { 1233 if (id_equal(public_key, dht_friend->public_key)) {
958 friend_foundip = friend; 1234 friend_foundip = dht_friend;
959 } 1235 }
960 1236
961 used++; 1237 ++used;
962 } 1238 }
963 } 1239 }
964 1240
965 if (friend_foundip) { 1241 if (!friend_foundip) {
966 uint32_t j; 1242 return used;
1243 }
967 1244
968 for (j = 0; j < friend_foundip->lock_count; ++j) { 1245 for (uint32_t i = 0; i < friend_foundip->lock_count; ++i) {
969 if (friend_foundip->callbacks[j].ip_callback) 1246 if (friend_foundip->callbacks[i].ip_callback) {
970 friend_foundip->callbacks[j].ip_callback(friend_foundip->callbacks[j].data, friend_foundip->callbacks[j].number, 1247 friend_foundip->callbacks[i].ip_callback(friend_foundip->callbacks[i].data,
971 ip_port); 1248 friend_foundip->callbacks[i].number, ip_port);
972 } 1249 }
973 } 1250 }
974 1251
975#ifdef ENABLE_ASSOC_DHT 1252 return used;
1253}
1254
1255static bool update_client_data(const Mono_Time *mono_time, Client_data *array, size_t size, IP_Port ip_port,
1256 const uint8_t *pk)
1257{
1258 const uint64_t temp_time = mono_time_get(mono_time);
1259 const uint32_t index = index_of_client_pk(array, size, pk);
976 1260
977 if (dht->assoc) { 1261 if (index == UINT32_MAX) {
978 IPPTs ippts; 1262 return false;
1263 }
979 1264
980 ippts.ip_port = ip_port; 1265 Client_data *const data = &array[index];
981 ippts.timestamp = unix_time(); 1266 IPPTsPng *assoc;
982 1267
983 Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, used ? 1 : 0); 1268 if (net_family_is_ipv4(ip_port.ip.family)) {
1269 assoc = &data->assoc4;
1270 } else if (net_family_is_ipv6(ip_port.ip.family)) {
1271 assoc = &data->assoc6;
1272 } else {
1273 return true;
984 } 1274 }
985 1275
986#endif 1276 assoc->ret_ip_port = ip_port;
987 return used; 1277 assoc->ret_timestamp = temp_time;
1278 return true;
988} 1279}
989 1280
990/* If public_key is a friend or us, update ret_ip_port 1281/* If public_key is a friend or us, update ret_ip_port
991 * nodepublic_key is the id of the node that sent us this info. 1282 * nodepublic_key is the id of the node that sent us this info.
992 */ 1283 */
993static int returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key) 1284static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key)
994{ 1285{
995 uint32_t i, j;
996 uint64_t temp_time = unix_time();
997
998 uint32_t used = 0;
999
1000 /* convert IPv4-in-IPv6 to IPv4 */ 1286 /* convert IPv4-in-IPv6 to IPv4 */
1001 if ((ip_port.ip.family == AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) { 1287 if (net_family_is_ipv6(ip_port.ip.family) && ipv6_ipv4_in_v6(ip_port.ip.ip.v6)) {
1002 ip_port.ip.family = AF_INET; 1288 ip_port.ip.family = net_family_ipv4;
1003 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; 1289 ip_port.ip.ip.v4.uint32 = ip_port.ip.ip.v6.uint32[3];
1004 } 1290 }
1005 1291
1006 if (id_equal(public_key, dht->self_public_key)) { 1292 if (id_equal(public_key, dht->self_public_key)) {
1007 for (i = 0; i < LCLIENT_LIST; ++i) { 1293 update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key);
1008 if (id_equal(nodepublic_key, dht->close_clientlist[i].public_key)) { 1294 return;
1009 if (ip_port.ip.family == AF_INET) {
1010 dht->close_clientlist[i].assoc4.ret_ip_port = ip_port;
1011 dht->close_clientlist[i].assoc4.ret_timestamp = temp_time;
1012 } else if (ip_port.ip.family == AF_INET6) {
1013 dht->close_clientlist[i].assoc6.ret_ip_port = ip_port;
1014 dht->close_clientlist[i].assoc6.ret_timestamp = temp_time;
1015 }
1016
1017 ++used;
1018 break;
1019 }
1020 }
1021 } else {
1022 for (i = 0; i < dht->num_friends; ++i) {
1023 if (id_equal(public_key, dht->friends_list[i].public_key)) {
1024 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1025 if (id_equal(nodepublic_key, dht->friends_list[i].client_list[j].public_key)) {
1026 if (ip_port.ip.family == AF_INET) {
1027 dht->friends_list[i].client_list[j].assoc4.ret_ip_port = ip_port;
1028 dht->friends_list[i].client_list[j].assoc4.ret_timestamp = temp_time;
1029 } else if (ip_port.ip.family == AF_INET6) {
1030 dht->friends_list[i].client_list[j].assoc6.ret_ip_port = ip_port;
1031 dht->friends_list[i].client_list[j].assoc6.ret_timestamp = temp_time;
1032 }
1033
1034 ++used;
1035 goto end;
1036 }
1037 }
1038 }
1039 }
1040 } 1295 }
1041 1296
1042end: 1297 for (uint32_t i = 0; i < dht->num_friends; ++i) {
1043#ifdef ENABLE_ASSOC_DHT 1298 if (id_equal(public_key, dht->friends_list[i].public_key)) {
1299 Client_data *const client_list = dht->friends_list[i].client_list;
1044 1300
1045 if (dht->assoc) { 1301 if (update_client_data(dht->mono_time, client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) {
1046 IPPTs ippts; 1302 return;
1047 ippts.ip_port = ip_port; 1303 }
1048 ippts.timestamp = temp_time; 1304 }
1049 /* this is only a hear-say entry, so ret-ipp is NULL, but used is required
1050 * to decide how valuable it is ("used" may throw an "unused" entry out) */
1051 Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, used ? 1 : 0);
1052 } 1305 }
1053
1054#endif
1055 return 0;
1056} 1306}
1057 1307
1058/* Send a getnodes request. 1308/* Send a getnodes request.
@@ -1061,56 +1311,47 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const
1061 const Node_format *sendback_node) 1311 const Node_format *sendback_node)
1062{ 1312{
1063 /* Check if packet is going to be sent to ourself. */ 1313 /* Check if packet is going to be sent to ourself. */
1064 if (id_equal(public_key, dht->self_public_key)) 1314 if (id_equal(public_key, dht->self_public_key)) {
1065 return -1; 1315 return -1;
1316 }
1066 1317
1067 uint8_t plain_message[sizeof(Node_format) * 2] = {0}; 1318 uint8_t plain_message[sizeof(Node_format) * 2] = {0};
1068 1319
1069 Node_format receiver; 1320 Node_format receiver;
1070 memcpy(receiver.public_key, public_key, crypto_box_PUBLICKEYBYTES); 1321 memcpy(receiver.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1071 receiver.ip_port = ip_port; 1322 receiver.ip_port = ip_port;
1072 memcpy(plain_message, &receiver, sizeof(receiver)); 1323 memcpy(plain_message, &receiver, sizeof(receiver));
1073 1324
1074 uint64_t ping_id = 0; 1325 uint64_t ping_id = 0;
1075 1326
1076 if (sendback_node != NULL) { 1327 if (sendback_node != nullptr) {
1077 memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format)); 1328 memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format));
1078 ping_id = ping_array_add(&dht->dht_harden_ping_array, plain_message, sizeof(plain_message)); 1329 ping_id = ping_array_add(dht->dht_harden_ping_array, dht->mono_time, plain_message, sizeof(plain_message));
1079 } else { 1330 } else {
1080 ping_id = ping_array_add(&dht->dht_ping_array, plain_message, sizeof(receiver)); 1331 ping_id = ping_array_add(dht->dht_ping_array, dht->mono_time, plain_message, sizeof(receiver));
1081 } 1332 }
1082 1333
1083 if (ping_id == 0) 1334 if (ping_id == 0) {
1084 return -1; 1335 return -1;
1336 }
1085 1337
1086 uint8_t plain[crypto_box_PUBLICKEYBYTES + sizeof(ping_id)]; 1338 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + sizeof(ping_id)];
1087 uint8_t encrypt[sizeof(plain) + crypto_box_MACBYTES]; 1339 uint8_t data[1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE];
1088 uint8_t data[1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + sizeof(encrypt)];
1089
1090 memcpy(plain, client_id, crypto_box_PUBLICKEYBYTES);
1091 memcpy(plain + crypto_box_PUBLICKEYBYTES, &ping_id, sizeof(ping_id));
1092 1340
1093 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 1341 memcpy(plain, client_id, CRYPTO_PUBLIC_KEY_SIZE);
1094 DHT_get_shared_key_sent(dht, shared_key, public_key); 1342 memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, &ping_id, sizeof(ping_id));
1095 1343
1096 uint8_t nonce[crypto_box_NONCEBYTES]; 1344 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
1097 new_nonce(nonce); 1345 dht_get_shared_key_sent(dht, shared_key, public_key);
1098 1346
1099 int len = encrypt_data_symmetric( shared_key, 1347 const int len = dht_create_packet(dht->self_public_key, shared_key, NET_PACKET_GET_NODES,
1100 nonce, 1348 plain, sizeof(plain), data);
1101 plain,
1102 sizeof(plain),
1103 encrypt );
1104 1349
1105 if (len != sizeof(encrypt)) 1350 if (len != sizeof(data)) {
1106 return -1; 1351 return -1;
1352 }
1107 1353
1108 data[0] = NET_PACKET_GET_NODES; 1354 return sendpacket(dht->net, ip_port, data, len);
1109 memcpy(data + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
1110 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
1111 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, encrypt, len);
1112
1113 return sendpacket(dht->net, ip_port, data, sizeof(data));
1114} 1355}
1115 1356
1116/* Send a send nodes response: message for IPv6 nodes */ 1357/* Send a send nodes response: message for IPv6 nodes */
@@ -1118,105 +1359,108 @@ static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public
1118 const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key) 1359 const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key)
1119{ 1360{
1120 /* Check if packet is going to be sent to ourself. */ 1361 /* Check if packet is going to be sent to ourself. */
1121 if (id_equal(public_key, dht->self_public_key)) 1362 if (id_equal(public_key, dht->self_public_key)) {
1122 return -1; 1363 return -1;
1364 }
1123 1365
1124 if (length != sizeof(uint64_t)) 1366 if (length != sizeof(uint64_t)) {
1125 return -1; 1367 return -1;
1368 }
1126 1369
1127 size_t Node_format_size = sizeof(Node_format); 1370 const size_t node_format_size = sizeof(Node_format);
1128 uint8_t data[1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES
1129 + Node_format_size * MAX_SENT_NODES + length + crypto_box_MACBYTES];
1130 1371
1131 Node_format nodes_list[MAX_SENT_NODES]; 1372 Node_format nodes_list[MAX_SENT_NODES];
1132 uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1); 1373 const uint32_t num_nodes =
1374 get_close_nodes(dht, client_id, nodes_list, net_family_unspec, ip_is_lan(ip_port.ip), 1);
1133 1375
1134 uint8_t plain[1 + Node_format_size * MAX_SENT_NODES + length]; 1376 VLA(uint8_t, plain, 1 + node_format_size * MAX_SENT_NODES + length);
1135 uint8_t encrypt[sizeof(plain) + crypto_box_MACBYTES];
1136 uint8_t nonce[crypto_box_NONCEBYTES];
1137 new_nonce(nonce);
1138 1377
1139 int nodes_length = 0; 1378 int nodes_length = 0;
1140 1379
1141 if (num_nodes) { 1380 if (num_nodes) {
1142 nodes_length = pack_nodes(plain + 1, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes); 1381 nodes_length = pack_nodes(plain + 1, node_format_size * MAX_SENT_NODES, nodes_list, num_nodes);
1143 1382
1144 if (nodes_length <= 0) 1383 if (nodes_length <= 0) {
1145 return -1; 1384 return -1;
1385 }
1146 } 1386 }
1147 1387
1148 plain[0] = num_nodes; 1388 plain[0] = num_nodes;
1149 memcpy(plain + 1 + nodes_length, sendback_data, length); 1389 memcpy(plain + 1 + nodes_length, sendback_data, length);
1150 int len = encrypt_data_symmetric( shared_encryption_key,
1151 nonce,
1152 plain,
1153 1 + nodes_length + length,
1154 encrypt );
1155 1390
1156 if (len != 1 + nodes_length + length + crypto_box_MACBYTES) 1391 const uint32_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
1157 return -1; 1392 VLA(uint8_t, data, 1 + nodes_length + length + crypto_size);
1158 1393
1159 data[0] = NET_PACKET_SEND_NODES_IPV6; 1394 const int len = dht_create_packet(dht->self_public_key, shared_encryption_key, NET_PACKET_SEND_NODES_IPV6,
1160 memcpy(data + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES); 1395 plain, 1 + nodes_length + length, data);
1161 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
1162 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, encrypt, len);
1163 1396
1164 return sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + len); 1397 if (len != SIZEOF_VLA(data)) {
1398 return -1;
1399 }
1400
1401 return sendpacket(dht->net, ip_port, data, len);
1165} 1402}
1166 1403
1167static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 1404#define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t))
1405
1406static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
1168{ 1407{
1169 if (length != (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + sizeof( 1408 if (length != (CRYPTO_SIZE + CRYPTO_MAC_SIZE + sizeof(uint64_t))) {
1170 uint64_t) + crypto_box_MACBYTES)) 1409 return true;
1171 return 1; 1410 }
1172 1411
1173 DHT *dht = object; 1412 DHT *const dht = (DHT *)object;
1174 1413
1175 /* Check if packet is from ourself. */ 1414 /* Check if packet is from ourself. */
1176 if (id_equal(packet + 1, dht->self_public_key)) 1415 if (id_equal(packet + 1, dht->self_public_key)) {
1177 return 1; 1416 return true;
1417 }
1178 1418
1179 uint8_t plain[crypto_box_PUBLICKEYBYTES + sizeof(uint64_t)]; 1419 uint8_t plain[CRYPTO_NODE_SIZE];
1180 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 1420 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
1181 1421
1182 DHT_get_shared_key_recv(dht, shared_key, packet + 1); 1422 dht_get_shared_key_recv(dht, shared_key, packet + 1);
1183 int len = decrypt_data_symmetric( shared_key, 1423 const int len = decrypt_data_symmetric(
1184 packet + 1 + crypto_box_PUBLICKEYBYTES, 1424 shared_key,
1185 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 1425 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
1186 crypto_box_PUBLICKEYBYTES + sizeof(uint64_t) + crypto_box_MACBYTES, 1426 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1187 plain ); 1427 CRYPTO_NODE_SIZE + CRYPTO_MAC_SIZE,
1428 plain);
1188 1429
1189 if (len != crypto_box_PUBLICKEYBYTES + sizeof(uint64_t)) 1430 if (len != CRYPTO_NODE_SIZE) {
1190 return 1; 1431 return true;
1432 }
1191 1433
1192 sendnodes_ipv6(dht, source, packet + 1, plain, plain + crypto_box_PUBLICKEYBYTES, sizeof(uint64_t), shared_key); 1434 sendnodes_ipv6(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key);
1193 1435
1194 add_to_ping(dht->ping, packet + 1, source); 1436 ping_add(dht->ping, packet + 1, source);
1195 1437
1196 return 0; 1438 return false;
1197} 1439}
1198/* return 0 if no 1440
1199 return 1 if yes */ 1441/* return false if no
1200static uint8_t sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id, 1442 return true if yes */
1201 Node_format *sendback_node) 1443static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id,
1444 Node_format *sendback_node)
1202{ 1445{
1203 uint8_t data[sizeof(Node_format) * 2]; 1446 uint8_t data[sizeof(Node_format) * 2];
1204 1447
1205 if (ping_array_check(data, sizeof(data), &dht->dht_ping_array, ping_id) == sizeof(Node_format)) { 1448 if (ping_array_check(dht->dht_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(Node_format)) {
1206 memset(sendback_node, 0, sizeof(Node_format)); 1449 memset(sendback_node, 0, sizeof(Node_format));
1207 } else if (ping_array_check(data, sizeof(data), &dht->dht_harden_ping_array, ping_id) == sizeof(data)) { 1450 } else if (ping_array_check(dht->dht_harden_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(data)) {
1208 memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format)); 1451 memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format));
1209 } else { 1452 } else {
1210 return 0; 1453 return false;
1211 } 1454 }
1212 1455
1213 Node_format test; 1456 Node_format test;
1214 memcpy(&test, data, sizeof(Node_format)); 1457 memcpy(&test, data, sizeof(Node_format));
1215 1458
1216 if (!ipport_equal(&test.ip_port, &node_ip_port) || public_key_cmp(test.public_key, public_key) != 0) 1459 if (!ipport_equal(&test.ip_port, &node_ip_port) || !id_equal(test.public_key, public_key)) {
1217 return 0; 1460 return false;
1461 }
1218 1462
1219 return 1; 1463 return true;
1220} 1464}
1221 1465
1222/* Function is needed in following functions. */ 1466/* Function is needed in following functions. */
@@ -1226,55 +1470,64 @@ static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto,
1226static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length, 1470static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
1227 Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) 1471 Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
1228{ 1472{
1229 DHT *dht = object; 1473 DHT *const dht = (DHT *)object;
1230 uint32_t cid_size = 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + 1 + sizeof(uint64_t) + crypto_box_MACBYTES; 1474 const uint32_t cid_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1 + sizeof(uint64_t) + CRYPTO_MAC_SIZE;
1231 1475
1232 if (length < cid_size) /* too short */ 1476 if (length < cid_size) { /* too short */
1233 return 1; 1477 return 1;
1478 }
1234 1479
1235 uint32_t data_size = length - cid_size; 1480 const uint32_t data_size = length - cid_size;
1236 1481
1237 if (data_size == 0) 1482 if (data_size == 0) {
1238 return 1; 1483 return 1;
1484 }
1239 1485
1240 if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */ 1486 if (data_size > sizeof(Node_format) * MAX_SENT_NODES) { /* invalid length */
1241 return 1; 1487 return 1;
1488 }
1489
1490 VLA(uint8_t, plain, 1 + data_size + sizeof(uint64_t));
1491 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
1492 dht_get_shared_key_sent(dht, shared_key, packet + 1);
1493 const int len = decrypt_data_symmetric(
1494 shared_key,
1495 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
1496 packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1497 1 + data_size + sizeof(uint64_t) + CRYPTO_MAC_SIZE,
1498 plain);
1242 1499
1243 uint8_t plain[1 + data_size + sizeof(uint64_t)]; 1500 if ((unsigned int)len != SIZEOF_VLA(plain)) {
1244 uint8_t shared_key[crypto_box_BEFORENMBYTES];
1245 DHT_get_shared_key_sent(dht, shared_key, packet + 1);
1246 int len = decrypt_data_symmetric(
1247 shared_key,
1248 packet + 1 + crypto_box_PUBLICKEYBYTES,
1249 packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
1250 1 + data_size + sizeof(uint64_t) + crypto_box_MACBYTES,
1251 plain);
1252
1253 if ((unsigned int)len != sizeof(plain))
1254 return 1; 1501 return 1;
1502 }
1255 1503
1256 if (plain[0] > size_plain_nodes) 1504 if (plain[0] > size_plain_nodes) {
1257 return 1; 1505 return 1;
1506 }
1258 1507
1259 Node_format sendback_node; 1508 Node_format sendback_node;
1260 1509
1261 uint64_t ping_id; 1510 uint64_t ping_id;
1262 memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id)); 1511 memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id));
1263 1512
1264 if (!sent_getnode_to_node(dht, packet + 1, source, ping_id, &sendback_node)) 1513 if (!sent_getnode_to_node(dht, packet + 1, source, ping_id, &sendback_node)) {
1265 return 1; 1514 return 1;
1515 }
1266 1516
1267 uint16_t length_nodes = 0; 1517 uint16_t length_nodes = 0;
1268 int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0); 1518 const int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0);
1269 1519
1270 if (length_nodes != data_size) 1520 if (length_nodes != data_size) {
1271 return 1; 1521 return 1;
1522 }
1272 1523
1273 if (num_nodes != plain[0]) 1524 if (num_nodes != plain[0]) {
1274 return 1; 1525 return 1;
1526 }
1275 1527
1276 if (num_nodes < 0) 1528 if (num_nodes < 0) {
1277 return 1; 1529 return 1;
1530 }
1278 1531
1279 /* store the address the *request* was sent to */ 1532 /* store the address the *request* was sent to */
1280 addto_lists(dht, source, packet + 1); 1533 addto_lists(dht, source, packet + 1);
@@ -1285,22 +1538,21 @@ static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *pa
1285 return 0; 1538 return 0;
1286} 1539}
1287 1540
1288static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 1541static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
1289{ 1542{
1290 DHT *dht = object; 1543 DHT *const dht = (DHT *)object;
1291 Node_format plain_nodes[MAX_SENT_NODES]; 1544 Node_format plain_nodes[MAX_SENT_NODES];
1292 uint32_t num_nodes; 1545 uint32_t num_nodes;
1293 1546
1294 if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) 1547 if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) {
1295 return 1; 1548 return 1;
1549 }
1296 1550
1297 if (num_nodes == 0) 1551 if (num_nodes == 0) {
1298 return 0; 1552 return 0;
1553 }
1299 1554
1300 uint32_t i; 1555 for (uint32_t i = 0; i < num_nodes; ++i) {
1301
1302 for (i = 0; i < num_nodes; i++) {
1303
1304 if (ipport_isset(&plain_nodes[i].ip_port)) { 1556 if (ipport_isset(&plain_nodes[i].ip_port)) {
1305 ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, plain_nodes[i].ip_port); 1557 ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, plain_nodes[i].ip_port);
1306 returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1); 1558 returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);
@@ -1313,130 +1565,134 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *pa
1313/*----------------------------------------------------------------------------------*/ 1565/*----------------------------------------------------------------------------------*/
1314/*------------------------END of packet handling functions--------------------------*/ 1566/*------------------------END of packet handling functions--------------------------*/
1315 1567
1316int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port), 1568int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,
1317 void *data, int32_t number, uint16_t *lock_count) 1569 void *data, int32_t number, uint16_t *lock_count)
1318{ 1570{
1319 int friend_num = friend_number(dht, public_key); 1571 const uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1320 1572
1321 uint16_t lock_num; 1573 uint16_t lock_num;
1322 1574
1323 if (friend_num != -1) { /* Is friend already in DHT? */ 1575 if (friend_num != UINT32_MAX) { /* Is friend already in DHT? */
1324 DHT_Friend *friend = &dht->friends_list[friend_num]; 1576 DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1325 1577
1326 if (friend->lock_count == DHT_FRIEND_MAX_LOCKS) 1578 if (dht_friend->lock_count == DHT_FRIEND_MAX_LOCKS) {
1327 return -1; 1579 return -1;
1580 }
1328 1581
1329 lock_num = friend->lock_count; 1582 lock_num = dht_friend->lock_count;
1330 ++friend->lock_count; 1583 ++dht_friend->lock_count;
1331 friend->callbacks[lock_num].ip_callback = ip_callback; 1584 dht_friend->callbacks[lock_num].ip_callback = ip_callback;
1332 friend->callbacks[lock_num].data = data; 1585 dht_friend->callbacks[lock_num].data = data;
1333 friend->callbacks[lock_num].number = number; 1586 dht_friend->callbacks[lock_num].number = number;
1334 1587
1335 if (lock_count) 1588 if (lock_count) {
1336 *lock_count = lock_num + 1; 1589 *lock_count = lock_num + 1;
1590 }
1337 1591
1338 return 0; 1592 return 0;
1339 } 1593 }
1340 1594
1341 DHT_Friend *temp; 1595 DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
1342 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
1343 1596
1344 if (temp == NULL) 1597 if (temp == nullptr) {
1345 return -1; 1598 return -1;
1599 }
1346 1600
1347 dht->friends_list = temp; 1601 dht->friends_list = temp;
1348 DHT_Friend *friend = &dht->friends_list[dht->num_friends]; 1602 DHT_Friend *const dht_friend = &dht->friends_list[dht->num_friends];
1349 memset(friend, 0, sizeof(DHT_Friend)); 1603 memset(dht_friend, 0, sizeof(DHT_Friend));
1350 memcpy(friend->public_key, public_key, crypto_box_PUBLICKEYBYTES); 1604 memcpy(dht_friend->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1351 1605
1352 friend->nat.NATping_id = random_64b(); 1606 dht_friend->nat.nat_ping_id = random_u64();
1353 ++dht->num_friends; 1607 ++dht->num_friends;
1354 1608
1355 lock_num = friend->lock_count; 1609 lock_num = dht_friend->lock_count;
1356 ++friend->lock_count; 1610 ++dht_friend->lock_count;
1357 friend->callbacks[lock_num].ip_callback = ip_callback; 1611 dht_friend->callbacks[lock_num].ip_callback = ip_callback;
1358 friend->callbacks[lock_num].data = data; 1612 dht_friend->callbacks[lock_num].data = data;
1359 friend->callbacks[lock_num].number = number; 1613 dht_friend->callbacks[lock_num].number = number;
1360 1614
1361 if (lock_count) 1615 if (lock_count) {
1362 *lock_count = lock_num + 1; 1616 *lock_count = lock_num + 1;
1617 }
1363 1618
1364 friend->num_to_bootstrap = get_close_nodes(dht, friend->public_key, friend->to_bootstrap, 0, 1, 0); 1619 dht_friend->num_to_bootstrap = get_close_nodes(dht, dht_friend->public_key, dht_friend->to_bootstrap, net_family_unspec,
1620 1, 0);
1365 1621
1366 return 0; 1622 return 0;
1367} 1623}
1368 1624
1369int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count) 1625int dht_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count)
1370{ 1626{
1371 int friend_num = friend_number(dht, public_key); 1627 const uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1372 1628
1373 if (friend_num == -1) { 1629 if (friend_num == UINT32_MAX) {
1374 return -1; 1630 return -1;
1375 } 1631 }
1376 1632
1377 DHT_Friend *friend = &dht->friends_list[friend_num]; 1633 DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1378 --friend->lock_count; 1634 --dht_friend->lock_count;
1379 1635
1380 if (friend->lock_count && lock_count) { /* DHT friend is still in use.*/ 1636 if (dht_friend->lock_count && lock_count) { /* DHT friend is still in use.*/
1381 --lock_count; 1637 --lock_count;
1382 friend->callbacks[lock_count].ip_callback = NULL; 1638 dht_friend->callbacks[lock_count].ip_callback = nullptr;
1383 friend->callbacks[lock_count].data = NULL; 1639 dht_friend->callbacks[lock_count].data = nullptr;
1384 friend->callbacks[lock_count].number = 0; 1640 dht_friend->callbacks[lock_count].number = 0;
1385 return 0; 1641 return 0;
1386 } 1642 }
1387 1643
1388 DHT_Friend *temp;
1389
1390 --dht->num_friends; 1644 --dht->num_friends;
1391 1645
1392 if (dht->num_friends != friend_num) { 1646 if (dht->num_friends != friend_num) {
1393 memcpy( &dht->friends_list[friend_num], 1647 memcpy(&dht->friends_list[friend_num],
1394 &dht->friends_list[dht->num_friends], 1648 &dht->friends_list[dht->num_friends],
1395 sizeof(DHT_Friend) ); 1649 sizeof(DHT_Friend));
1396 } 1650 }
1397 1651
1398 if (dht->num_friends == 0) { 1652 if (dht->num_friends == 0) {
1399 free(dht->friends_list); 1653 free(dht->friends_list);
1400 dht->friends_list = NULL; 1654 dht->friends_list = nullptr;
1401 return 0; 1655 return 0;
1402 } 1656 }
1403 1657
1404 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends)); 1658 DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends));
1405 1659
1406 if (temp == NULL) 1660 if (temp == nullptr) {
1407 return -1; 1661 return -1;
1662 }
1408 1663
1409 dht->friends_list = temp; 1664 dht->friends_list = temp;
1410 return 0; 1665 return 0;
1411} 1666}
1412 1667
1413/* TODO: Optimize this. */ 1668/* TODO(irungentoo): Optimize this. */
1414int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port) 1669int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
1415{ 1670{
1416 uint32_t i, j;
1417
1418 ip_reset(&ip_port->ip); 1671 ip_reset(&ip_port->ip);
1419 ip_port->port = 0; 1672 ip_port->port = 0;
1420 1673
1421 for (i = 0; i < dht->num_friends; ++i) { 1674 const uint32_t friend_index = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1422 /* Equal */
1423 if (id_equal(dht->friends_list[i].public_key, public_key)) {
1424 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1425 Client_data *client = &dht->friends_list[i].client_list[j];
1426
1427 if (id_equal(client->public_key, public_key)) {
1428 IPPTsPng *assoc = NULL;
1429 uint32_t a;
1430
1431 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4)
1432 if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) {
1433 *ip_port = assoc->ip_port;
1434 return 1;
1435 }
1436 }
1437 }
1438 1675
1439 return 0; 1676 if (friend_index == UINT32_MAX) {
1677 return -1;
1678 }
1679
1680 DHT_Friend *const frnd = &dht->friends_list[friend_index];
1681 const uint32_t client_index = index_of_client_pk(frnd->client_list, MAX_FRIEND_CLIENTS, public_key);
1682
1683 if (client_index == -1) {
1684 return 0;
1685 }
1686
1687 const Client_data *const client = &frnd->client_list[client_index];
1688 const IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4, nullptr };
1689
1690 for (const IPPTsPng * const *it = assocs; *it; ++it) {
1691 const IPPTsPng *const assoc = *it;
1692
1693 if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1694 *ip_port = assoc->ip_port;
1695 return 1;
1440 } 1696 }
1441 } 1697 }
1442 1698
@@ -1445,36 +1701,37 @@ int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
1445 1701
1446/* returns number of nodes not in kill-timeout */ 1702/* returns number of nodes not in kill-timeout */
1447static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key, 1703static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key,
1448 Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, _Bool sortable) 1704 Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable)
1449{ 1705{
1450 uint32_t i;
1451 uint8_t not_kill = 0; 1706 uint8_t not_kill = 0;
1452 uint64_t temp_time = unix_time(); 1707 const uint64_t temp_time = mono_time_get(dht->mono_time);
1453 1708
1454 uint32_t num_nodes = 0; 1709 uint32_t num_nodes = 0;
1455 Client_data *client_list[list_count * 2]; 1710 VLA(Client_data *, client_list, list_count * 2);
1456 IPPTsPng *assoc_list[list_count * 2]; 1711 VLA(IPPTsPng *, assoc_list, list_count * 2);
1457 unsigned int sort = 0; 1712 unsigned int sort = 0;
1458 _Bool sort_ok = 0; 1713 bool sort_ok = false;
1459 1714
1460 for (i = 0; i < list_count; i++) { 1715 for (uint32_t i = 0; i < list_count; ++i) {
1461 /* If node is not dead. */ 1716 /* If node is not dead. */
1462 Client_data *client = &list[i]; 1717 Client_data *client = &list[i];
1463 IPPTsPng *assoc;
1464 uint32_t a;
1465 1718
1466 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) 1719 IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4 };
1467 if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) { 1720
1721 for (uint32_t j = 0; j < sizeof(assocs) / sizeof(assocs[0]); ++j) {
1722 IPPTsPng *const assoc = assocs[j];
1723
1724 if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, KILL_NODE_TIMEOUT)) {
1468 sort = 0; 1725 sort = 0;
1469 not_kill++; 1726 ++not_kill;
1470 1727
1471 if (is_timeout(assoc->last_pinged, PING_INTERVAL)) { 1728 if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) {
1472 getnodes(dht, assoc->ip_port, client->public_key, public_key, NULL); 1729 getnodes(dht, assoc->ip_port, client->public_key, public_key, nullptr);
1473 assoc->last_pinged = temp_time; 1730 assoc->last_pinged = temp_time;
1474 } 1731 }
1475 1732
1476 /* If node is good. */ 1733 /* If node is good. */
1477 if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { 1734 if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1478 client_list[num_nodes] = client; 1735 client_list[num_nodes] = client;
1479 assoc_list[num_nodes] = assoc; 1736 assoc_list[num_nodes] = assoc;
1480 ++num_nodes; 1737 ++num_nodes;
@@ -1483,24 +1740,26 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1483 ++sort; 1740 ++sort;
1484 1741
1485 /* Timed out should be at beginning, if they are not, sort the list. */ 1742 /* Timed out should be at beginning, if they are not, sort the list. */
1486 if (sort > 1 && sort < (((i + 1) * 2) - 1)) { 1743 if (sort > 1 && sort < (((j + 1) * 2) - 1)) {
1487 sort_ok = 1; 1744 sort_ok = true;
1488 } 1745 }
1489 } 1746 }
1747 }
1490 } 1748 }
1491 1749
1492 if (sortable && sort_ok) { 1750 if (sortable && sort_ok) {
1493 sort_client_list(list, list_count, public_key); 1751 sort_client_list(list, dht->mono_time, list_count, public_key);
1494 } 1752 }
1495 1753
1496 if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { 1754 if ((num_nodes != 0) && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL)
1497 uint32_t rand_node = rand() % (num_nodes); 1755 || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
1756 uint32_t rand_node = random_u32() % num_nodes;
1498 1757
1499 if ((num_nodes - 1) != rand_node) { 1758 if ((num_nodes - 1) != rand_node) {
1500 rand_node += rand() % (num_nodes - (rand_node + 1)); 1759 rand_node += random_u32() % (num_nodes - (rand_node + 1));
1501 } 1760 }
1502 1761
1503 getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, NULL); 1762 getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, nullptr);
1504 1763
1505 *lastgetnode = temp_time; 1764 *lastgetnode = temp_time;
1506 ++*bootstrap_times; 1765 ++*bootstrap_times;
@@ -1512,21 +1771,21 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1512/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 1771/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
1513 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. 1772 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list.
1514 */ 1773 */
1515static void do_DHT_friends(DHT *dht) 1774static void do_dht_friends(DHT *dht)
1516{ 1775{
1517 unsigned int i, j; 1776 for (size_t i = 0; i < dht->num_friends; ++i) {
1518 1777 DHT_Friend *const dht_friend = &dht->friends_list[i];
1519 for (i = 0; i < dht->num_friends; ++i) {
1520 DHT_Friend *friend = &dht->friends_list[i];
1521 1778
1522 for (j = 0; j < friend->num_to_bootstrap; ++j) { 1779 for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) {
1523 getnodes(dht, friend->to_bootstrap[j].ip_port, friend->to_bootstrap[j].public_key, friend->public_key, NULL); 1780 getnodes(dht, dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key,
1781 nullptr);
1524 } 1782 }
1525 1783
1526 friend->num_to_bootstrap = 0; 1784 dht_friend->num_to_bootstrap = 0;
1527 1785
1528 do_ping_and_sendnode_requests(dht, &friend->lastgetnode, friend->public_key, friend->client_list, MAX_FRIEND_CLIENTS, 1786 do_ping_and_sendnode_requests(dht, &dht_friend->lastgetnode, dht_friend->public_key, dht_friend->client_list,
1529 &friend->bootstrap_times, 1); 1787 MAX_FRIEND_CLIENTS,
1788 &dht_friend->bootstrap_times, 1);
1530 } 1789 }
1531} 1790}
1532 1791
@@ -1535,84 +1794,80 @@ static void do_DHT_friends(DHT *dht)
1535 */ 1794 */
1536static void do_Close(DHT *dht) 1795static void do_Close(DHT *dht)
1537{ 1796{
1538 unsigned int i; 1797 for (size_t i = 0; i < dht->num_to_bootstrap; ++i) {
1539 1798 getnodes(dht, dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key, nullptr);
1540 for (i = 0; i < dht->num_to_bootstrap; ++i) {
1541 getnodes(dht, dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key, NULL);
1542 } 1799 }
1543 1800
1544 dht->num_to_bootstrap = 0; 1801 dht->num_to_bootstrap = 0;
1545 1802
1546 uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key, 1803 uint8_t not_killed = do_ping_and_sendnode_requests(
1547 dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times, 0); 1804 dht, &dht->close_lastgetnodes, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times,
1805 0);
1806
1807 if (not_killed != 0) {
1808 return;
1809 }
1810
1811 /* all existing nodes are at least KILL_NODE_TIMEOUT,
1812 * which means we are mute, as we only send packets to
1813 * nodes NOT in KILL_NODE_TIMEOUT
1814 *
1815 * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
1816 * KILL_NODE_TIMEOUT, so we at least keep trying pings */
1817 const uint64_t badonly = mono_time_get(dht->mono_time) - BAD_NODE_TIMEOUT;
1548 1818
1549 if (!not_killed) { 1819 for (size_t i = 0; i < LCLIENT_LIST; ++i) {
1550 /* all existing nodes are at least KILL_NODE_TIMEOUT, 1820 Client_data *const client = &dht->close_clientlist[i];
1551 * which means we are mute, as we only send packets to
1552 * nodes NOT in KILL_NODE_TIMEOUT
1553 *
1554 * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
1555 * KILL_NODE_TIMEOUT, so we at least keep trying pings */
1556 uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT;
1557 size_t i, a;
1558 1821
1559 for (i = 0; i < LCLIENT_LIST; i++) { 1822 IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4, nullptr };
1560 Client_data *client = &dht->close_clientlist[i];
1561 IPPTsPng *assoc;
1562 1823
1563 for (a = 0, assoc = &client->assoc4; a < 2; a++, assoc = &client->assoc6) 1824 for (IPPTsPng * const *it = assocs; *it; ++it) {
1564 if (assoc->timestamp) 1825 IPPTsPng *const assoc = *it;
1565 assoc->timestamp = badonly; 1826
1827 if (assoc->timestamp) {
1828 assoc->timestamp = badonly;
1829 }
1566 } 1830 }
1567 } 1831 }
1568} 1832}
1569 1833
1570void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id) 1834void dht_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id)
1571{ 1835{
1572 getnodes(dht, *from_ipp, from_id, which_id, NULL); 1836 getnodes(dht, *from_ipp, from_id, which_id, nullptr);
1573} 1837}
1574 1838
1575void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key) 1839void dht_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
1576{ 1840{
1577 /*#ifdef ENABLE_ASSOC_DHT 1841 getnodes(dht, ip_port, public_key, dht->self_public_key, nullptr);
1578 if (dht->assoc) {
1579 IPPTs ippts;
1580 ippts.ip_port = ip_port;
1581 ippts.timestamp = 0;
1582
1583 Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, 0);
1584 }
1585 #endif*/
1586
1587 getnodes(dht, ip_port, public_key, dht->self_public_key, NULL);
1588} 1842}
1589int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, 1843int dht_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
1590 uint16_t port, const uint8_t *public_key) 1844 uint16_t port, const uint8_t *public_key)
1591{ 1845{
1592 IP_Port ip_port_v64; 1846 IP_Port ip_port_v64;
1593 IP *ip_extra = NULL; 1847 IP *ip_extra = nullptr;
1594 IP_Port ip_port_v4; 1848 IP_Port ip_port_v4;
1595 ip_init(&ip_port_v64.ip, ipv6enabled); 1849 ip_init(&ip_port_v64.ip, ipv6enabled);
1596 1850
1597 if (ipv6enabled) { 1851 if (ipv6enabled) {
1598 /* setup for getting BOTH: an IPv6 AND an IPv4 address */ 1852 /* setup for getting BOTH: an IPv6 AND an IPv4 address */
1599 ip_port_v64.ip.family = AF_UNSPEC; 1853 ip_port_v64.ip.family = net_family_unspec;
1600 ip_reset(&ip_port_v4.ip); 1854 ip_reset(&ip_port_v4.ip);
1601 ip_extra = &ip_port_v4.ip; 1855 ip_extra = &ip_port_v4.ip;
1602 } 1856 }
1603 1857
1604 if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) { 1858 if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
1605 ip_port_v64.port = port; 1859 ip_port_v64.port = port;
1606 DHT_bootstrap(dht, ip_port_v64, public_key); 1860 dht_bootstrap(dht, ip_port_v64, public_key);
1607 1861
1608 if ((ip_extra != NULL) && ip_isset(ip_extra)) { 1862 if ((ip_extra != nullptr) && ip_isset(ip_extra)) {
1609 ip_port_v4.port = port; 1863 ip_port_v4.port = port;
1610 DHT_bootstrap(dht, ip_port_v4, public_key); 1864 dht_bootstrap(dht, ip_port_v4, public_key);
1611 } 1865 }
1612 1866
1613 return 1; 1867 return 1;
1614 } else 1868 }
1615 return 0; 1869
1870 return 0;
1616} 1871}
1617 1872
1618/* Send the given packet to node with public_key 1873/* Send the given packet to node with public_key
@@ -1621,18 +1876,20 @@ int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable
1621 */ 1876 */
1622int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length) 1877int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length)
1623{ 1878{
1624 uint32_t i; 1879 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
1625
1626 for (i = 0; i < LCLIENT_LIST; ++i) {
1627 if (id_equal(public_key, dht->close_clientlist[i].public_key)) { 1880 if (id_equal(public_key, dht->close_clientlist[i].public_key)) {
1628 const Client_data *client = &dht->close_clientlist[i]; 1881 const Client_data *const client = &dht->close_clientlist[i];
1882 const IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4, nullptr };
1629 1883
1630 if (ip_isset(&client->assoc6.ip_port.ip)) 1884 for (const IPPTsPng * const *it = assocs; *it; ++it) {
1631 return sendpacket(dht->net, client->assoc6.ip_port, packet, length); 1885 const IPPTsPng *const assoc = *it;
1632 else if (ip_isset(&client->assoc4.ip_port.ip)) 1886
1633 return sendpacket(dht->net, client->assoc4.ip_port, packet, length); 1887 if (ip_isset(&assoc->ip_port.ip)) {
1634 else 1888 return sendpacket(dht->net, assoc->ip_port, packet, length);
1635 break; 1889 }
1890 }
1891
1892 break;
1636 } 1893 }
1637 } 1894 }
1638 1895
@@ -1648,46 +1905,52 @@ int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packe
1648 */ 1905 */
1649static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) 1906static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
1650{ 1907{
1651 if (friend_num >= dht->num_friends) 1908 if (friend_num >= dht->num_friends) {
1652 return -1; 1909 return -1;
1910 }
1653 1911
1654 DHT_Friend *friend = &dht->friends_list[friend_num]; 1912 const DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1655 Client_data *client;
1656 IP_Port ipv4s[MAX_FRIEND_CLIENTS]; 1913 IP_Port ipv4s[MAX_FRIEND_CLIENTS];
1657 int num_ipv4s = 0; 1914 int num_ipv4s = 0;
1658 IP_Port ipv6s[MAX_FRIEND_CLIENTS]; 1915 IP_Port ipv6s[MAX_FRIEND_CLIENTS];
1659 int num_ipv6s = 0; 1916 int num_ipv6s = 0;
1660 int i;
1661 1917
1662 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1918 for (size_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1663 client = &(friend->client_list[i]); 1919 const Client_data *const client = &dht_friend->client_list[i];
1664 1920
1665 /* If ip is not zero and node is good. */ 1921 /* If ip is not zero and node is good. */
1666 if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { 1922 if (ip_isset(&client->assoc4.ret_ip_port.ip)
1923 && !mono_time_is_timeout(dht->mono_time, client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {
1667 ipv4s[num_ipv4s] = client->assoc4.ret_ip_port; 1924 ipv4s[num_ipv4s] = client->assoc4.ret_ip_port;
1668 ++num_ipv4s; 1925 ++num_ipv4s;
1669 } 1926 }
1670 1927
1671 if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) { 1928 if (ip_isset(&client->assoc6.ret_ip_port.ip)
1929 && !mono_time_is_timeout(dht->mono_time, client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) {
1672 ipv6s[num_ipv6s] = client->assoc6.ret_ip_port; 1930 ipv6s[num_ipv6s] = client->assoc6.ret_ip_port;
1673 ++num_ipv6s; 1931 ++num_ipv6s;
1674 } 1932 }
1675 1933
1676 if (id_equal(client->public_key, friend->public_key)) 1934 if (id_equal(client->public_key, dht_friend->public_key)) {
1677 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) 1935 if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)
1936 || !mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)) {
1678 return 0; /* direct connectivity */ 1937 return 0; /* direct connectivity */
1938 }
1939 }
1679 } 1940 }
1680 1941
1681#ifdef FRIEND_IPLIST_PAD 1942#ifdef FRIEND_IPLIST_PAD
1682 memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port)); 1943 memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1683 1944
1684 if (num_ipv6s == MAX_FRIEND_CLIENTS) 1945 if (num_ipv6s == MAX_FRIEND_CLIENTS) {
1685 return MAX_FRIEND_CLIENTS; 1946 return MAX_FRIEND_CLIENTS;
1947 }
1686 1948
1687 int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s; 1949 int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s;
1688 1950
1689 if (num_ipv4s_used > num_ipv4s) 1951 if (num_ipv4s_used > num_ipv4s) {
1690 num_ipv4s_used = num_ipv4s; 1952 num_ipv4s_used = num_ipv4s;
1953 }
1691 1954
1692 memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port)); 1955 memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
1693 return num_ipv6s + num_ipv4s_used; 1956 return num_ipv6s + num_ipv4s_used;
@@ -1716,44 +1979,41 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
1716 */ 1979 */
1717int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) 1980int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
1718{ 1981{
1719 int num = friend_number(dht, friend_id); 1982 const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
1720 1983
1721 if (num == -1) 1984 if (num == UINT32_MAX) {
1722 return 0; 1985 return 0;
1986 }
1723 1987
1724 uint32_t i, sent = 0; 1988 uint32_t sent = 0;
1725 uint8_t friend_sent[MAX_FRIEND_CLIENTS] = {0}; 1989 uint8_t friend_sent[MAX_FRIEND_CLIENTS] = {0};
1726 1990
1727 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1991 IP_Port ip_list[MAX_FRIEND_CLIENTS];
1728 int ip_num = friend_iplist(dht, ip_list, num); 1992 const int ip_num = friend_iplist(dht, ip_list, num);
1729 1993
1730 if (ip_num < (MAX_FRIEND_CLIENTS / 4)) 1994 if (ip_num < (MAX_FRIEND_CLIENTS / 4)) {
1731 return 0; /* Reason for that? */ 1995 return 0; /* Reason for that? */
1996 }
1732 1997
1733 DHT_Friend *friend = &dht->friends_list[num]; 1998 const DHT_Friend *const dht_friend = &dht->friends_list[num];
1734 Client_data *client;
1735 1999
1736 /* extra legwork, because having the outside allocating the space for us 2000 /* extra legwork, because having the outside allocating the space for us
1737 * is *usually* good(tm) (bites us in the behind in this case though) */ 2001 * is *usually* good(tm) (bites us in the behind in this case though) */
1738 uint32_t a;
1739 2002
1740 for (a = 0; a < 2; a++) 2003 for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1741 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 2004 if (friend_sent[i]) {/* Send one packet per client.*/
1742 if (friend_sent[i])/* Send one packet per client.*/ 2005 continue;
1743 continue; 2006 }
1744 2007
1745 client = &friend->client_list[i]; 2008 const Client_data *const client = &dht_friend->client_list[i];
1746 IPPTsPng *assoc = NULL; 2009 const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6, nullptr };
1747 2010
1748 if (!a) 2011 for (const IPPTsPng * const *it = assocs; *it; ++it) {
1749 assoc = &client->assoc4; 2012 const IPPTsPng *const assoc = *it;
1750 else
1751 assoc = &client->assoc6;
1752 2013
1753 /* If ip is not zero and node is good. */ 2014 /* If ip is not zero and node is good. */
1754 if (ip_isset(&assoc->ret_ip_port.ip) && 2015 if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1755 !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 2016 const int retval = sendpacket(dht->net, assoc->ip_port, packet, length);
1756 int retval = sendpacket(dht->net, assoc->ip_port, packet, length);
1757 2017
1758 if ((unsigned int)retval == length) { 2018 if ((unsigned int)retval == length) {
1759 ++sent; 2019 ++sent;
@@ -1761,6 +2021,7 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack
1761 } 2021 }
1762 } 2022 }
1763 } 2023 }
2024 }
1764 2025
1765 return sent; 2026 return sent;
1766} 2027}
@@ -1771,46 +2032,44 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack
1771 */ 2032 */
1772static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length) 2033static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
1773{ 2034{
1774 int num = friend_number(dht, friend_id); 2035 const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
1775 2036
1776 if (num == -1) 2037 if (num == UINT32_MAX) {
1777 return 0; 2038 return 0;
2039 }
1778 2040
1779 DHT_Friend *friend = &dht->friends_list[num]; 2041 const DHT_Friend *const dht_friend = &dht->friends_list[num];
1780 Client_data *client;
1781 2042
1782 IP_Port ip_list[MAX_FRIEND_CLIENTS * 2]; 2043 IP_Port ip_list[MAX_FRIEND_CLIENTS * 2];
1783 int n = 0; 2044 int n = 0;
1784 uint32_t i;
1785 2045
1786 /* extra legwork, because having the outside allocating the space for us 2046 /* extra legwork, because having the outside allocating the space for us
1787 * is *usually* good(tm) (bites us in the behind in this case though) */ 2047 * is *usually* good(tm) (bites us in the behind in this case though) */
1788 uint32_t a;
1789 2048
1790 for (a = 0; a < 2; a++) 2049 for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1791 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 2050 const Client_data *const client = &dht_friend->client_list[i];
1792 client = &friend->client_list[i]; 2051 const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6, nullptr };
1793 IPPTsPng *assoc = NULL;
1794 2052
1795 if (!a) 2053 for (const IPPTsPng * const *it = assocs; *it; ++it) {
1796 assoc = &client->assoc4; 2054 const IPPTsPng *const assoc = *it;
1797 else
1798 assoc = &client->assoc6;
1799 2055
1800 /* If ip is not zero and node is good. */ 2056 /* If ip is not zero and node is good. */
1801 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 2057 if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1802 ip_list[n] = assoc->ip_port; 2058 ip_list[n] = assoc->ip_port;
1803 ++n; 2059 ++n;
1804 } 2060 }
1805 } 2061 }
2062 }
1806 2063
1807 if (n < 1) 2064 if (n < 1) {
1808 return 0; 2065 return 0;
2066 }
1809 2067
1810 int retval = sendpacket(dht->net, ip_list[rand() % n], packet, length); 2068 const int retval = sendpacket(dht->net, ip_list[random_u32() % n], packet, length);
1811 2069
1812 if ((unsigned int)retval == length) 2070 if ((unsigned int)retval == length) {
1813 return 1; 2071 return 1;
2072 }
1814 2073
1815 return 0; 2074 return 0;
1816} 2075}
@@ -1828,50 +2087,58 @@ static int send_NATping(DHT *dht, const uint8_t *public_key, uint64_t ping_id, u
1828 data[0] = type; 2087 data[0] = type;
1829 memcpy(data + 1, &ping_id, sizeof(uint64_t)); 2088 memcpy(data + 1, &ping_id, sizeof(uint64_t));
1830 /* 254 is NAT ping request packet id */ 2089 /* 254 is NAT ping request packet id */
1831 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, public_key, data, 2090 const int len = create_request(
1832 sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING); 2091 dht->self_public_key, dht->self_secret_key, packet, public_key, data,
2092 sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);
1833 2093
1834 if (len == -1) 2094 if (len == -1) {
1835 return -1; 2095 return -1;
2096 }
1836 2097
1837 if (type == 0) /* If packet is request use many people to route it. */ 2098 if (type == 0) { /* If packet is request use many people to route it. */
1838 num = route_tofriend(dht, public_key, packet, len); 2099 num = route_tofriend(dht, public_key, packet, len);
1839 else if (type == 1) /* If packet is response use only one person to route it */ 2100 } else if (type == 1) { /* If packet is response use only one person to route it */
1840 num = routeone_tofriend(dht, public_key, packet, len); 2101 num = routeone_tofriend(dht, public_key, packet, len);
2102 }
1841 2103
1842 if (num == 0) 2104 if (num == 0) {
1843 return -1; 2105 return -1;
2106 }
1844 2107
1845 return num; 2108 return num;
1846} 2109}
1847 2110
1848/* Handle a received ping request for. */ 2111/* Handle a received ping request for. */
1849static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, 2112static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
1850 uint16_t length) 2113 uint16_t length, void *userdata)
1851{ 2114{
1852 if (length != sizeof(uint64_t) + 1) 2115 if (length != sizeof(uint64_t) + 1) {
1853 return 1; 2116 return 1;
2117 }
1854 2118
1855 DHT *dht = object; 2119 DHT *const dht = (DHT *)object;
1856 uint64_t ping_id; 2120 uint64_t ping_id;
1857 memcpy(&ping_id, packet + 1, sizeof(uint64_t)); 2121 memcpy(&ping_id, packet + 1, sizeof(uint64_t));
1858 2122
1859 int friendnumber = friend_number(dht, source_pubkey); 2123 uint32_t friendnumber = index_of_friend_pk(dht->friends_list, dht->num_friends, source_pubkey);
1860 2124
1861 if (friendnumber == -1) 2125 if (friendnumber == UINT32_MAX) {
1862 return 1; 2126 return 1;
2127 }
1863 2128
1864 DHT_Friend *friend = &dht->friends_list[friendnumber]; 2129 DHT_Friend *const dht_friend = &dht->friends_list[friendnumber];
1865 2130
1866 if (packet[0] == NAT_PING_REQUEST) { 2131 if (packet[0] == NAT_PING_REQUEST) {
1867 /* 1 is reply */ 2132 /* 1 is reply */
1868 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); 2133 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
1869 friend->nat.recvNATping_timestamp = unix_time(); 2134 dht_friend->nat.recv_nat_ping_timestamp = mono_time_get(dht->mono_time);
1870 return 0; 2135 return 0;
1871 } else if (packet[0] == NAT_PING_RESPONSE) { 2136 }
1872 if (friend->nat.NATping_id == ping_id) { 2137
1873 friend->nat.NATping_id = random_64b(); 2138 if (packet[0] == NAT_PING_RESPONSE) {
1874 friend->nat.hole_punching = 1; 2139 if (dht_friend->nat.nat_ping_id == ping_id) {
2140 dht_friend->nat.nat_ping_id = random_u64();
2141 dht_friend->nat.hole_punching = 1;
1875 return 0; 2142 return 0;
1876 } 2143 }
1877 } 2144 }
@@ -1885,25 +2152,27 @@ static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pu
1885 * 2152 *
1886 * return ip of 0 if failure. 2153 * return ip of 0 if failure.
1887 */ 2154 */
1888static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) 2155static IP nat_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1889{ 2156{
1890 IP zero; 2157 IP zero;
1891 ip_reset(&zero); 2158 ip_reset(&zero);
1892 2159
1893 if (len > MAX_FRIEND_CLIENTS) 2160 if (len > MAX_FRIEND_CLIENTS) {
1894 return zero; 2161 return zero;
2162 }
1895 2163
1896 uint32_t i, j;
1897 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; 2164 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
1898 2165
1899 for (i = 0; i < len; ++i) { 2166 for (uint32_t i = 0; i < len; ++i) {
1900 for (j = 0; j < len; ++j) { 2167 for (uint32_t j = 0; j < len; ++j) {
1901 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) 2168 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) {
1902 ++numbers[i]; 2169 ++numbers[i];
2170 }
1903 } 2171 }
1904 2172
1905 if (numbers[i] >= min_num) 2173 if (numbers[i] >= min_num) {
1906 return ip_portlist[i].ip; 2174 return ip_portlist[i].ip;
2175 }
1907 } 2176 }
1908 2177
1909 return zero; 2178 return zero;
@@ -1915,14 +2184,13 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1915 * 2184 *
1916 * return number of ports and puts the list of ports in portlist. 2185 * return number of ports and puts the list of ports in portlist.
1917 */ 2186 */
1918static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip) 2187static uint16_t nat_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip)
1919{ 2188{
1920 uint32_t i;
1921 uint16_t num = 0; 2189 uint16_t num = 0;
1922 2190
1923 for (i = 0; i < len; ++i) { 2191 for (uint32_t i = 0; i < len; ++i) {
1924 if (ip_equal(&ip_portlist[i].ip, &ip)) { 2192 if (ip_equal(&ip_portlist[i].ip, &ip)) {
1925 portlist[num] = ntohs(ip_portlist[i].port); 2193 portlist[num] = net_ntohs(ip_portlist[i].port);
1926 ++num; 2194 ++num;
1927 } 2195 }
1928 } 2196 }
@@ -1932,48 +2200,57 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1932 2200
1933static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) 2201static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num)
1934{ 2202{
1935 if (numports > MAX_FRIEND_CLIENTS || numports == 0) 2203 if (!dht->hole_punching_enabled) {
1936 return; 2204 return;
2205 }
2206
2207 if (numports > MAX_FRIEND_CLIENTS || numports == 0) {
2208 return;
2209 }
1937 2210
2211 const uint16_t first_port = port_list[0];
1938 uint32_t i; 2212 uint32_t i;
1939 uint32_t top = dht->friends_list[friend_num].nat.punching_index + MAX_PUNCHING_PORTS;
1940 uint16_t firstport = port_list[0];
1941 2213
1942 for (i = 0; i < numports; ++i) { 2214 for (i = 0; i < numports; ++i) {
1943 if (firstport != port_list[i]) 2215 if (first_port != port_list[i]) {
1944 break; 2216 break;
2217 }
1945 } 2218 }
1946 2219
1947 if (i == numports) { /* If all ports are the same, only try that one port. */ 2220 if (i == numports) { /* If all ports are the same, only try that one port. */
1948 IP_Port pinging; 2221 IP_Port pinging;
1949 ip_copy(&pinging.ip, &ip); 2222 ip_copy(&pinging.ip, &ip);
1950 pinging.port = htons(firstport); 2223 pinging.port = net_htons(first_port);
1951 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); 2224 ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
1952 } else { 2225 } else {
1953 for (i = dht->friends_list[friend_num].nat.punching_index; i != top; ++i) { 2226 for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
1954 /* TODO: Improve port guessing algorithm. */ 2227 /* TODO(irungentoo): Improve port guessing algorithm. */
1955 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 2228 const uint32_t it = i + dht->friends_list[friend_num].nat.punching_index;
2229 const int8_t sign = (it % 2) ? -1 : 1;
2230 const uint32_t delta = sign * (it / (2 * numports));
2231 const uint32_t index = (it / 2) % numports;
2232 const uint16_t port = port_list[index] + delta;
1956 IP_Port pinging; 2233 IP_Port pinging;
1957 ip_copy(&pinging.ip, &ip); 2234 ip_copy(&pinging.ip, &ip);
1958 pinging.port = htons(port); 2235 pinging.port = net_htons(port);
1959 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); 2236 ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
1960 } 2237 }
1961 2238
1962 dht->friends_list[friend_num].nat.punching_index = i; 2239 dht->friends_list[friend_num].nat.punching_index += i;
1963 } 2240 }
1964 2241
1965 if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) { 2242 if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) {
1966 top = dht->friends_list[friend_num].nat.punching_index2 + MAX_PUNCHING_PORTS; 2243 const uint16_t port = 1024;
1967 uint16_t port = 1024;
1968 IP_Port pinging; 2244 IP_Port pinging;
1969 ip_copy(&pinging.ip, &ip); 2245 ip_copy(&pinging.ip, &ip);
1970 2246
1971 for (i = dht->friends_list[friend_num].nat.punching_index2; i != top; ++i) { 2247 for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
1972 pinging.port = htons(port + i); 2248 uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;
1973 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key); 2249 pinging.port = net_htons(port + it);
2250 ping_send_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
1974 } 2251 }
1975 2252
1976 dht->friends_list[friend_num].nat.punching_index2 = i - (MAX_PUNCHING_PORTS / 2); 2253 dht->friends_list[friend_num].nat.punching_index2 += i - (MAX_PUNCHING_PORTS / 2);
1977 } 2254 }
1978 2255
1979 ++dht->friends_list[friend_num].nat.tries; 2256 ++dht->friends_list[friend_num].nat.tries;
@@ -1981,33 +2258,40 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
1981 2258
1982static void do_NAT(DHT *dht) 2259static void do_NAT(DHT *dht)
1983{ 2260{
1984 uint32_t i; 2261 const uint64_t temp_time = mono_time_get(dht->mono_time);
1985 uint64_t temp_time = unix_time();
1986 2262
1987 for (i = 0; i < dht->num_friends; ++i) { 2263 for (uint32_t i = 0; i < dht->num_friends; ++i) {
1988 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 2264 IP_Port ip_list[MAX_FRIEND_CLIENTS];
1989 int num = friend_iplist(dht, ip_list, i); 2265 const int num = friend_iplist(dht, ip_list, i);
1990 2266
1991 /* If already connected or friend is not online don't try to hole punch. */ 2267 /* If already connected or friend is not online don't try to hole punch. */
1992 if (num < MAX_FRIEND_CLIENTS / 2) 2268 if (num < MAX_FRIEND_CLIENTS / 2) {
1993 continue; 2269 continue;
2270 }
1994 2271
1995 if (dht->friends_list[i].nat.NATping_timestamp + PUNCH_INTERVAL < temp_time) { 2272 if (dht->friends_list[i].nat.nat_ping_timestamp + PUNCH_INTERVAL < temp_time) {
1996 send_NATping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.NATping_id, NAT_PING_REQUEST); 2273 send_NATping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.nat_ping_id, NAT_PING_REQUEST);
1997 dht->friends_list[i].nat.NATping_timestamp = temp_time; 2274 dht->friends_list[i].nat.nat_ping_timestamp = temp_time;
1998 } 2275 }
1999 2276
2000 if (dht->friends_list[i].nat.hole_punching == 1 && 2277 if (dht->friends_list[i].nat.hole_punching == 1 &&
2001 dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time && 2278 dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time &&
2002 dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 2279 dht->friends_list[i].nat.recv_nat_ping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
2003 2280
2004 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 2281 const IP ip = nat_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
2005 2282
2006 if (!ip_isset(&ip)) 2283 if (!ip_isset(&ip)) {
2007 continue; 2284 continue;
2285 }
2286
2287 if (dht->friends_list[i].nat.punching_timestamp + PUNCH_RESET_TIME < temp_time) {
2288 dht->friends_list[i].nat.tries = 0;
2289 dht->friends_list[i].nat.punching_index = 0;
2290 dht->friends_list[i].nat.punching_index2 = 0;
2291 }
2008 2292
2009 uint16_t port_list[MAX_FRIEND_CLIENTS]; 2293 uint16_t port_list[MAX_FRIEND_CLIENTS];
2010 uint16_t numports = NAT_getports(port_list, ip_list, num, ip); 2294 const uint16_t numports = nat_getports(port_list, ip_list, num, ip);
2011 punch_holes(dht, ip, port_list, numports, i); 2295 punch_holes(dht, ip, port_list, numports, i);
2012 2296
2013 dht->friends_list[i].nat.punching_timestamp = temp_time; 2297 dht->friends_list[i].nat.punching_timestamp = temp_time;
@@ -2019,29 +2303,36 @@ static void do_NAT(DHT *dht)
2019/*----------------------------------------------------------------------------------*/ 2303/*----------------------------------------------------------------------------------*/
2020/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ 2304/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
2021 2305
2022#define HARDREQ_DATA_SIZE 384 /* Attempt to prevent amplification/other attacks*/ 2306#define DHT_HARDENING 0
2307#define HARDREQ_DATA_SIZE 384 // Attempt to prevent amplification/other attacks
2023 2308
2024#define CHECK_TYPE_ROUTE_REQ 0 2309typedef enum Check_Type {
2025#define CHECK_TYPE_ROUTE_RES 1 2310 CHECK_TYPE_ROUTE_REQ = 0,
2026#define CHECK_TYPE_GETNODE_REQ 2 2311 CHECK_TYPE_ROUTE_RES = 1,
2027#define CHECK_TYPE_GETNODE_RES 3 2312 CHECK_TYPE_GETNODE_REQ = 2,
2028#define CHECK_TYPE_TEST_REQ 4 2313 CHECK_TYPE_GETNODE_RES = 3,
2029#define CHECK_TYPE_TEST_RES 5 2314 CHECK_TYPE_TEST_REQ = 4,
2315 CHECK_TYPE_TEST_RES = 5,
2316} Check_Type;
2030 2317
2318#if DHT_HARDENING
2031static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length) 2319static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length)
2032{ 2320{
2033 if (length > HARDREQ_DATA_SIZE - 1) 2321 if (length > HARDREQ_DATA_SIZE - 1) {
2034 return -1; 2322 return -1;
2323 }
2035 2324
2036 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; 2325 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
2037 uint8_t data[HARDREQ_DATA_SIZE] = {0}; 2326 uint8_t data[HARDREQ_DATA_SIZE] = {0};
2038 data[0] = type; 2327 data[0] = type;
2039 memcpy(data + 1, contents, length); 2328 memcpy(data + 1, contents, length);
2040 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data, 2329 const int len = create_request(
2041 sizeof(data), CRYPTO_PACKET_HARDENING); 2330 dht->self_public_key, dht->self_secret_key, packet, sendto->public_key,
2331 data, sizeof(data), CRYPTO_PACKET_HARDENING);
2042 2332
2043 if (len == -1) 2333 if (len == -1) {
2044 return -1; 2334 return -1;
2335 }
2045 2336
2046 return sendpacket(dht->net, sendto->ip_port, packet, len); 2337 return sendpacket(dht->net, sendto->ip_port, packet, len);
2047} 2338}
@@ -2049,70 +2340,75 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8
2049/* Send a get node hardening request */ 2340/* Send a get node hardening request */
2050static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id) 2341static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id)
2051{ 2342{
2052 uint8_t data[sizeof(Node_format) + crypto_box_PUBLICKEYBYTES]; 2343 uint8_t data[sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE];
2053 memcpy(data, node_totest, sizeof(Node_format)); 2344 memcpy(data, node_totest, sizeof(Node_format));
2054 memcpy(data + sizeof(Node_format), search_id, crypto_box_PUBLICKEYBYTES); 2345 memcpy(data + sizeof(Node_format), search_id, CRYPTO_PUBLIC_KEY_SIZE);
2055 return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + crypto_box_PUBLICKEYBYTES); 2346 return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE);
2056} 2347}
2348#endif
2057 2349
2058/* Send a get node hardening response */ 2350/* Send a get node hardening response */
2059static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id, 2351static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id,
2060 const uint8_t *nodes_data, uint16_t nodes_data_length) 2352 const uint8_t *nodes_data, uint16_t nodes_data_length)
2061{ 2353{
2062 if (!ip_isset(&sendto->ip_port.ip)) 2354 if (!ip_isset(&sendto->ip_port.ip)) {
2063 return -1; 2355 return -1;
2356 }
2064 2357
2065 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; 2358 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
2066 uint8_t data[1 + crypto_box_PUBLICKEYBYTES + nodes_data_length]; 2359 VLA(uint8_t, data, 1 + CRYPTO_PUBLIC_KEY_SIZE + nodes_data_length);
2067 data[0] = CHECK_TYPE_GETNODE_RES; 2360 data[0] = CHECK_TYPE_GETNODE_RES;
2068 memcpy(data + 1, queried_client_id, crypto_box_PUBLICKEYBYTES); 2361 memcpy(data + 1, queried_client_id, CRYPTO_PUBLIC_KEY_SIZE);
2069 memcpy(data + 1 + crypto_box_PUBLICKEYBYTES, nodes_data, nodes_data_length); 2362 memcpy(data + 1 + CRYPTO_PUBLIC_KEY_SIZE, nodes_data, nodes_data_length);
2070 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data, 2363 const int len = create_request(
2071 sizeof(data), CRYPTO_PACKET_HARDENING); 2364 dht->self_public_key, dht->self_secret_key, packet, sendto->public_key,
2365 data, SIZEOF_VLA(data), CRYPTO_PACKET_HARDENING);
2072 2366
2073 if (len == -1) 2367 if (len == -1) {
2074 return -1; 2368 return -1;
2369 }
2075 2370
2076 return sendpacket(dht->net, sendto->ip_port, packet, len); 2371 return sendpacket(dht->net, sendto->ip_port, packet, len);
2077} 2372}
2078 2373
2079/* TODO: improve */ 2374/* TODO(irungentoo): improve */
2080static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, sa_family_t sa_family) 2375static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, Family sa_family)
2081{ 2376{
2082 uint32_t i; 2377 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2083 2378 if (!id_equal(dht->close_clientlist[i].public_key, public_key)) {
2084 for (i = 0; i < LCLIENT_LIST; ++i) {
2085 if (public_key_cmp(dht->close_clientlist[i].public_key, public_key) != 0)
2086 continue; 2379 continue;
2380 }
2087 2381
2088 if (sa_family == AF_INET) 2382 if (net_family_is_ipv4(sa_family)) {
2089 return &dht->close_clientlist[i].assoc4; 2383 return &dht->close_clientlist[i].assoc4;
2090 else if (sa_family == AF_INET6) 2384 }
2385
2386 if (net_family_is_ipv6(sa_family)) {
2091 return &dht->close_clientlist[i].assoc6; 2387 return &dht->close_clientlist[i].assoc6;
2388 }
2092 } 2389 }
2093 2390
2094 return NULL; 2391 return nullptr;
2095} 2392}
2096 2393
2097/* 2394/*
2098 * check how many nodes in nodes are also present in the closelist. 2395 * check how many nodes in nodes are also present in the closelist.
2099 * TODO: make this function better. 2396 * TODO(irungentoo): make this function better.
2100 */ 2397 */
2101static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num) 2398static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
2102{ 2399{
2103 uint32_t counter = 0; 2400 uint32_t counter = 0;
2104 uint32_t i;
2105 2401
2106 for (i = 0; i < num; ++i) { 2402 for (uint32_t i = 0; i < num; ++i) {
2107 if (id_equal(nodes[i].public_key, dht->self_public_key)) { 2403 if (id_equal(nodes[i].public_key, dht->self_public_key)) {
2108 ++counter; 2404 ++counter;
2109 continue; 2405 continue;
2110 } 2406 }
2111 2407
2112 IPPTsPng *temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family); 2408 const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);
2113 2409
2114 if (temp) { 2410 if (temp) {
2115 if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) { 2411 if (!mono_time_is_timeout(dht->mono_time, temp->timestamp, BAD_NODE_TIMEOUT)) {
2116 ++counter; 2412 ++counter;
2117 } 2413 }
2118 } 2414 }
@@ -2123,13 +2419,12 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
2123 2419
2124/* Interval in seconds between hardening checks */ 2420/* Interval in seconds between hardening checks */
2125#define HARDENING_INTERVAL 120 2421#define HARDENING_INTERVAL 120
2126#define HARDEN_TIMEOUT 1200
2127 2422
2128/* Handle a received hardening packet */ 2423/* Handle a received hardening packet */
2129static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, 2424static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
2130 uint16_t length) 2425 uint16_t length, void *userdata)
2131{ 2426{
2132 DHT *dht = object; 2427 DHT *const dht = (DHT *)object;
2133 2428
2134 if (length < 2) { 2429 if (length < 2) {
2135 return 1; 2430 return 1;
@@ -2137,50 +2432,60 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
2137 2432
2138 switch (packet[0]) { 2433 switch (packet[0]) {
2139 case CHECK_TYPE_GETNODE_REQ: { 2434 case CHECK_TYPE_GETNODE_REQ: {
2140 if (length != HARDREQ_DATA_SIZE) 2435 if (length != HARDREQ_DATA_SIZE) {
2141 return 1; 2436 return 1;
2437 }
2142 2438
2143 Node_format node, tocheck_node; 2439 Node_format node, tocheck_node;
2144 node.ip_port = source; 2440 node.ip_port = source;
2145 memcpy(node.public_key, source_pubkey, crypto_box_PUBLICKEYBYTES); 2441 memcpy(node.public_key, source_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
2146 memcpy(&tocheck_node, packet + 1, sizeof(Node_format)); 2442 memcpy(&tocheck_node, packet + 1, sizeof(Node_format));
2147 2443
2148 if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1) 2444 if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1) {
2149 return 1; 2445 return 1;
2446 }
2150 2447
2151 return 0; 2448 return 0;
2152 } 2449 }
2153 2450
2154 case CHECK_TYPE_GETNODE_RES: { 2451 case CHECK_TYPE_GETNODE_RES: {
2155 if (length <= crypto_box_PUBLICKEYBYTES + 1) 2452 if (length <= CRYPTO_PUBLIC_KEY_SIZE + 1) {
2156 return 1; 2453 return 1;
2454 }
2157 2455
2158 if (length > 1 + crypto_box_PUBLICKEYBYTES + sizeof(Node_format) * MAX_SENT_NODES) 2456 if (length > 1 + CRYPTO_PUBLIC_KEY_SIZE + sizeof(Node_format) * MAX_SENT_NODES) {
2159 return 1; 2457 return 1;
2458 }
2160 2459
2161 uint16_t length_nodes = length - 1 - crypto_box_PUBLICKEYBYTES; 2460 uint16_t length_nodes = length - 1 - CRYPTO_PUBLIC_KEY_SIZE;
2162 Node_format nodes[MAX_SENT_NODES]; 2461 Node_format nodes[MAX_SENT_NODES];
2163 int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + crypto_box_PUBLICKEYBYTES, length_nodes, 0); 2462 const int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
2463 length_nodes, 0);
2164 2464
2165 /* TODO: MAX_SENT_NODES nodes should be returned at all times 2465 /* TODO(irungentoo): MAX_SENT_NODES nodes should be returned at all times
2166 (right now we have a small network size so it could cause problems for testing and etc..) */ 2466 (right now we have a small network size so it could cause problems for testing and etc..) */
2167 if (num_nodes <= 0) 2467 if (num_nodes <= 0) {
2168 return 1; 2468 return 1;
2469 }
2169 2470
2170 /* NOTE: This should work for now but should be changed to something better. */ 2471 /* NOTE: This should work for now but should be changed to something better. */
2171 if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) 2472 if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) {
2172 return 1; 2473 return 1;
2474 }
2173 2475
2174 IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); 2476 IPPTsPng *const temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family);
2175 2477
2176 if (temp == NULL) 2478 if (temp == nullptr) {
2177 return 1; 2479 return 1;
2480 }
2178 2481
2179 if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) 2482 if (mono_time_is_timeout(dht->mono_time, temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
2180 return 1; 2483 return 1;
2484 }
2181 2485
2182 if (public_key_cmp(temp->hardening.send_nodes_pingedid, source_pubkey) != 0) 2486 if (!id_equal(temp->hardening.send_nodes_pingedid, source_pubkey)) {
2183 return 1; 2487 return 1;
2488 }
2184 2489
2185 /* If Nodes look good and the request checks out */ 2490 /* If Nodes look good and the request checks out */
2186 temp->hardening.send_nodes_ok = 1; 2491 temp->hardening.send_nodes_ok = 1;
@@ -2191,62 +2496,69 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
2191 return 1; 2496 return 1;
2192} 2497}
2193 2498
2499#if DHT_HARDENING
2500#define HARDEN_TIMEOUT 1200
2501
2194/* Return a random node from all the nodes we are connected to. 2502/* Return a random node from all the nodes we are connected to.
2195 * TODO: improve this function. 2503 * TODO(irungentoo): improve this function.
2196 */ 2504 */
2197Node_format random_node(DHT *dht, sa_family_t sa_family) 2505static Node_format random_node(DHT *dht, Family sa_family)
2198{ 2506{
2199 uint8_t id[crypto_box_PUBLICKEYBYTES]; 2507 uint8_t id[CRYPTO_PUBLIC_KEY_SIZE];
2200 uint32_t i;
2201 2508
2202 for (i = 0; i < crypto_box_PUBLICKEYBYTES / 4; ++i) { /* populate the id with pseudorandom bytes.*/ 2509 for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE / 4; ++i) { /* populate the id with pseudorandom bytes.*/
2203 uint32_t t = rand(); 2510 const uint32_t t = random_u32();
2204 memcpy(id + i * sizeof(t), &t, sizeof(t)); 2511 memcpy(id + i * sizeof(t), &t, sizeof(t));
2205 } 2512 }
2206 2513
2207 Node_format nodes_list[MAX_SENT_NODES]; 2514 Node_format nodes_list[MAX_SENT_NODES];
2208 memset(nodes_list, 0, sizeof(nodes_list)); 2515 memset(nodes_list, 0, sizeof(nodes_list));
2209 uint32_t num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1, 0); 2516 const uint32_t num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1, 0);
2210 2517
2211 if (num_nodes == 0) 2518 if (num_nodes == 0) {
2212 return nodes_list[0]; 2519 return nodes_list[0];
2213 else 2520 }
2214 return nodes_list[rand() % num_nodes]; 2521
2522 return nodes_list[random_u32() % num_nodes];
2215} 2523}
2524#endif
2216 2525
2217/* Put up to max_num nodes in nodes from the closelist. 2526/* Put up to max_num nodes in nodes from the closelist.
2218 * 2527 *
2219 * return the number of nodes. 2528 * return the number of nodes.
2220 */ 2529 */
2221uint16_t list_nodes(Client_data *list, unsigned int length, Node_format *nodes, uint16_t max_num) 2530static uint16_t list_nodes(Client_data *list, size_t length, const Mono_Time *mono_time, Node_format *nodes,
2531 uint16_t max_num)
2222{ 2532{
2223 if (max_num == 0) 2533 if (max_num == 0) {
2224 return 0; 2534 return 0;
2535 }
2225 2536
2226 uint16_t count = 0; 2537 uint16_t count = 0;
2227 2538
2228 unsigned int i; 2539 for (size_t i = length; i != 0; --i) {
2540 const IPPTsPng *assoc = nullptr;
2229 2541
2230 for (i = length; i != 0; --i) { 2542 if (!mono_time_is_timeout(mono_time, list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) {
2231 IPPTsPng *assoc = NULL;
2232
2233 if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT))
2234 assoc = &list[i - 1].assoc4; 2543 assoc = &list[i - 1].assoc4;
2544 }
2235 2545
2236 if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) { 2546 if (!mono_time_is_timeout(mono_time, list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) {
2237 if (assoc == NULL) 2547 if (assoc == nullptr) {
2238 assoc = &list[i - 1].assoc6; 2548 assoc = &list[i - 1].assoc6;
2239 else if (rand() % 2) 2549 } else if (random_u08() % 2) {
2240 assoc = &list[i - 1].assoc6; 2550 assoc = &list[i - 1].assoc6;
2551 }
2241 } 2552 }
2242 2553
2243 if (assoc != NULL) { 2554 if (assoc != nullptr) {
2244 memcpy(nodes[count].public_key, list[i - 1].public_key, crypto_box_PUBLICKEYBYTES); 2555 memcpy(nodes[count].public_key, list[i - 1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2245 nodes[count].ip_port = assoc->ip_port; 2556 nodes[count].ip_port = assoc->ip_port;
2246 ++count; 2557 ++count;
2247 2558
2248 if (count >= max_num) 2559 if (count >= max_num) {
2249 return count; 2560 return count;
2561 }
2250 } 2562 }
2251 } 2563 }
2252 2564
@@ -2259,18 +2571,20 @@ uint16_t list_nodes(Client_data *list, unsigned int length, Node_format *nodes,
2259 */ 2571 */
2260uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) 2572uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2261{ 2573{
2262 if (max_num == 0) 2574 if (max_num == 0) {
2263 return 0; 2575 return 0;
2576 }
2264 2577
2265 uint16_t count = 0; 2578 uint16_t count = 0;
2266 unsigned int i, r = rand(); 2579 const uint32_t r = random_u32();
2267 2580
2268 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { 2581 for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
2269 count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, nodes + count, 2582 count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->mono_time,
2270 max_num - count); 2583 nodes + count, max_num - count);
2271 2584
2272 if (count >= max_num) 2585 if (count >= max_num) {
2273 break; 2586 break;
2587 }
2274 } 2588 }
2275 2589
2276 return count; 2590 return count;
@@ -2282,96 +2596,107 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2282 */ 2596 */
2283uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) 2597uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2284{ 2598{
2285 return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num); 2599 return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->mono_time, nodes, max_num);
2286} 2600}
2287 2601
2288void do_hardening(DHT *dht) 2602#if DHT_HARDENING
2603static void do_hardening(DHT *dht)
2289{ 2604{
2290 uint32_t i; 2605 for (uint32_t i = 0; i < LCLIENT_LIST * 2; ++i) {
2291 2606 IPPTsPng *cur_iptspng;
2292 for (i = 0; i < LCLIENT_LIST * 2; ++i) { 2607 Family sa_family;
2293 IPPTsPng *cur_iptspng; 2608 const uint8_t *const public_key = dht->close_clientlist[i / 2].public_key;
2294 sa_family_t sa_family;
2295 uint8_t *public_key = dht->close_clientlist[i / 2].public_key;
2296 2609
2297 if (i % 2 == 0) { 2610 if (i % 2 == 0) {
2298 cur_iptspng = &dht->close_clientlist[i / 2].assoc4; 2611 cur_iptspng = &dht->close_clientlist[i / 2].assoc4;
2299 sa_family = AF_INET; 2612 sa_family = net_family_ipv4;
2300 } else { 2613 } else {
2301 cur_iptspng = &dht->close_clientlist[i / 2].assoc6; 2614 cur_iptspng = &dht->close_clientlist[i / 2].assoc6;
2302 sa_family = AF_INET6; 2615 sa_family = net_family_ipv6;
2303 } 2616 }
2304 2617
2305 if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) 2618 if (mono_time_is_timeout(dht->mono_time, cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) {
2306 continue; 2619 continue;
2620 }
2307 2621
2308 if (cur_iptspng->hardening.send_nodes_ok == 0) { 2622 if (cur_iptspng->hardening.send_nodes_ok == 0) {
2309 if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { 2623 if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
2310 Node_format rand_node = random_node(dht, sa_family); 2624 Node_format rand_node = random_node(dht, sa_family);
2311 2625
2312 if (!ipport_isset(&rand_node.ip_port)) 2626 if (!ipport_isset(&rand_node.ip_port)) {
2313 continue; 2627 continue;
2628 }
2314 2629
2315 if (id_equal(public_key, rand_node.public_key)) 2630 if (id_equal(public_key, rand_node.public_key)) {
2316 continue; 2631 continue;
2632 }
2317 2633
2318 Node_format to_test; 2634 Node_format to_test;
2319 to_test.ip_port = cur_iptspng->ip_port; 2635 to_test.ip_port = cur_iptspng->ip_port;
2320 memcpy(to_test.public_key, public_key, crypto_box_PUBLICKEYBYTES); 2636 memcpy(to_test.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
2321 2637
2322 //TODO: The search id should maybe not be ours? 2638 // TODO(irungentoo): The search id should maybe not be ours?
2323 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { 2639 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) {
2324 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, crypto_box_PUBLICKEYBYTES); 2640 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE);
2325 cur_iptspng->hardening.send_nodes_timestamp = unix_time(); 2641 cur_iptspng->hardening.send_nodes_timestamp = mono_time_get(dht->mono_time);
2326 } 2642 }
2327 } 2643 }
2328 } else { 2644 } else {
2329 if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) { 2645 if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) {
2330 cur_iptspng->hardening.send_nodes_ok = 0; 2646 cur_iptspng->hardening.send_nodes_ok = 0;
2331 } 2647 }
2332 } 2648 }
2333 2649
2334 //TODO: add the 2 other testers. 2650 // TODO(irungentoo): add the 2 other testers.
2335 } 2651 }
2336} 2652}
2653#endif
2337 2654
2338/*----------------------------------------------------------------------------------*/ 2655/*----------------------------------------------------------------------------------*/
2339 2656
2340void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object) 2657void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_cb *cb, void *object)
2341{ 2658{
2342 dht->cryptopackethandlers[byte].function = cb; 2659 dht->cryptopackethandlers[byte].function = cb;
2343 dht->cryptopackethandlers[byte].object = object; 2660 dht->cryptopackethandlers[byte].object = object;
2344} 2661}
2345 2662
2346static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length) 2663static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
2347{ 2664{
2348 DHT *dht = object; 2665 DHT *const dht = (DHT *)object;
2349 2666
2350 if (packet[0] == NET_PACKET_CRYPTO) { 2667 assert(packet[0] == NET_PACKET_CRYPTO);
2351 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES ||
2352 length > MAX_CRYPTO_REQUEST_SIZE + crypto_box_MACBYTES)
2353 return 1;
2354 2668
2355 if (public_key_cmp(packet + 1, dht->self_public_key) == 0) { // Check if request is for us. 2669 if (length <= CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1 + CRYPTO_MAC_SIZE ||
2356 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 2670 length > MAX_CRYPTO_REQUEST_SIZE + CRYPTO_MAC_SIZE) {
2357 uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; 2671 return 1;
2358 uint8_t number; 2672 }
2359 int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length);
2360 2673
2361 if (len == -1 || len == 0) 2674 // Check if request is for us.
2362 return 1; 2675 if (id_equal(packet + 1, dht->self_public_key)) {
2676 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
2677 uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
2678 uint8_t number;
2679 const int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key,
2680 data, &number, packet, length);
2363 2681
2364 if (!dht->cryptopackethandlers[number].function) return 1; 2682 if (len == -1 || len == 0) {
2683 return 1;
2684 }
2685
2686 if (!dht->cryptopackethandlers[number].function) {
2687 return 1;
2688 }
2365 2689
2366 return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key, 2690 return dht->cryptopackethandlers[number].function(
2367 data, len); 2691 dht->cryptopackethandlers[number].object, source, public_key,
2692 data, len, userdata);
2693 }
2368 2694
2369 } else { /* If request is not for us, try routing it. */ 2695 /* If request is not for us, try routing it. */
2370 int retval = route_packet(dht, packet + 1, packet, length); 2696 const int retval = route_packet(dht, packet + 1, packet, length);
2371 2697
2372 if ((unsigned int)retval == length) 2698 if ((unsigned int)retval == length) {
2373 return 0; 2699 return 0;
2374 }
2375 } 2700 }
2376 2701
2377 return 1; 2702 return 1;
@@ -2379,25 +2704,29 @@ static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *pack
2379 2704
2380/*----------------------------------------------------------------------------------*/ 2705/*----------------------------------------------------------------------------------*/
2381 2706
2382DHT *new_DHT(Networking_Core *net) 2707DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled)
2383{ 2708{
2384 /* init time */ 2709 if (net == nullptr) {
2385 unix_time_update(); 2710 return nullptr;
2386 2711 }
2387 if (net == NULL)
2388 return NULL;
2389 2712
2390 DHT *dht = calloc(1, sizeof(DHT)); 2713 DHT *const dht = (DHT *)calloc(1, sizeof(DHT));
2391 2714
2392 if (dht == NULL) 2715 if (dht == nullptr) {
2393 return NULL; 2716 return nullptr;
2717 }
2394 2718
2719 dht->mono_time = mono_time;
2720 dht->log = log;
2395 dht->net = net; 2721 dht->net = net;
2396 dht->ping = new_ping(dht);
2397 2722
2398 if (dht->ping == NULL) { 2723 dht->hole_punching_enabled = holepunching_enabled;
2399 kill_DHT(dht); 2724
2400 return NULL; 2725 dht->ping = ping_new(mono_time, dht);
2726
2727 if (dht->ping == nullptr) {
2728 kill_dht(dht);
2729 return nullptr;
2401 } 2730 }
2402 2731
2403 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); 2732 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
@@ -2406,74 +2735,63 @@ DHT *new_DHT(Networking_Core *net)
2406 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); 2735 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
2407 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); 2736 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht);
2408 2737
2409 new_symmetric_key(dht->secret_symmetric_key); 2738 crypto_new_keypair(dht->self_public_key, dht->self_secret_key);
2410 crypto_box_keypair(dht->self_public_key, dht->self_secret_key);
2411 2739
2412 ping_array_init(&dht->dht_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT); 2740 dht->dht_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
2413 ping_array_init(&dht->dht_harden_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT); 2741 dht->dht_harden_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
2414#ifdef ENABLE_ASSOC_DHT 2742
2415 dht->assoc = new_Assoc_default(dht->self_public_key); 2743 for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
2416#endif 2744 uint8_t random_public_key_bytes[CRYPTO_PUBLIC_KEY_SIZE];
2417 uint32_t i; 2745 uint8_t random_secret_key_bytes[CRYPTO_SECRET_KEY_SIZE];
2418 2746
2419 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { 2747 crypto_new_keypair(random_public_key_bytes, random_secret_key_bytes);
2420 uint8_t random_key_bytes[crypto_box_PUBLICKEYBYTES];
2421 randombytes(random_key_bytes, sizeof(random_key_bytes));
2422 2748
2423 if (DHT_addfriend(dht, random_key_bytes, 0, 0, 0, 0) != 0) { 2749 if (dht_addfriend(dht, random_public_key_bytes, nullptr, nullptr, 0, nullptr) != 0) {
2424 kill_DHT(dht); 2750 kill_dht(dht);
2425 return NULL; 2751 return nullptr;
2426 } 2752 }
2427 } 2753 }
2428 2754
2429 return dht; 2755 return dht;
2430} 2756}
2431 2757
2432void do_DHT(DHT *dht) 2758void do_dht(DHT *dht)
2433{ 2759{
2434 unix_time_update(); 2760 if (dht->last_run == mono_time_get(dht->mono_time)) {
2435
2436 if (dht->last_run == unix_time()) {
2437 return; 2761 return;
2438 } 2762 }
2439 2763
2440 // Load friends/clients if first call to do_DHT 2764 // Load friends/clients if first call to do_dht
2441 if (dht->loaded_num_nodes) { 2765 if (dht->loaded_num_nodes) {
2442 DHT_connect_after_load(dht); 2766 dht_connect_after_load(dht);
2443 } 2767 }
2444 2768
2445 do_Close(dht); 2769 do_Close(dht);
2446 do_DHT_friends(dht); 2770 do_dht_friends(dht);
2447 do_NAT(dht); 2771 do_NAT(dht);
2448 do_to_ping(dht->ping); 2772 ping_iterate(dht->ping);
2449 //do_hardening(dht); 2773#if DHT_HARDENING
2450#ifdef ENABLE_ASSOC_DHT 2774 do_hardening(dht);
2451
2452 if (dht->assoc)
2453 do_Assoc(dht->assoc, dht);
2454
2455#endif 2775#endif
2456 dht->last_run = unix_time(); 2776 dht->last_run = mono_time_get(dht->mono_time);
2457} 2777}
2458void kill_DHT(DHT *dht) 2778
2779void kill_dht(DHT *dht)
2459{ 2780{
2460#ifdef ENABLE_ASSOC_DHT 2781 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, nullptr, nullptr);
2461 kill_Assoc(dht->assoc); 2782 networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, nullptr, nullptr);
2462#endif 2783 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, nullptr, nullptr);
2463 networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL); 2784 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, nullptr, nullptr);
2464 networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL); 2785 ping_array_kill(dht->dht_ping_array);
2465 cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL); 2786 ping_array_kill(dht->dht_harden_ping_array);
2466 cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL); 2787 ping_kill(dht->ping);
2467 ping_array_free_all(&dht->dht_ping_array);
2468 ping_array_free_all(&dht->dht_harden_ping_array);
2469 kill_ping(dht->ping);
2470 free(dht->friends_list); 2788 free(dht->friends_list);
2471 free(dht->loaded_nodes_list); 2789 free(dht->loaded_nodes_list);
2472 free(dht); 2790 free(dht);
2473} 2791}
2474 2792
2475/* new DHT format for load/save, more robust and forward compatible */ 2793/* new DHT format for load/save, more robust and forward compatible */
2476//TODO: Move this closer to Messenger. 2794// TODO(irungentoo): Move this closer to Messenger.
2477#define DHT_STATE_COOKIE_GLOBAL 0x159000d 2795#define DHT_STATE_COOKIE_GLOBAL 0x159000d
2478 2796
2479#define DHT_STATE_COOKIE_TYPE 0x11ce 2797#define DHT_STATE_COOKIE_TYPE 0x11ce
@@ -2482,156 +2800,155 @@ void kill_DHT(DHT *dht)
2482#define MAX_SAVED_DHT_NODES (((DHT_FAKE_FRIEND_NUMBER * MAX_FRIEND_CLIENTS) + LCLIENT_LIST) * 2) 2800#define MAX_SAVED_DHT_NODES (((DHT_FAKE_FRIEND_NUMBER * MAX_FRIEND_CLIENTS) + LCLIENT_LIST) * 2)
2483 2801
2484/* Get the size of the DHT (for saving). */ 2802/* Get the size of the DHT (for saving). */
2485uint32_t DHT_size(const DHT *dht) 2803uint32_t dht_size(const DHT *dht)
2486{ 2804{
2487 uint32_t numv4 = 0, numv6 = 0, i, j; 2805 uint32_t numv4 = 0;
2806 uint32_t numv6 = 0;
2807
2808 for (uint32_t i = 0; i < dht->loaded_num_nodes; ++i) {
2809 numv4 += net_family_is_ipv4(dht->loaded_nodes_list[i].ip_port.ip.family);
2810 numv6 += net_family_is_ipv6(dht->loaded_nodes_list[i].ip_port.ip.family);
2811 }
2488 2812
2489 for (i = 0; i < LCLIENT_LIST; ++i) { 2813 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2490 numv4 += (dht->close_clientlist[i].assoc4.timestamp != 0); 2814 numv4 += (dht->close_clientlist[i].assoc4.timestamp != 0);
2491 numv6 += (dht->close_clientlist[i].assoc6.timestamp != 0); 2815 numv6 += (dht->close_clientlist[i].assoc6.timestamp != 0);
2492 } 2816 }
2493 2817
2494 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) { 2818 for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2495 DHT_Friend *fr = &dht->friends_list[i]; 2819 const DHT_Friend *const fr = &dht->friends_list[i];
2496 2820
2497 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 2821 for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2498 numv4 += (fr->client_list[j].assoc4.timestamp != 0); 2822 numv4 += (fr->client_list[j].assoc4.timestamp != 0);
2499 numv6 += (fr->client_list[j].assoc6.timestamp != 0); 2823 numv6 += (fr->client_list[j].assoc6.timestamp != 0);
2500 } 2824 }
2501 } 2825 }
2502 2826
2503 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; 2827 const uint32_t size32 = sizeof(uint32_t);
2828 const uint32_t sizesubhead = size32 * 2;
2504 2829
2505 return size32 + sizesubhead + (packed_node_size(AF_INET) * numv4) + (packed_node_size(AF_INET6) * numv6); 2830 return size32 + sizesubhead + packed_node_size(net_family_ipv4) * numv4 + packed_node_size(net_family_ipv6) * numv6;
2506} 2831}
2507 2832
2508static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type) 2833/* Save the DHT in data where data is an array of size dht_size(). */
2834void dht_save(const DHT *dht, uint8_t *data)
2509{ 2835{
2510 host_to_lendian32(data, len); 2836 host_to_lendian_bytes32(data, DHT_STATE_COOKIE_GLOBAL);
2511 data += sizeof(uint32_t);
2512 host_to_lendian32(data, (host_tolendian16(DHT_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type));
2513 data += sizeof(uint32_t); 2837 data += sizeof(uint32_t);
2514 return data;
2515}
2516
2517
2518/* Save the DHT in data where data is an array of size DHT_size(). */
2519void DHT_save(DHT *dht, uint8_t *data)
2520{
2521 host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL);
2522 data += sizeof(uint32_t);
2523
2524 uint32_t num, i, j;
2525 2838
2526 uint8_t *old_data = data; 2839 uint8_t *const old_data = data;
2527 2840
2528 /* get right offset. we write the actual header later. */ 2841 /* get right offset. we write the actual header later. */
2529 data = z_state_save_subheader(data, 0, 0); 2842 data = state_write_section_header(data, DHT_STATE_COOKIE_TYPE, 0, 0);
2530 2843
2531 Node_format clients[MAX_SAVED_DHT_NODES]; 2844 Node_format clients[MAX_SAVED_DHT_NODES];
2532 2845
2533 for (num = 0, i = 0; i < LCLIENT_LIST; ++i) { 2846 uint32_t num = 0;
2847
2848 if (dht->loaded_num_nodes > 0) {
2849 memcpy(clients, dht->loaded_nodes_list, sizeof(Node_format) * dht->loaded_num_nodes);
2850 num += dht->loaded_num_nodes;
2851 }
2852
2853 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2534 if (dht->close_clientlist[i].assoc4.timestamp != 0) { 2854 if (dht->close_clientlist[i].assoc4.timestamp != 0) {
2535 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, crypto_box_PUBLICKEYBYTES); 2855 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2536 clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port; 2856 clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port;
2537 ++num; 2857 ++num;
2538 } 2858 }
2539 2859
2540 if (dht->close_clientlist[i].assoc6.timestamp != 0) { 2860 if (dht->close_clientlist[i].assoc6.timestamp != 0) {
2541 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, crypto_box_PUBLICKEYBYTES); 2861 memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2542 clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port; 2862 clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port;
2543 ++num; 2863 ++num;
2544 } 2864 }
2545 } 2865 }
2546 2866
2547 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) { 2867 for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2548 DHT_Friend *fr = &dht->friends_list[i]; 2868 const DHT_Friend *const fr = &dht->friends_list[i];
2549 2869
2550 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 2870 for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2551 if (fr->client_list[j].assoc4.timestamp != 0) { 2871 if (fr->client_list[j].assoc4.timestamp != 0) {
2552 memcpy(clients[num].public_key, fr->client_list[j].public_key, crypto_box_PUBLICKEYBYTES); 2872 memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2553 clients[num].ip_port = fr->client_list[j].assoc4.ip_port; 2873 clients[num].ip_port = fr->client_list[j].assoc4.ip_port;
2554 ++num; 2874 ++num;
2555 } 2875 }
2556 2876
2557 if (fr->client_list[j].assoc6.timestamp != 0) { 2877 if (fr->client_list[j].assoc6.timestamp != 0) {
2558 memcpy(clients[num].public_key, fr->client_list[j].public_key, crypto_box_PUBLICKEYBYTES); 2878 memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2559 clients[num].ip_port = fr->client_list[j].assoc6.ip_port; 2879 clients[num].ip_port = fr->client_list[j].assoc6.ip_port;
2560 ++num; 2880 ++num;
2561 } 2881 }
2562 } 2882 }
2563 } 2883 }
2564 2884
2565 z_state_save_subheader(old_data, pack_nodes(data, sizeof(Node_format) * num, clients, num), DHT_STATE_TYPE_NODES); 2885 state_write_section_header(old_data, DHT_STATE_COOKIE_TYPE, pack_nodes(data, sizeof(Node_format) * num, clients, num),
2886 DHT_STATE_TYPE_NODES);
2566} 2887}
2567 2888
2568/* Bootstrap from this number of nodes every time DHT_connect_after_load() is called */ 2889/* Bootstrap from this number of nodes every time dht_connect_after_load() is called */
2569#define SAVE_BOOTSTAP_FREQUENCY 8 2890#define SAVE_BOOTSTAP_FREQUENCY 8
2570 2891
2571/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */ 2892/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */
2572int DHT_connect_after_load(DHT *dht) 2893int dht_connect_after_load(DHT *dht)
2573{ 2894{
2574 if (dht == NULL) 2895 if (dht == nullptr) {
2575 return -1; 2896 return -1;
2897 }
2576 2898
2577 if (!dht->loaded_nodes_list) 2899 if (!dht->loaded_nodes_list) {
2578 return -1; 2900 return -1;
2901 }
2579 2902
2580 /* DHT is connected, stop. */ 2903 /* DHT is connected, stop. */
2581 if (DHT_non_lan_connected(dht)) { 2904 if (dht_non_lan_connected(dht)) {
2582 free(dht->loaded_nodes_list); 2905 free(dht->loaded_nodes_list);
2583 dht->loaded_nodes_list = NULL; 2906 dht->loaded_nodes_list = nullptr;
2584 dht->loaded_num_nodes = 0; 2907 dht->loaded_num_nodes = 0;
2585 return 0; 2908 return 0;
2586 } 2909 }
2587 2910
2588 unsigned int i; 2911 for (uint32_t i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
2589 2912 const unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
2590 for (i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) { 2913 dht_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
2591 unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
2592 DHT_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
2593 ++dht->loaded_nodes_index; 2914 ++dht->loaded_nodes_index;
2594 } 2915 }
2595 2916
2596 return 0; 2917 return 0;
2597} 2918}
2598 2919
2599static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type) 2920static State_Load_Status dht_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
2600{ 2921{
2601 DHT *dht = outer; 2922 DHT *dht = (DHT *)outer;
2602 2923
2603 switch (type) { 2924 switch (type) {
2604 case DHT_STATE_TYPE_NODES: 2925 case DHT_STATE_TYPE_NODES: {
2605 if (length == 0) 2926 if (length == 0) {
2606 break; 2927 break;
2928 }
2607 2929
2608 { 2930 free(dht->loaded_nodes_list);
2609 free(dht->loaded_nodes_list); 2931 // Copy to loaded_clients_list
2610 // Copy to loaded_clients_list 2932 dht->loaded_nodes_list = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
2611 dht->loaded_nodes_list = calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
2612
2613 int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, NULL, data, length, 0);
2614 2933
2615 if (num > 0) { 2934 const int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, nullptr, data, length, 0);
2616 dht->loaded_num_nodes = num;
2617 } else {
2618 dht->loaded_num_nodes = 0;
2619 }
2620 2935
2621 } /* localize declarations */ 2936 if (num > 0) {
2937 dht->loaded_num_nodes = num;
2938 } else {
2939 dht->loaded_num_nodes = 0;
2940 }
2622 2941
2623 break; 2942 break;
2624 2943 }
2625#ifdef DEBUG
2626 2944
2627 default: 2945 default:
2628 fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n", 2946 LOGGER_ERROR(dht->log, "Load state (DHT): contains unrecognized part (len %u, type %u)\n",
2629 length, type); 2947 length, type);
2630 break; 2948 break;
2631#endif
2632 } 2949 }
2633 2950
2634 return 0; 2951 return STATE_LOAD_STATUS_CONTINUE;
2635} 2952}
2636 2953
2637/* Load the DHT from data of size size. 2954/* Load the DHT from data of size size.
@@ -2639,59 +2956,58 @@ static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t le
2639 * return -1 if failure. 2956 * return -1 if failure.
2640 * return 0 if success. 2957 * return 0 if success.
2641 */ 2958 */
2642int DHT_load(DHT *dht, const uint8_t *data, uint32_t length) 2959int dht_load(DHT *dht, const uint8_t *data, uint32_t length)
2643{ 2960{
2644 uint32_t cookie_len = sizeof(uint32_t); 2961 const uint32_t cookie_len = sizeof(uint32_t);
2645 2962
2646 if (length > cookie_len) { 2963 if (length > cookie_len) {
2647 uint32_t data32; 2964 uint32_t data32;
2648 lendian_to_host32(&data32, data); 2965 lendian_bytes_to_host32(&data32, data);
2649 2966
2650 if (data32 == DHT_STATE_COOKIE_GLOBAL) 2967 if (data32 == DHT_STATE_COOKIE_GLOBAL) {
2651 return load_state(dht_load_state_callback, dht, data + cookie_len, 2968 return state_load(dht->log, dht_load_state_callback, dht, data + cookie_len,
2652 length - cookie_len, DHT_STATE_COOKIE_TYPE); 2969 length - cookie_len, DHT_STATE_COOKIE_TYPE);
2970 }
2653 } 2971 }
2654 2972
2655 return -1; 2973 return -1;
2656} 2974}
2657 2975
2658/* return 0 if we are not connected to the DHT. 2976/* return false if we are not connected to the DHT.
2659 * return 1 if we are. 2977 * return true if we are.
2660 */ 2978 */
2661int DHT_isconnected(const DHT *dht) 2979bool dht_isconnected(const DHT *dht)
2662{ 2980{
2663 uint32_t i; 2981 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2664 unix_time_update(); 2982 const Client_data *const client = &dht->close_clientlist[i];
2665 2983
2666 for (i = 0; i < LCLIENT_LIST; ++i) { 2984 if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
2667 const Client_data *client = &dht->close_clientlist[i]; 2985 !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
2668 2986 return true;
2669 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || 2987 }
2670 !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT))
2671 return 1;
2672 } 2988 }
2673 2989
2674 return 0; 2990 return false;
2675} 2991}
2676 2992
2677/* return 0 if we are not connected or only connected to lan peers with the DHT. 2993/* return false if we are not connected or only connected to lan peers with the DHT.
2678 * return 1 if we are. 2994 * return true if we are.
2679 */ 2995 */
2680int DHT_non_lan_connected(const DHT *dht) 2996bool dht_non_lan_connected(const DHT *dht)
2681{ 2997{
2682 uint32_t i; 2998 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2683 unix_time_update(); 2999 const Client_data *const client = &dht->close_clientlist[i];
2684
2685 for (i = 0; i < LCLIENT_LIST; ++i) {
2686 const Client_data *client = &dht->close_clientlist[i];
2687
2688 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc4.ip_port.ip) == -1)
2689 return 1;
2690 3000
2691 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc6.ip_port.ip) == -1) 3001 if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)
2692 return 1; 3002 && !ip_is_lan(client->assoc4.ip_port.ip)) {
3003 return true;
3004 }
2693 3005
3006 if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)
3007 && !ip_is_lan(client->assoc6.ip_port.ip)) {
3008 return true;
3009 }
2694 } 3010 }
2695 3011
2696 return 0; 3012 return false;
2697} 3013}