Coverage Report

Created: 2024-01-26 01:52

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