Coverage Report

Created: 2023-11-22 10:24

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