Coverage Report

Created: 2024-01-26 01:52

/work/toxcore/network.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2023 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 */
5
6
/**
7
 * Functions for the core networking.
8
 */
9
10
#ifdef __APPLE__
11
#define _DARWIN_C_SOURCE
12
#endif /* __APPLE__ */
13
14
// For Solaris.
15
#ifdef __sun
16
#define __EXTENSIONS__ 1
17
#endif /* __sun */
18
19
// For Linux (and some BSDs).
20
#ifndef _XOPEN_SOURCE
21
#define _XOPEN_SOURCE 700
22
#endif /* _XOPEN_SOURCE */
23
24
#if defined(_WIN32) && defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
25
#undef _WIN32_WINNT
26
#define _WIN32_WINNT  0x501
27
#endif /* defined(_WIN32) && defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WINXP */
28
29
#if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
30
#define OS_WIN32
31
#endif /* !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) */
32
33
#if defined(OS_WIN32) && !defined(WINVER)
34
// Windows XP
35
#define WINVER 0x0501
36
#endif /* defined(OS_WIN32) && !defined(WINVER) */
37
38
#include "network.h"
39
40
#ifdef OS_WIN32 // Put win32 includes here
41
// The mingw32/64 Windows library warns about including winsock2.h after
42
// windows.h even though with the above it's a valid thing to do. So, to make
43
// mingw32 headers happy, we include winsock2.h first.
44
#include <winsock2.h>
45
// Comment line here to avoid reordering by source code formatters.
46
#include <windows.h>
47
#include <ws2tcpip.h>
48
#endif /* OS_WIN32 */
49
50
#ifdef __APPLE__
51
#include <mach/clock.h>
52
#include <mach/mach.h>
53
#endif /* __APPLE__ */
54
55
#if !defined(OS_WIN32)
56
#include <arpa/inet.h>
57
#include <errno.h>
58
#include <fcntl.h>
59
#include <netdb.h>
60
#include <netinet/in.h>
61
#include <sys/ioctl.h>
62
#include <sys/socket.h>
63
#include <sys/time.h>
64
#include <sys/types.h>
65
#include <unistd.h>
66
67
#ifdef __sun
68
#include <stropts.h>
69
#include <sys/filio.h>
70
#endif /* __sun */
71
72
#else
73
#ifndef IPV6_V6ONLY
74
#define IPV6_V6ONLY 27
75
#endif /* IPV6_V6ONLY */
76
#endif /* !defined(OS_WIN32) */
77
78
#include <assert.h>
79
#include <limits.h>
80
#include <stdio.h>
81
#include <stdlib.h>
82
#include <string.h>
83
84
#include "ccompat.h"
85
#include "logger.h"
86
#include "mem.h"
87
#include "util.h"
88
89
// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
90
#if !defined(MSG_NOSIGNAL)
91
#define MSG_NOSIGNAL 0
92
#endif /* !defined(MSG_NOSIGNAL) */
93
94
#ifndef IPV6_ADD_MEMBERSHIP
95
#ifdef IPV6_JOIN_GROUP
96
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
97
#endif /* IPV6_JOIN_GROUP */
98
#endif /* IPV6_ADD_MEMBERSHIP */
99
100
static_assert(sizeof(IP4) == SIZE_IP4, "IP4 size must be 4");
101
102
// TODO(iphydf): Stop relying on this. We memcpy this struct (and IP4 above)
103
// into packets but really should be serialising it properly.
104
static_assert(sizeof(IP6) == SIZE_IP6, "IP6 size must be 16");
105
106
#if !defined(OS_WIN32)
107
108
static bool should_ignore_recv_error(int err)
109
157k
{
110
157k
    return err == EWOULDBLOCK;
111
157k
}
112
113
static bool should_ignore_connect_error(int err)
114
69
{
115
69
    return err == EWOULDBLOCK || err == EINPROGRESS;
116
69
}
117
118
non_null()
119
static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)
120
2.92M
{
121
2.92M
    return inet_ntop(AF_INET, addr, buf, bufsize);
122
2.92M
}
123
124
non_null()
125
static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t bufsize)
126
16.2k
{
127
16.2k
    return inet_ntop(AF_INET6, addr, buf, bufsize);
128
16.2k
}
129
130
non_null()
131
static int inet_pton4(const char *addr_string, struct in_addr *addrbuf)
132
29.4k
{
133
29.4k
    return inet_pton(AF_INET, addr_string, addrbuf);
134
29.4k
}
135
136
non_null()
137
static int inet_pton6(const char *addr_string, struct in6_addr *addrbuf)
138
693
{
139
693
    return inet_pton(AF_INET6, addr_string, addrbuf);
140
693
}
141
142
#else
143
#ifndef IPV6_V6ONLY
144
#define IPV6_V6ONLY 27
145
#endif /* IPV6_V6ONLY */
146
147
static bool should_ignore_recv_error(int err)
148
{
149
    // We ignore WSAECONNRESET as Windows helpfully* sends that error if a
150
    // previously sent UDP packet wasn't delivered.
151
    return err == WSAEWOULDBLOCK || err == WSAECONNRESET;
152
}
153
154
static bool should_ignore_connect_error(int err)
155
{
156
    return err == WSAEWOULDBLOCK || err == WSAEINPROGRESS;
157
}
158
159
non_null()
160
static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)
161
{
162
    struct sockaddr_in saddr = {0};
163
164
    saddr.sin_family = AF_INET;
165
    saddr.sin_addr = *addr;
166
167
    DWORD len = bufsize;
168
169
    if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {
170
        return nullptr;
171
    }
172
173
    return buf;
174
}
175
176
non_null()
177
static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t bufsize)
178
{
179
    struct sockaddr_in6 saddr = {0};
180
181
    saddr.sin6_family = AF_INET6;
182
    saddr.sin6_addr = *addr;
183
184
    DWORD len = bufsize;
185
186
    if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {
187
        return nullptr;
188
    }
189
190
    return buf;
191
}
192
193
non_null()
194
static int inet_pton4(const char *addrString, struct in_addr *addrbuf)
195
{
196
    struct sockaddr_in saddr = {0};
197
198
    INT len = sizeof(saddr);
199
200
    if (WSAStringToAddress((LPTSTR)addrString, AF_INET, nullptr, (LPSOCKADDR)&saddr, &len)) {
201
        return 0;
202
    }
203
204
    *addrbuf = saddr.sin_addr;
205
206
    return 1;
207
}
208
209
non_null()
210
static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
211
{
212
    struct sockaddr_in6 saddr = {0};
213
214
    INT len = sizeof(saddr);
215
216
    if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, nullptr, (LPSOCKADDR)&saddr, &len)) {
217
        return 0;
218
    }
219
220
    *addrbuf = saddr.sin6_addr;
221
222
    return 1;
223
}
224
225
#endif /* !defined(OS_WIN32) */
226
227
static_assert(TOX_INET6_ADDRSTRLEN >= INET6_ADDRSTRLEN,
228
              "TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)");
229
static_assert(TOX_INET_ADDRSTRLEN >= INET_ADDRSTRLEN,
230
              "TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)");
231
232
static int make_proto(int proto)
233
4.50k
{
234
4.50k
    switch (proto) {
235
478
        case TOX_PROTO_TCP:
236
478
            return IPPROTO_TCP;
237
238
3.99k
        case TOX_PROTO_UDP:
239
3.99k
            return IPPROTO_UDP;
240
241
34
        default:
242
34
            return proto;
243
4.50k
    }
244
4.50k
}
245
246
static int make_socktype(int type)
247
5.10k
{
248
5.10k
    switch (type) {
249
512
        case TOX_SOCK_STREAM:
250
512
            return SOCK_STREAM;
251
252
4.59k
        case TOX_SOCK_DGRAM:
253
4.59k
            return SOCK_DGRAM;
254
255
0
        default:
256
0
            return type;
257
5.10k
    }
258
5.10k
}
259
260
static int make_family(Family tox_family)
261
2.94M
{
262
2.94M
    switch (tox_family.value) {
263
2.92M
        case TOX_AF_INET:
264
2.92M
            return AF_INET;
265
266
18.0k
        case TOX_AF_INET6:
267
18.0k
            return AF_INET6;
268
269
3
        case TOX_AF_UNSPEC:
270
3
            return AF_UNSPEC;
271
272
0
        default:
273
0
            return tox_family.value;
274
2.94M
    }
275
2.94M
}
276
277
static const Family family_unspec = {TOX_AF_UNSPEC};
278
static const Family family_ipv4 = {TOX_AF_INET};
279
static const Family family_ipv6 = {TOX_AF_INET6};
280
static const Family family_tcp_server = {TCP_SERVER_FAMILY};
281
static const Family family_tcp_client = {TCP_CLIENT_FAMILY};
282
static const Family family_tcp_ipv4 = {TCP_INET};
283
static const Family family_tcp_ipv6 = {TCP_INET6};
284
static const Family family_tox_tcp_ipv4 = {TOX_TCP_INET};
285
static const Family family_tox_tcp_ipv6 = {TOX_TCP_INET6};
286
287
static const Family *make_tox_family(int family)
288
985k
{
289
985k
    switch (family) {
290
985k
        case AF_INET:
291
985k
            return &family_ipv4;
292
293
0
        case AF_INET6:
294
0
            return &family_ipv6;
295
296
0
        case AF_UNSPEC:
297
0
            return &family_unspec;
298
299
0
        default:
300
0
            return nullptr;
301
985k
    }
302
985k
}
303
304
non_null()
305
static void get_ip4(IP4 *result, const struct in_addr *addr)
306
1.01M
{
307
1.01M
    static_assert(sizeof(result->uint32) == sizeof(addr->s_addr),
308
1.01M
                  "Tox and operating system don't agree on size of IPv4 addresses");
309
1.01M
    result->uint32 = addr->s_addr;
310
1.01M
}
311
312
non_null()
313
static void get_ip6(IP6 *result, const struct in6_addr *addr)
314
6
{
315
6
    static_assert(sizeof(result->uint8) == sizeof(addr->s6_addr),
316
6
                  "Tox and operating system don't agree on size of IPv6 addresses");
317
6
    memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8));
318
6
}
319
320
non_null()
321
static void fill_addr4(const IP4 *ip, struct in_addr *addr)
322
4.95M
{
323
4.95M
    addr->s_addr = ip->uint32;
324
4.95M
}
325
326
non_null()
327
static void fill_addr6(const IP6 *ip, struct in6_addr *addr)
328
33.3k
{
329
33.3k
    memcpy(addr->s6_addr, ip->uint8, sizeof(ip->uint8));
330
33.3k
}
331
332
#if !defined(INADDR_LOOPBACK)
333
#define INADDR_LOOPBACK 0x7f000001
334
#endif /* !defined(INADDR_LOOPBACK) */
335
336
static const IP empty_ip = {{0}};
337
338
IP4 get_ip4_broadcast(void)
339
295
{
340
295
    const IP4 ip4_broadcast = { INADDR_BROADCAST };
341
295
    return ip4_broadcast;
342
295
}
343
344
IP6 get_ip6_broadcast(void)
345
7.24k
{
346
7.24k
    const IP6 ip6_broadcast = {
347
7.24k
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
348
7.24k
    };
349
7.24k
    return ip6_broadcast;
350
7.24k
}
351
352
IP4 get_ip4_loopback(void)
353
113
{
354
113
    IP4 loopback;
355
113
    loopback.uint32 = htonl(INADDR_LOOPBACK);
356
113
    return loopback;
357
113
}
358
359
IP6 get_ip6_loopback(void)
360
3
{
361
    /* in6addr_loopback isn't available everywhere, so we do it ourselves. */
362
3
    IP6 loopback = empty_ip.ip.v6;
363
3
    loopback.uint8[15] = 1;
364
3
    return loopback;
365
3
}
366
367
#ifndef OS_WIN32
368
9.91k
#define INVALID_SOCKET (-1)
369
#endif /* OS_WIN32 */
370
371
Socket net_invalid_socket(void)
372
9.91k
{
373
9.91k
    const Socket invalid_socket = { (int)INVALID_SOCKET };
374
9.91k
    return invalid_socket;
375
9.91k
}
376
377
Family net_family_unspec(void)
378
257k
{
379
257k
    return family_unspec;
380
257k
}
381
382
Family net_family_ipv4(void)
383
535k
{
384
535k
    return family_ipv4;
385
535k
}
386
387
Family net_family_ipv6(void)
388
35.5k
{
389
35.5k
    return family_ipv6;
390
35.5k
}
391
392
Family net_family_tcp_server(void)
393
1.37k
{
394
1.37k
    return family_tcp_server;
395
1.37k
}
396
397
Family net_family_tcp_client(void)
398
1.00k
{
399
1.00k
    return family_tcp_client;
400
1.00k
}
401
402
Family net_family_tcp_ipv4(void)
403
1.13k
{
404
1.13k
    return family_tcp_ipv4;
405
1.13k
}
406
407
Family net_family_tcp_ipv6(void)
408
6.15k
{
409
6.15k
    return family_tcp_ipv6;
410
6.15k
}
411
412
Family net_family_tox_tcp_ipv4(void)
413
0
{
414
0
    return family_tox_tcp_ipv4;
415
0
}
416
417
Family net_family_tox_tcp_ipv6(void)
418
0
{
419
0
    return family_tox_tcp_ipv6;
420
0
}
421
422
bool net_family_is_unspec(Family family)
423
9.99M
{
424
9.99M
    return family.value == family_unspec.value;
425
9.99M
}
426
427
bool net_family_is_ipv4(Family family)
428
134M
{
429
134M
    return family.value == family_ipv4.value;
430
134M
}
431
432
bool net_family_is_ipv6(Family family)
433
119M
{
434
119M
    return family.value == family_ipv6.value;
435
119M
}
436
437
bool net_family_is_tcp_server(Family family)
438
1.07k
{
439
1.07k
    return family.value == family_tcp_server.value;
440
1.07k
}
441
442
bool net_family_is_tcp_client(Family family)
443
808
{
444
808
    return family.value == family_tcp_client.value;
445
808
}
446
447
bool net_family_is_tcp_ipv4(Family family)
448
18.6k
{
449
18.6k
    return family.value == family_tcp_ipv4.value;
450
18.6k
}
451
452
bool net_family_is_tcp_ipv6(Family family)
453
13.3k
{
454
13.3k
    return family.value == family_tcp_ipv6.value;
455
13.3k
}
456
457
bool net_family_is_tox_tcp_ipv4(Family family)
458
1.85k
{
459
1.85k
    return family.value == family_tox_tcp_ipv4.value;
460
1.85k
}
461
462
bool net_family_is_tox_tcp_ipv6(Family family)
463
0
{
464
0
    return family.value == family_tox_tcp_ipv6.value;
465
0
}
466
467
bool sock_valid(Socket sock)
468
9.91k
{
469
9.91k
    const Socket invalid_socket = net_invalid_socket();
470
9.91k
    return sock.sock != invalid_socket.sock;
471
9.91k
}
472
473
struct Network_Addr {
474
    struct sockaddr_storage addr;
475
    size_t size;
476
};
477
478
non_null()
479
static int sys_close(void *obj, int sock)
480
1.26k
{
481
#if defined(OS_WIN32)
482
    return closesocket(sock);
483
#else  // !OS_WIN32
484
1.26k
    return close(sock);
485
1.26k
#endif /* OS_WIN32 */
486
1.26k
}
487
488
non_null()
489
static int sys_accept(void *obj, int sock)
490
2.56k
{
491
2.56k
    return accept(sock, nullptr, nullptr);
492
2.56k
}
493
494
non_null()
495
static int sys_bind(void *obj, int sock, const Network_Addr *addr)
496
63.6k
{
497
63.6k
    return bind(sock, (const struct sockaddr *)&addr->addr, addr->size);
498
63.6k
}
499
500
non_null()
501
static int sys_listen(void *obj, int sock, int backlog)
502
19
{
503
19
    return listen(sock, backlog);
504
19
}
505
506
non_null()
507
static int sys_recvbuf(void *obj, int sock)
508
37.7k
{
509
#ifdef OS_WIN32
510
    u_long count = 0;
511
    ioctlsocket(sock, FIONREAD, &count);
512
#else
513
37.7k
    int count = 0;
514
37.7k
    ioctl(sock, FIONREAD, &count);
515
37.7k
#endif /* OS_WIN32 */
516
517
37.7k
    return count;
518
37.7k
}
519
520
non_null()
521
static int sys_recv(void *obj, int sock, uint8_t *buf, size_t len)
522
9.00k
{
523
9.00k
    return recv(sock, (char *)buf, len, MSG_NOSIGNAL);
524
9.00k
}
525
526
non_null()
527
static int sys_send(void *obj, int sock, const uint8_t *buf, size_t len)
528
5.51k
{
529
5.51k
    return send(sock, (const char *)buf, len, MSG_NOSIGNAL);
530
5.51k
}
531
532
non_null()
533
1.20M
static int sys_sendto(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) {
534
1.20M
    return sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size);
535
1.20M
}
536
537
non_null()
538
1.12M
static int sys_recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) {
539
1.12M
    socklen_t size = addr->size;
540
1.12M
    const int ret = recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size);
541
1.12M
    addr->size = size;
542
1.12M
    return ret;
543
1.12M
}
544
545
non_null()
546
static int sys_socket(void *obj, int domain, int type, int proto)
547
2.32k
{
548
2.32k
    return (int)socket(domain, type, proto);
549
2.32k
}
550
551
non_null()
552
static int sys_socket_nonblock(void *obj, int sock, bool nonblock)
553
2.33k
{
554
#ifdef OS_WIN32
555
    u_long mode = nonblock ? 1 : 0;
556
    return ioctlsocket(sock, FIONBIO, &mode);
557
#else
558
2.33k
    return fcntl(sock, F_SETFL, O_NONBLOCK, nonblock ? 1 : 0);
559
2.33k
#endif /* OS_WIN32 */
560
2.33k
}
561
562
non_null()
563
static int sys_getsockopt(void *obj, int sock, int level, int optname, void *optval, size_t *optlen)
564
5
{
565
5
    socklen_t len = *optlen;
566
5
    const int ret = getsockopt(sock, level, optname, (char *)optval, &len);
567
5
    *optlen = len;
568
5
    return ret;
569
5
}
570
571
non_null()
572
static int sys_setsockopt(void *obj, int sock, int level, int optname, const void *optval, size_t optlen)
573
6.57k
{
574
6.57k
    return setsockopt(sock, level, optname, (const char *)optval, optlen);
575
6.57k
}
576
577
static const Network_Funcs os_network_funcs = {
578
    sys_close,
579
    sys_accept,
580
    sys_bind,
581
    sys_listen,
582
    sys_recvbuf,
583
    sys_recv,
584
    sys_recvfrom,
585
    sys_send,
586
    sys_sendto,
587
    sys_socket,
588
    sys_socket_nonblock,
589
    sys_getsockopt,
590
    sys_setsockopt,
591
};
592
static const Network os_network_obj = {&os_network_funcs};
593
594
const Network *os_network(void)
595
4.31k
{
596
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
597
1.96k
    if ((true)) {
598
1.96k
        return nullptr;
599
1.96k
    }
600
0
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
601
#ifdef OS_WIN32
602
    WSADATA wsaData;
603
604
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
605
        return nullptr;
606
    }
607
#endif /* OS_WIN32 */
608
0
    return &os_network_obj;
609
4.31k
}
os_network
Line
Count
Source
595
1.96k
{
596
1.96k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
597
1.96k
    if ((true)) {
598
1.96k
        return nullptr;
599
1.96k
    }
600
0
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
601
#ifdef OS_WIN32
602
    WSADATA wsaData;
603
604
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
605
        return nullptr;
606
    }
607
#endif /* OS_WIN32 */
608
0
    return &os_network_obj;
609
1.96k
}
os_network
Line
Count
Source
595
2.34k
{
596
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
597
    if ((true)) {
598
        return nullptr;
599
    }
600
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
601
#ifdef OS_WIN32
602
    WSADATA wsaData;
603
604
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
605
        return nullptr;
606
    }
607
#endif /* OS_WIN32 */
608
2.34k
    return &os_network_obj;
609
2.34k
}
610
611
#if 0
612
/* TODO(iphydf): Call this from functions that use `os_network()`. */
613
void os_network_deinit(const Network *ns)
614
{
615
#ifdef OS_WIN32
616
    WSACleanup();
617
#endif /* OS_WIN32 */
618
}
619
#endif /* 0 */
620
621
non_null()
622
static int net_setsockopt(const Network *ns, Socket sock, int level, int optname, const void *optval, size_t optlen)
623
13.7k
{
624
13.7k
    return ns->funcs->setsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
625
13.7k
}
626
627
non_null()
628
static int net_getsockopt(const Network *ns, Socket sock, int level, int optname, void *optval, size_t *optlen)
629
1.79k
{
630
1.79k
    return ns->funcs->getsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
631
1.79k
}
632
633
non_null()
634
static uint32_t data_0(uint16_t buflen, const uint8_t *buffer)
635
2.22M
{
636
2.22M
    uint32_t data = 0;
637
638
2.22M
    if (buflen > 4) {
639
2.21M
        net_unpack_u32(buffer + 1, &data);
640
2.21M
    }
641
642
2.22M
    return data;
643
2.22M
}
644
non_null()
645
static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)
646
2.22M
{
647
2.22M
    uint32_t data = 0;
648
649
2.22M
    if (buflen > 8) {
650
2.21M
        net_unpack_u32(buffer + 5, &data);
651
2.21M
    }
652
653
2.22M
    return data;
654
2.22M
}
655
656
static const char *net_packet_type_name(Net_Packet_Type type)
657
2.22M
{
658
2.22M
    switch (type) {
659
20.9k
        case NET_PACKET_PING_REQUEST:
660
20.9k
            return "PING_REQUEST";
661
662
12.8k
        case NET_PACKET_PING_RESPONSE:
663
12.8k
            return "PING_RESPONSE";
664
665
184k
        case NET_PACKET_GET_NODES:
666
184k
            return "GET_NODES";
667
668
161k
        case NET_PACKET_SEND_NODES_IPV6:
669
161k
            return "SEND_NODES_IPV6";
670
671
4.25k
        case NET_PACKET_COOKIE_REQUEST:
672
4.25k
            return "COOKIE_REQUEST";
673
674
3.52k
        case NET_PACKET_COOKIE_RESPONSE:
675
3.52k
            return "COOKIE_RESPONSE";
676
677
3.78k
        case NET_PACKET_CRYPTO_HS:
678
3.78k
            return "CRYPTO_HS";
679
680
618k
        case NET_PACKET_CRYPTO_DATA:
681
618k
            return "CRYPTO_DATA";
682
683
11.7k
        case NET_PACKET_CRYPTO:
684
11.7k
            return "CRYPTO";
685
686
1.09k
        case NET_PACKET_GC_HANDSHAKE:
687
1.09k
            return "GC_HANDSHAKE";
688
689
28.0k
        case NET_PACKET_GC_LOSSLESS:
690
28.0k
            return "GC_LOSSLESS";
691
692
27.1k
        case NET_PACKET_GC_LOSSY:
693
27.1k
            return "GC_LOSSY";
694
695
18.8k
        case NET_PACKET_LAN_DISCOVERY:
696
18.8k
            return "LAN_DISCOVERY";
697
698
149k
        case NET_PACKET_ONION_SEND_INITIAL:
699
149k
            return "ONION_SEND_INITIAL";
700
701
144k
        case NET_PACKET_ONION_SEND_1:
702
144k
            return "ONION_SEND_1";
703
704
139k
        case NET_PACKET_ONION_SEND_2:
705
139k
            return "ONION_SEND_2";
706
707
124k
        case NET_PACKET_ANNOUNCE_REQUEST_OLD:
708
124k
            return "ANNOUNCE_REQUEST_OLD";
709
710
119k
        case NET_PACKET_ANNOUNCE_RESPONSE_OLD:
711
119k
            return "ANNOUNCE_RESPONSE_OLD";
712
713
8.48k
        case NET_PACKET_ONION_DATA_REQUEST:
714
8.48k
            return "ONION_DATA_REQUEST";
715
716
8.10k
        case NET_PACKET_ONION_DATA_RESPONSE:
717
8.10k
            return "ONION_DATA_RESPONSE";
718
719
3.28k
        case NET_PACKET_ANNOUNCE_REQUEST:
720
3.28k
            return "ANNOUNCE_REQUEST";
721
722
3.27k
        case NET_PACKET_ANNOUNCE_RESPONSE:
723
3.27k
            return "ANNOUNCE_RESPONSE";
724
725
133k
        case NET_PACKET_ONION_RECV_3:
726
133k
            return "ONION_RECV_3";
727
728
132k
        case NET_PACKET_ONION_RECV_2:
729
132k
            return "ONION_RECV_2";
730
731
132k
        case NET_PACKET_ONION_RECV_1:
732
132k
            return "ONION_RECV_1";
733
734
288
        case NET_PACKET_FORWARD_REQUEST:
735
288
            return "FORWARD_REQUEST";
736
737
1.36k
        case NET_PACKET_FORWARDING:
738
1.36k
            return "FORWARDING";
739
740
188
        case NET_PACKET_FORWARD_REPLY:
741
188
            return "FORWARD_REPLY";
742
743
10.9k
        case NET_PACKET_DATA_SEARCH_REQUEST:
744
10.9k
            return "DATA_SEARCH_REQUEST";
745
746
8.09k
        case NET_PACKET_DATA_SEARCH_RESPONSE:
747
8.09k
            return "DATA_SEARCH_RESPONSE";
748
749
80
        case NET_PACKET_DATA_RETRIEVE_REQUEST:
750
80
            return "DATA_RETRIEVE_REQUEST";
751
752
20
        case NET_PACKET_DATA_RETRIEVE_RESPONSE:
753
20
            return "DATA_RETRIEVE_RESPONSE";
754
755
73
        case NET_PACKET_STORE_ANNOUNCE_REQUEST:
756
73
            return "STORE_ANNOUNCE_REQUEST";
757
758
19
        case NET_PACKET_STORE_ANNOUNCE_RESPONSE:
759
19
            return "STORE_ANNOUNCE_RESPONSE";
760
761
25
        case BOOTSTRAP_INFO_PACKET_ID:
762
25
            return "BOOTSTRAP_INFO";
763
764
361
        case NET_PACKET_MAX:
765
361
            return "MAX";
766
2.22M
    }
767
768
6.44k
    return "<unknown>";
769
2.22M
}
770
771
non_null()
772
static void loglogdata(const Logger *log, const char *message, const uint8_t *buffer,
773
                       uint16_t buflen, const IP_Port *ip_port, long res)
774
2.22M
{
775
2.22M
    if (res < 0) { /* Windows doesn't necessarily know `%zu` */
776
4.41k
        Ip_Ntoa ip_str;
777
4.41k
        const int error = net_error();
778
4.41k
        char *strerror = net_new_strerror(error);
779
4.41k
        LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
780
4.41k
                     buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
781
4.41k
                     min_u16(buflen, 999), 'E',
782
4.41k
                     net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error,
783
4.41k
                     strerror, data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
784
4.41k
        net_kill_strerror(strerror);
785
2.21M
    } else if ((res > 0) && ((size_t)res <= buflen)) {
786
2.21M
        Ip_Ntoa ip_str;
787
2.21M
        LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
788
2.21M
                     buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
789
2.21M
                     min_u16(res, 999), (size_t)res < buflen ? '<' : '=',
790
2.21M
                     net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
791
2.21M
                     data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
792
2.21M
    } else { /* empty or overwrite */
793
6.30k
        Ip_Ntoa ip_str;
794
6.30k
        LOGGER_TRACE(log, "[%02x = %-21s] %s %lu%c%u %s:%u (%u: %s) | %08x%08x...%02x",
795
6.30k
                     buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
796
6.30k
                     res, res == 0 ? '!' : '>', buflen,
797
6.30k
                     net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
798
6.30k
                     data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
799
6.30k
    }
800
2.22M
}
801
802
int net_send(const Network *ns, const Logger *log,
803
             Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port)
804
6.20k
{
805
6.20k
    const int res = ns->funcs->send(ns->obj, sock.sock, buf, len);
806
6.20k
    loglogdata(log, "T=>", buf, len, ip_port, res);
807
6.20k
    return res;
808
6.20k
}
809
810
non_null()
811
static int net_sendto(
812
        const Network *ns,
813
        Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr, const IP_Port *ip_port)
814
1.21M
{
815
1.21M
    return ns->funcs->sendto(ns->obj, sock.sock, buf, len, addr);
816
1.21M
}
817
818
int net_recv(const Network *ns, const Logger *log,
819
             Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port)
820
13.0k
{
821
13.0k
    const int res = ns->funcs->recv(ns->obj, sock.sock, buf, len);
822
13.0k
    loglogdata(log, "=>T", buf, len, ip_port, res);
823
13.0k
    return res;
824
13.0k
}
825
826
non_null()
827
static int net_recvfrom(const Network *ns,
828
                        Socket sock, uint8_t *buf, size_t len, Network_Addr *addr)
829
1.14M
{
830
1.14M
    return ns->funcs->recvfrom(ns->obj, sock.sock, buf, len, addr);
831
1.14M
}
832
833
int net_listen(const Network *ns, Socket sock, int backlog)
834
35
{
835
35
    return ns->funcs->listen(ns->obj, sock.sock, backlog);
836
35
}
837
838
non_null()
839
static int net_bind(const Network *ns, Socket sock, const Network_Addr *addr)
840
65.4k
{
841
65.4k
    return ns->funcs->bind(ns->obj, sock.sock, addr);
842
65.4k
}
843
844
Socket net_accept(const Network *ns, Socket sock)
845
5.38k
{
846
5.38k
    const Socket newsock = {ns->funcs->accept(ns->obj, sock.sock)};
847
5.38k
    return newsock;
848
5.38k
}
849
850
/** Close the socket. */
851
void kill_sock(const Network *ns, Socket sock)
852
3.69k
{
853
3.69k
    ns->funcs->close(ns->obj, sock.sock);
854
3.69k
}
855
856
bool set_socket_nonblock(const Network *ns, Socket sock)
857
7.33k
{
858
7.33k
    return ns->funcs->socket_nonblock(ns->obj, sock.sock, true) == 0;
859
7.33k
}
860
861
bool set_socket_nosigpipe(const Network *ns, Socket sock)
862
7.29k
{
863
#if defined(__APPLE__)
864
    int set = 1;
865
    return net_setsockopt(ns, sock, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(int)) == 0;
866
#else
867
7.29k
    return true;
868
7.29k
#endif /* __APPLE__ */
869
7.29k
}
870
871
bool set_socket_reuseaddr(const Network *ns, Socket sock)
872
35
{
873
35
    int set = 1;
874
35
    return net_setsockopt(ns, sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) == 0;
875
35
}
876
877
bool set_socket_dualstack(const Network *ns, Socket sock)
878
1.79k
{
879
1.79k
    int ipv6only = 0;
880
1.79k
    size_t optsize = sizeof(ipv6only);
881
1.79k
    const int res = net_getsockopt(ns, sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize);
882
883
1.79k
    if ((res == 0) && (ipv6only == 0)) {
884
1.79k
        return true;
885
1.79k
    }
886
887
0
    ipv6only = 0;
888
0
    return net_setsockopt(ns, sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0;
889
1.79k
}
890
891
892
typedef struct Packet_Handler {
893
    packet_handler_cb *function;
894
    void *object;
895
} Packet_Handler;
896
897
struct Networking_Core {
898
    const Logger *log;
899
    const Memory *mem;
900
    Packet_Handler packethandlers[256];
901
    const Network *ns;
902
903
    Family family;
904
    uint16_t port;
905
    /* Our UDP socket. */
906
    Socket sock;
907
};
908
909
Family net_family(const Networking_Core *net)
910
68.3k
{
911
68.3k
    return net->family;
912
68.3k
}
913
914
uint16_t net_port(const Networking_Core *net)
915
752
{
916
752
    return net->port;
917
752
}
918
919
/* Basic network functions:
920
 */
921
922
int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packet)
923
1.22M
{
924
1.22M
    IP_Port ipp_copy = *ip_port;
925
926
1.22M
    if (net_family_is_unspec(ip_port->ip.family)) {
927
        // TODO(iphydf): Make this an error. Currently this fails sometimes when
928
        // called from DHT.c:do_ping_and_sendnode_requests.
929
3.31k
        return -1;
930
3.31k
    }
931
932
1.21M
    if (net_family_is_unspec(net->family)) { /* Socket not initialized */
933
        // TODO(iphydf): Make this an error. Currently, the onion client calls
934
        // this via DHT getnodes.
935
4
        LOGGER_WARNING(net->log, "attempted to send message of length %u on uninitialised socket", packet.length);
936
4
        return -1;
937
4
    }
938
939
    /* socket TOX_AF_INET, but target IP NOT: can't send */
940
1.21M
    if (net_family_is_ipv4(net->family) && !net_family_is_ipv4(ipp_copy.ip.family)) {
941
        // TODO(iphydf): Make this an error. Occasionally we try to send to an
942
        // all-zero ip_port.
943
0
        Ip_Ntoa ip_str;
944
0
        LOGGER_WARNING(net->log, "attempted to send message with network family %d (probably IPv6) on IPv4 socket (%s)",
945
0
                       ipp_copy.ip.family.value, net_ip_ntoa(&ipp_copy.ip, &ip_str));
946
0
        return -1;
947
0
    }
948
949
1.21M
    if (net_family_is_ipv4(ipp_copy.ip.family) && net_family_is_ipv6(net->family)) {
950
        /* must convert to IPV4-in-IPV6 address */
951
777
        IP6 ip6;
952
953
        /* there should be a macro for this in a standards compliant
954
         * environment, not found */
955
777
        ip6.uint32[0] = 0;
956
777
        ip6.uint32[1] = 0;
957
777
        ip6.uint32[2] = net_htonl(0xFFFF);
958
777
        ip6.uint32[3] = ipp_copy.ip.ip.v4.uint32;
959
960
777
        ipp_copy.ip.family = net_family_ipv6();
961
777
        ipp_copy.ip.ip.v6 = ip6;
962
777
    }
963
964
1.21M
    Network_Addr addr;
965
966
1.21M
    if (net_family_is_ipv4(ipp_copy.ip.family)) {
967
1.20M
        struct sockaddr_in *const addr4 = (struct sockaddr_in *)&addr.addr;
968
969
1.20M
        addr.size = sizeof(struct sockaddr_in);
970
1.20M
        addr4->sin_family = AF_INET;
971
1.20M
        addr4->sin_port = ipp_copy.port;
972
1.20M
        fill_addr4(&ipp_copy.ip.ip.v4, &addr4->sin_addr);
973
1.20M
    } else if (net_family_is_ipv6(ipp_copy.ip.family)) {
974
15.2k
        struct sockaddr_in6 *const addr6 = (struct sockaddr_in6 *)&addr.addr;
975
976
15.2k
        addr.size = sizeof(struct sockaddr_in6);
977
15.2k
        addr6->sin6_family = AF_INET6;
978
15.2k
        addr6->sin6_port = ipp_copy.port;
979
15.2k
        fill_addr6(&ipp_copy.ip.ip.v6, &addr6->sin6_addr);
980
981
15.2k
        addr6->sin6_flowinfo = 0;
982
15.2k
        addr6->sin6_scope_id = 0;
983
15.2k
    } else {
984
10
        LOGGER_ERROR(net->log, "unknown address type: %d", ipp_copy.ip.family.value);
985
10
        return -1;
986
10
    }
987
988
1.21M
    const long res = net_sendto(net->ns, net->sock, packet.data, packet.length, &addr, &ipp_copy);
989
1.21M
    loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res);
990
991
1.21M
    assert(res <= INT_MAX);
992
1.21M
    return (int)res;
993
1.21M
}
994
995
/**
996
 * Function to send packet(data) of length length to ip_port.
997
 *
998
 * @deprecated Use send_packet instead.
999
 */
1000
int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t *data, uint16_t length)
1001
1.21M
{
1002
1.21M
    const Packet packet = {data, length};
1003
1.21M
    return send_packet(net, ip_port, packet);
1004
1.21M
}
1005
1006
/** @brief Function to receive data
1007
 * ip and port of sender is put into ip_port.
1008
 * Packet data is put into data.
1009
 * Packet length is put into length.
1010
 */
1011
non_null()
1012
static int receivepacket(const Network *ns, const Memory *mem, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
1013
1.14M
{
1014
1.14M
    memset(ip_port, 0, sizeof(IP_Port));
1015
1.14M
    Network_Addr addr = {{0}};
1016
1.14M
    addr.size = sizeof(addr.addr);
1017
1.14M
    *length = 0;
1018
1019
1.14M
    const int fail_or_len = net_recvfrom(ns, sock, data, MAX_UDP_PACKET_SIZE, &addr);
1020
1021
1.14M
    if (fail_or_len < 0) {
1022
157k
        const int error = net_error();
1023
1024
157k
        if (!should_ignore_recv_error(error)) {
1025
593
            char *strerror = net_new_strerror(error);
1026
593
            LOGGER_ERROR(log, "unexpected error reading from socket: %u, %s", error, strerror);
1027
593
            net_kill_strerror(strerror);
1028
593
        }
1029
1030
157k
        return -1; /* Nothing received. */
1031
157k
    }
1032
1033
984k
    *length = (uint32_t)fail_or_len;
1034
1035
984k
    if (addr.addr.ss_family == AF_INET) {
1036
984k
        const struct sockaddr_in *addr_in = (const struct sockaddr_in *)&addr.addr;
1037
1038
984k
        const Family *const family = make_tox_family(addr_in->sin_family);
1039
984k
        assert(family != nullptr);
1040
1041
984k
        if (family == nullptr) {
1042
0
            return -1;
1043
0
        }
1044
1045
984k
        ip_port->ip.family = *family;
1046
984k
        get_ip4(&ip_port->ip.ip.v4, &addr_in->sin_addr);
1047
984k
        ip_port->port = addr_in->sin_port;
1048
984k
    } else if (addr.addr.ss_family == AF_INET6) {
1049
0
        const struct sockaddr_in6 *addr_in6 = (const struct sockaddr_in6 *)&addr.addr;
1050
0
        const Family *const family = make_tox_family(addr_in6->sin6_family);
1051
0
        assert(family != nullptr);
1052
1053
0
        if (family == nullptr) {
1054
0
            return -1;
1055
0
        }
1056
1057
0
        ip_port->ip.family = *family;
1058
0
        get_ip6(&ip_port->ip.ip.v6, &addr_in6->sin6_addr);
1059
0
        ip_port->port = addr_in6->sin6_port;
1060
1061
0
        if (ipv6_ipv4_in_v6(&ip_port->ip.ip.v6)) {
1062
0
            ip_port->ip.family = net_family_ipv4();
1063
0
            ip_port->ip.ip.v4.uint32 = ip_port->ip.ip.v6.uint32[3];
1064
0
        }
1065
0
    } else {
1066
0
        return -1;
1067
0
    }
1068
1069
984k
    loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length);
1070
1071
984k
    return 0;
1072
984k
}
1073
1074
void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_cb *cb, void *object)
1075
209k
{
1076
209k
    net->packethandlers[byte].function = cb;
1077
209k
    net->packethandlers[byte].object = object;
1078
209k
}
1079
1080
void networking_poll(const Networking_Core *net, void *userdata)
1081
158k
{
1082
158k
    if (net_family_is_unspec(net->family)) {
1083
        /* Socket not initialized */
1084
1.28k
        return;
1085
1.28k
    }
1086
1087
157k
    IP_Port ip_port;
1088
157k
    uint8_t data[MAX_UDP_PACKET_SIZE] = {0};
1089
157k
    uint32_t length;
1090
1091
1.14M
    while (receivepacket(net->ns, net->mem, net->log, net->sock, &ip_port, data, &length) != -1) {
1092
984k
        if (length < 1) {
1093
6.18k
            continue;
1094
6.18k
        }
1095
1096
978k
        const Packet_Handler *const handler = &net->packethandlers[data[0]];
1097
1098
978k
        if (handler->function == nullptr) {
1099
            // TODO(https://github.com/TokTok/c-toxcore/issues/1115): Make this
1100
            // a warning or error again.
1101
1.56k
            LOGGER_DEBUG(net->log, "[%02u] -- Packet has no handler", data[0]);
1102
1.56k
            continue;
1103
1.56k
        }
1104
1105
976k
        handler->function(handler->object, &ip_port, data, length, userdata);
1106
976k
    }
1107
157k
}
1108
1109
/** @brief Initialize networking.
1110
 * Bind to ip and port.
1111
 * ip must be in network order EX: 127.0.0.1 = (7F000001).
1112
 * port is in host byte order (this means don't worry about it).
1113
 *
1114
 * @return Networking_Core object if no problems
1115
 * @retval NULL if there are problems.
1116
 *
1117
 * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
1118
 */
1119
Networking_Core *new_networking_ex(
1120
        const Logger *log, const Memory *mem, const Network *ns, const IP *ip,
1121
        uint16_t port_from, uint16_t port_to, unsigned int *error)
1122
4.01k
{
1123
    /* If both from and to are 0, use default port range
1124
     * If one is 0 and the other is non-0, use the non-0 value as only port
1125
     * If from > to, swap
1126
     */
1127
4.01k
    if (port_from == 0 && port_to == 0) {
1128
1.77k
        port_from = TOX_PORTRANGE_FROM;
1129
1.77k
        port_to = TOX_PORTRANGE_TO;
1130
2.23k
    } else if (port_from == 0 && port_to != 0) {
1131
3
        port_from = port_to;
1132
2.23k
    } else if (port_from != 0 && port_to == 0) {
1133
1
        port_to = port_from;
1134
2.22k
    } else if (port_from > port_to) {
1135
2
        const uint16_t temp_port = port_from;
1136
2
        port_from = port_to;
1137
2
        port_to = temp_port;
1138
2
    }
1139
1140
4.01k
    if (error != nullptr) {
1141
3.92k
        *error = 2;
1142
3.92k
    }
1143
1144
    /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
1145
4.01k
    if (!net_family_is_ipv4(ip->family) && !net_family_is_ipv6(ip->family)) {
1146
2
        LOGGER_ERROR(log, "invalid address family: %u", ip->family.value);
1147
2
        return nullptr;
1148
2
    }
1149
1150
4.00k
    Networking_Core *temp = (Networking_Core *)mem_alloc(mem, sizeof(Networking_Core));
1151
1152
4.00k
    if (temp == nullptr) {
1153
14
        return nullptr;
1154
14
    }
1155
1156
3.99k
    temp->ns = ns;
1157
3.99k
    temp->log = log;
1158
3.99k
    temp->mem = mem;
1159
3.99k
    temp->family = ip->family;
1160
3.99k
    temp->port = 0;
1161
1162
    /* Initialize our socket. */
1163
    /* add log message what we're creating */
1164
3.99k
    temp->sock = net_socket(ns, temp->family, TOX_SOCK_DGRAM, TOX_PROTO_UDP);
1165
1166
    /* Check for socket error. */
1167
3.99k
    if (!sock_valid(temp->sock)) {
1168
19
        const int neterror = net_error();
1169
19
        char *strerror = net_new_strerror(neterror);
1170
19
        LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, strerror);
1171
19
        net_kill_strerror(strerror);
1172
19
        mem_delete(mem, temp);
1173
1174
19
        if (error != nullptr) {
1175
19
            *error = 1;
1176
19
        }
1177
1178
19
        return nullptr;
1179
19
    }
1180
1181
    /* Functions to increase the size of the send and receive UDP buffers.
1182
     */
1183
3.97k
    int n = 1024 * 1024 * 2;
1184
1185
3.97k
    if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) != 0) {
1186
20
        LOGGER_WARNING(log, "failed to set socket option %d", SO_RCVBUF);
1187
20
    }
1188
1189
3.97k
    if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)) != 0) {
1190
20
        LOGGER_WARNING(log, "failed to set socket option %d", SO_SNDBUF);
1191
20
    }
1192
1193
    /* Enable broadcast on socket */
1194
3.97k
    int broadcast = 1;
1195
1196
3.97k
    if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) != 0) {
1197
20
        LOGGER_ERROR(log, "failed to set socket option %d", SO_BROADCAST);
1198
20
    }
1199
1200
    /* iOS UDP sockets are weird and apparently can SIGPIPE */
1201
3.97k
    if (!set_socket_nosigpipe(ns, temp->sock)) {
1202
0
        kill_networking(temp);
1203
1204
0
        if (error != nullptr) {
1205
0
            *error = 1;
1206
0
        }
1207
1208
0
        return nullptr;
1209
0
    }
1210
1211
    /* Set socket nonblocking. */
1212
3.97k
    if (!set_socket_nonblock(ns, temp->sock)) {
1213
0
        kill_networking(temp);
1214
1215
0
        if (error != nullptr) {
1216
0
            *error = 1;
1217
0
        }
1218
1219
0
        return nullptr;
1220
0
    }
1221
1222
    /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
1223
3.97k
    uint16_t *portptr = nullptr;
1224
3.97k
    Network_Addr addr = {{0}};
1225
1226
3.97k
    if (net_family_is_ipv4(temp->family)) {
1227
2.19k
        struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
1228
1229
2.19k
        addr.size = sizeof(struct sockaddr_in);
1230
2.19k
        addr4->sin_family = AF_INET;
1231
2.19k
        addr4->sin_port = 0;
1232
2.19k
        fill_addr4(&ip->ip.v4, &addr4->sin_addr);
1233
1234
2.19k
        portptr = &addr4->sin_port;
1235
2.19k
    } else if (net_family_is_ipv6(temp->family)) {
1236
1.78k
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
1237
1238
1.78k
        addr.size = sizeof(struct sockaddr_in6);
1239
1.78k
        addr6->sin6_family = AF_INET6;
1240
1.78k
        addr6->sin6_port = 0;
1241
1.78k
        fill_addr6(&ip->ip.v6, &addr6->sin6_addr);
1242
1243
1.78k
        addr6->sin6_flowinfo = 0;
1244
1.78k
        addr6->sin6_scope_id = 0;
1245
1246
1.78k
        portptr = &addr6->sin6_port;
1247
1.78k
    } else {
1248
0
        mem_delete(mem, temp);
1249
0
        return nullptr;
1250
0
    }
1251
1252
3.97k
    if (net_family_is_ipv6(ip->family)) {
1253
1.78k
        const bool is_dualstack = set_socket_dualstack(ns, temp->sock);
1254
1255
1.78k
        if (is_dualstack) {
1256
1.78k
            LOGGER_TRACE(log, "Dual-stack socket: enabled");
1257
1.78k
        } else {
1258
0
            LOGGER_ERROR(log, "Dual-stack socket failed to enable, won't be able to receive from/send to IPv4 addresses");
1259
0
        }
1260
1261
1.78k
#ifndef ESP_PLATFORM
1262
        /* multicast local nodes */
1263
1.78k
        struct ipv6_mreq mreq = {{0}};
1264
1.78k
        mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
1265
1.78k
        mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
1266
1.78k
        mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
1267
1.78k
        mreq.ipv6mr_interface = 0;
1268
1269
1.78k
        const int res = net_setsockopt(ns, temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
1270
1271
1.78k
        int neterror = net_error();
1272
1.78k
        char *strerror = net_new_strerror(neterror);
1273
1274
1.78k
        if (res < 0) {
1275
5
            LOGGER_INFO(log, "Failed to activate local multicast membership in FF02::1. (%d, %s)", neterror, strerror);
1276
1.77k
        } else {
1277
1.77k
            LOGGER_TRACE(log, "Local multicast group joined successfully. (%d, %s)", neterror, strerror);
1278
1.77k
        }
1279
1280
1.78k
        net_kill_strerror(strerror);
1281
1.78k
#endif /* ESP_PLATFORM */
1282
1.78k
    }
1283
1284
    /* A hanging program or a different user might block the standard port.
1285
     * As long as it isn't a parameter coming from the commandline,
1286
     * try a few ports after it, to see if we can find a "free" one.
1287
     *
1288
     * If we go on without binding, the first sendto() automatically binds to
1289
     * a free port chosen by the system (i.e. anything from 1024 to 65535).
1290
     *
1291
     * Returning NULL after bind fails has both advantages and disadvantages:
1292
     * advantage:
1293
     *   we can rely on getting the port in the range 33445..33450, which
1294
     *   enables us to tell joe user to open their firewall to a small range
1295
     *
1296
     * disadvantage:
1297
     *   some clients might not test return of tox_new(), blindly assuming that
1298
     *   it worked ok (which it did previously without a successful bind)
1299
     */
1300
3.97k
    uint16_t port_to_try = port_from;
1301
3.97k
    *portptr = net_htons(port_to_try);
1302
1303
65.3k
    for (uint16_t tries = port_from; tries <= port_to; ++tries) {
1304
65.3k
        const int res = net_bind(ns, temp->sock, &addr);
1305
1306
65.3k
        if (res == 0) {
1307
3.96k
            temp->port = *portptr;
1308
1309
3.96k
            Ip_Ntoa ip_str;
1310
3.96k
            LOGGER_DEBUG(log, "Bound successfully to %s:%u", net_ip_ntoa(ip, &ip_str),
1311
3.96k
                         net_ntohs(temp->port));
1312
1313
            /* errno isn't reset on success, only set on failure, the failed
1314
             * binds with parallel clients yield a -EPERM to the outside if
1315
             * errno isn't cleared here */
1316
3.96k
            if (tries > 0) {
1317
3.96k
                errno = 0;
1318
3.96k
            }
1319
1320
3.96k
            if (error != nullptr) {
1321
3.88k
                *error = 0;
1322
3.88k
            }
1323
1324
3.96k
            return temp;
1325
3.96k
        }
1326
1327
61.4k
        ++port_to_try;
1328
1329
61.4k
        if (port_to_try > port_to) {
1330
8
            port_to_try = port_from;
1331
8
        }
1332
1333
61.4k
        *portptr = net_htons(port_to_try);
1334
61.4k
    }
1335
1336
8
    Ip_Ntoa ip_str;
1337
8
    int neterror = net_error();
1338
8
    char *strerror = net_new_strerror(neterror);
1339
8
    LOGGER_ERROR(log, "failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u",
1340
8
                 neterror, strerror, net_ip_ntoa(ip, &ip_str), port_from, port_to);
1341
8
    net_kill_strerror(strerror);
1342
8
    kill_networking(temp);
1343
1344
8
    if (error != nullptr) {
1345
8
        *error = 1;
1346
8
    }
1347
1348
8
    return nullptr;
1349
3.97k
}
1350
1351
Networking_Core *new_networking_no_udp(const Logger *log, const Memory *mem, const Network *ns)
1352
234
{
1353
    /* this is the easiest way to completely disable UDP without changing too much code. */
1354
234
    Networking_Core *net = (Networking_Core *)mem_alloc(mem, sizeof(Networking_Core));
1355
1356
234
    if (net == nullptr) {
1357
1
        return nullptr;
1358
1
    }
1359
1360
233
    net->ns = ns;
1361
233
    net->log = log;
1362
233
    net->mem = mem;
1363
1364
233
    return net;
1365
234
}
1366
1367
/** Function to cleanup networking stuff (doesn't do much right now). */
1368
void kill_networking(Networking_Core *net)
1369
3.16k
{
1370
3.16k
    if (net == nullptr) {
1371
0
        return;
1372
0
    }
1373
1374
3.16k
    if (!net_family_is_unspec(net->family)) {
1375
        /* Socket is initialized, so we close it. */
1376
2.92k
        kill_sock(net->ns, net->sock);
1377
2.92k
    }
1378
1379
3.16k
    mem_delete(net->mem, net);
1380
3.16k
}
1381
1382
1383
bool ip_equal(const IP *a, const IP *b)
1384
412k
{
1385
412k
    if (a == nullptr || b == nullptr) {
1386
9
        return false;
1387
9
    }
1388
1389
    /* same family */
1390
412k
    if (a->family.value == b->family.value) {
1391
412k
        if (net_family_is_ipv4(a->family) || net_family_is_tcp_ipv4(a->family)) {
1392
412k
            struct in_addr addr_a;
1393
412k
            struct in_addr addr_b;
1394
412k
            fill_addr4(&a->ip.v4, &addr_a);
1395
412k
            fill_addr4(&b->ip.v4, &addr_b);
1396
412k
            return addr_a.s_addr == addr_b.s_addr;
1397
412k
        }
1398
1399
6
        if (net_family_is_ipv6(a->family) || net_family_is_tcp_ipv6(a->family)) {
1400
6
            return a->ip.v6.uint64[0] == b->ip.v6.uint64[0] &&
1401
6
                   a->ip.v6.uint64[1] == b->ip.v6.uint64[1];
1402
6
        }
1403
1404
0
        return false;
1405
6
    }
1406
1407
    /* different family: check on the IPv6 one if it is the IPv4 one embedded */
1408
9
    if (net_family_is_ipv4(a->family) && net_family_is_ipv6(b->family)) {
1409
6
        if (ipv6_ipv4_in_v6(&b->ip.v6)) {
1410
3
            struct in_addr addr_a;
1411
3
            fill_addr4(&a->ip.v4, &addr_a);
1412
3
            return addr_a.s_addr == b->ip.v6.uint32[3];
1413
3
        }
1414
6
    } else if (net_family_is_ipv6(a->family) && net_family_is_ipv4(b->family)) {
1415
0
        if (ipv6_ipv4_in_v6(&a->ip.v6)) {
1416
0
            struct in_addr addr_b;
1417
0
            fill_addr4(&b->ip.v4, &addr_b);
1418
0
            return a->ip.v6.uint32[3] == addr_b.s_addr;
1419
0
        }
1420
0
    }
1421
1422
6
    return false;
1423
9
}
1424
1425
bool ipport_equal(const IP_Port *a, const IP_Port *b)
1426
12.8M
{
1427
12.8M
    if (a == nullptr || b == nullptr) {
1428
0
        return false;
1429
0
    }
1430
1431
12.8M
    if (a->port == 0 || (a->port != b->port)) {
1432
12.4M
        return false;
1433
12.4M
    }
1434
1435
412k
    return ip_equal(&a->ip, &b->ip);
1436
12.8M
}
1437
1438
/** nulls out ip */
1439
void ip_reset(IP *ip)
1440
67.3k
{
1441
67.3k
    if (ip == nullptr) {
1442
0
        return;
1443
0
    }
1444
1445
67.3k
    *ip = empty_ip;
1446
67.3k
}
1447
1448
/** nulls out ip_port */
1449
void ipport_reset(IP_Port *ipport)
1450
484k
{
1451
484k
    if (ipport == nullptr) {
1452
0
        return;
1453
0
    }
1454
1455
484k
    const IP_Port empty_ip_port = {{{0}}};
1456
484k
    *ipport = empty_ip_port;
1457
484k
}
1458
1459
/** nulls out ip, sets family according to flag */
1460
void ip_init(IP *ip, bool ipv6enabled)
1461
4.14k
{
1462
4.14k
    if (ip == nullptr) {
1463
0
        return;
1464
0
    }
1465
1466
4.14k
    *ip = empty_ip;
1467
4.14k
    ip->family = ipv6enabled ? net_family_ipv6() : net_family_ipv4();
1468
4.14k
}
1469
1470
/** checks if ip is valid */
1471
bool ip_isset(const IP *ip)
1472
6.16M
{
1473
6.16M
    if (ip == nullptr) {
1474
0
        return false;
1475
0
    }
1476
1477
6.16M
    return !net_family_is_unspec(ip->family);
1478
6.16M
}
1479
1480
/** checks if ip is valid */
1481
bool ipport_isset(const IP_Port *ipport)
1482
386k
{
1483
386k
    if (ipport == nullptr) {
1484
0
        return false;
1485
0
    }
1486
1487
386k
    if (ipport->port == 0) {
1488
138k
        return false;
1489
138k
    }
1490
1491
247k
    return ip_isset(&ipport->ip);
1492
386k
}
1493
1494
/** copies an ip structure (careful about direction) */
1495
void ip_copy(IP *target, const IP *source)
1496
6
{
1497
6
    if (source == nullptr || target == nullptr) {
1498
0
        return;
1499
0
    }
1500
1501
6
    *target = *source;
1502
6
}
1503
1504
/** copies an ip_port structure (careful about direction) */
1505
void ipport_copy(IP_Port *target, const IP_Port *source)
1506
6.87k
{
1507
6.87k
    if (source == nullptr || target == nullptr) {
1508
0
        return;
1509
0
    }
1510
1511
6.87k
    *target = *source;
1512
6.87k
}
1513
1514
const char *net_ip_ntoa(const IP *ip, Ip_Ntoa *ip_str)
1515
2.95M
{
1516
2.95M
    assert(ip_str != nullptr);
1517
1518
2.95M
    ip_str->ip_is_valid = false;
1519
1520
2.95M
    if (ip == nullptr) {
1521
0
        snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid: NULL)");
1522
0
        ip_str->length = (uint16_t)strlen(ip_str->buf);
1523
0
        return ip_str->buf;
1524
0
    }
1525
1526
2.95M
    if (!ip_parse_addr(ip, ip_str->buf, sizeof(ip_str->buf))) {
1527
19.3k
        snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid, family %u)", ip->family.value);
1528
19.3k
        ip_str->length = (uint16_t)strlen(ip_str->buf);
1529
19.3k
        return ip_str->buf;
1530
19.3k
    }
1531
1532
    /* brute force protection against lacking termination */
1533
2.93M
    ip_str->buf[sizeof(ip_str->buf) - 1] = '\0';
1534
2.93M
    ip_str->length = (uint16_t)strlen(ip_str->buf);
1535
2.93M
    ip_str->ip_is_valid = true;
1536
1537
2.93M
    return ip_str->buf;
1538
2.95M
}
1539
1540
bool ip_parse_addr(const IP *ip, char *address, size_t length)
1541
2.95M
{
1542
2.95M
    if (address == nullptr || ip == nullptr) {
1543
0
        return false;
1544
0
    }
1545
1546
2.95M
    if (net_family_is_ipv4(ip->family)) {
1547
2.92M
        struct in_addr addr;
1548
2.92M
        assert(make_family(ip->family) == AF_INET);
1549
2.92M
        fill_addr4(&ip->ip.v4, &addr);
1550
2.92M
        return inet_ntop4(&addr, address, length) != nullptr;
1551
2.92M
    }
1552
1553
35.6k
    if (net_family_is_ipv6(ip->family)) {
1554
16.2k
        struct in6_addr addr;
1555
16.2k
        assert(make_family(ip->family) == AF_INET6);
1556
16.2k
        fill_addr6(&ip->ip.v6, &addr);
1557
16.2k
        return inet_ntop6(&addr, address, length) != nullptr;
1558
16.2k
    }
1559
1560
19.3k
    return false;
1561
35.6k
}
1562
1563
bool addr_parse_ip(const char *address, IP *to)
1564
29.4k
{
1565
29.4k
    if (address == nullptr || to == nullptr) {
1566
0
        return false;
1567
0
    }
1568
1569
29.4k
    struct in_addr addr4;
1570
1571
29.4k
    if (inet_pton4(address, &addr4) == 1) {
1572
28.7k
        to->family = net_family_ipv4();
1573
28.7k
        get_ip4(&to->ip.v4, &addr4);
1574
28.7k
        return true;
1575
28.7k
    }
1576
1577
693
    struct in6_addr addr6;
1578
1579
693
    if (inet_pton6(address, &addr6) == 1) {
1580
0
        to->family = net_family_ipv6();
1581
0
        get_ip6(&to->ip.v6, &addr6);
1582
0
        return true;
1583
0
    }
1584
1585
693
    return false;
1586
693
}
1587
1588
/** addr_resolve return values */
1589
0
#define TOX_ADDR_RESOLVE_INET  1
1590
0
#define TOX_ADDR_RESOLVE_INET6 2
1591
1592
/**
1593
 * Uses getaddrinfo to resolve an address into an IP address.
1594
 *
1595
 * Uses the first IPv4/IPv6 addresses returned by getaddrinfo.
1596
 *
1597
 * @param address a hostname (or something parseable to an IP address)
1598
 * @param to to.family MUST be initialized, either set to a specific IP version
1599
 *   (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (0), if both
1600
 *   IP versions are acceptable
1601
 * @param extra can be NULL and is only set in special circumstances, see returns
1602
 *
1603
 * Returns in `*to` a valid IPAny (v4/v6),
1604
 * prefers v6 if `ip.family` was TOX_AF_UNSPEC and both available
1605
 * Returns in `*extra` an IPv4 address, if family was TOX_AF_UNSPEC and `*to` is TOX_AF_INET6
1606
 *
1607
 * @return 0 on failure, `TOX_ADDR_RESOLVE_*` on success.
1608
 */
1609
non_null(1, 2, 3) nullable(4)
1610
static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra)
1611
180
{
1612
180
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1613
180
    if ((true)) {
1614
180
        return 0;
1615
180
    }
1616
0
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
1617
1618
0
    if (address == nullptr || to == nullptr) {
1619
0
        return 0;
1620
0
    }
1621
1622
0
    const Family tox_family = to->family;
1623
0
    const int family = make_family(tox_family);
1624
1625
0
    struct addrinfo hints = {0};
1626
0
    hints.ai_family   = family;
1627
0
    hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
1628
1629
0
    struct addrinfo *server = nullptr;
1630
1631
0
    const int rc = getaddrinfo(address, nullptr, &hints, &server);
1632
1633
    // Lookup failed.
1634
0
    if (rc != 0) {
1635
0
        return 0;
1636
0
    }
1637
1638
0
    IP ip4;
1639
0
    ip_init(&ip4, false); // ipv6enabled = false
1640
0
    IP ip6;
1641
0
    ip_init(&ip6, true); // ipv6enabled = true
1642
1643
0
    int result = 0;
1644
0
    bool done = false;
1645
1646
0
    for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) {
1647
0
        switch (walker->ai_family) {
1648
0
            case AF_INET: {
1649
0
                if (walker->ai_family == family) { /* AF_INET requested, done */
1650
0
                    const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
1651
0
                    get_ip4(&to->ip.v4, &addr->sin_addr);
1652
0
                    result = TOX_ADDR_RESOLVE_INET;
1653
0
                    done = true;
1654
0
                } else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */
1655
0
                    const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
1656
0
                    get_ip4(&ip4.ip.v4, &addr->sin_addr);
1657
0
                    result |= TOX_ADDR_RESOLVE_INET;
1658
0
                }
1659
1660
0
                break; /* switch */
1661
0
            }
1662
1663
0
            case AF_INET6: {
1664
0
                if (walker->ai_family == family) { /* AF_INET6 requested, done */
1665
0
                    if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
1666
0
                        const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
1667
0
                        get_ip6(&to->ip.v6, &addr->sin6_addr);
1668
0
                        result = TOX_ADDR_RESOLVE_INET6;
1669
0
                        done = true;
1670
0
                    }
1671
0
                } else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */
1672
0
                    if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
1673
0
                        const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
1674
0
                        get_ip6(&ip6.ip.v6, &addr->sin6_addr);
1675
0
                        result |= TOX_ADDR_RESOLVE_INET6;
1676
0
                    }
1677
0
                }
1678
1679
0
                break; /* switch */
1680
0
            }
1681
0
        }
1682
0
    }
1683
1684
0
    if (family == AF_UNSPEC) {
1685
0
        if ((result & TOX_ADDR_RESOLVE_INET6) != 0) {
1686
0
            ip_copy(to, &ip6);
1687
1688
0
            if ((result & TOX_ADDR_RESOLVE_INET) != 0 && (extra != nullptr)) {
1689
0
                ip_copy(extra, &ip4);
1690
0
            }
1691
0
        } else if ((result & TOX_ADDR_RESOLVE_INET) != 0) {
1692
0
            ip_copy(to, &ip4);
1693
0
        } else {
1694
0
            result = 0;
1695
0
        }
1696
0
    }
1697
1698
0
    freeaddrinfo(server);
1699
0
    return result;
1700
0
}
1701
1702
bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra)
1703
193
{
1704
193
    if (addr_resolve(ns, address, to, extra) == 0) {
1705
180
        if (!addr_parse_ip(address, to)) {
1706
0
            return false;
1707
0
        }
1708
180
    }
1709
1710
193
    return true;
1711
193
}
1712
1713
bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port)
1714
368
{
1715
368
    struct sockaddr_storage addr = {0};
1716
368
    size_t addrsize;
1717
1718
368
    if (net_family_is_ipv4(ip_port->ip.family)) {
1719
368
        struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
1720
1721
368
        addrsize = sizeof(struct sockaddr_in);
1722
368
        addr4->sin_family = AF_INET;
1723
368
        fill_addr4(&ip_port->ip.ip.v4, &addr4->sin_addr);
1724
368
        addr4->sin_port = ip_port->port;
1725
368
    } else if (net_family_is_ipv6(ip_port->ip.family)) {
1726
0
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
1727
1728
0
        addrsize = sizeof(struct sockaddr_in6);
1729
0
        addr6->sin6_family = AF_INET6;
1730
0
        fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr);
1731
0
        addr6->sin6_port = ip_port->port;
1732
0
    } else {
1733
0
        Ip_Ntoa ip_str;
1734
0
        LOGGER_ERROR(log, "cannot connect to %s:%d which is neither IPv4 nor IPv6",
1735
0
                     net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
1736
0
        return false;
1737
0
    }
1738
1739
368
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1740
368
    if ((true)) {
1741
368
        return true;
1742
368
    }
1743
0
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
1744
1745
0
    Ip_Ntoa ip_str;
1746
0
    LOGGER_DEBUG(log, "connecting socket %d to %s:%d",
1747
0
                 (int)sock.sock, net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
1748
0
    errno = 0;
1749
1750
0
    if (connect(sock.sock, (struct sockaddr *)&addr, addrsize) == -1) {
1751
0
        const int error = net_error();
1752
1753
        // Non-blocking socket: "Operation in progress" means it's connecting.
1754
0
        if (!should_ignore_connect_error(error)) {
1755
0
            char *net_strerror = net_new_strerror(error);
1756
0
            LOGGER_WARNING(log, "failed to connect to %s:%d: %d (%s)",
1757
0
                           net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror);
1758
0
            net_kill_strerror(net_strerror);
1759
0
            return false;
1760
0
        }
1761
0
    }
1762
1763
0
    return true;
1764
0
}
1765
1766
int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type)
1767
29.2k
{
1768
29.2k
    assert(node != nullptr);
1769
1770
    // Try parsing as IP address first.
1771
29.2k
    IP_Port parsed = {{{0}}};
1772
    // Initialise to nullptr. In error paths, at least we initialise the out
1773
    // parameter.
1774
29.2k
    *res = nullptr;
1775
1776
29.2k
    if (addr_parse_ip(node, &parsed.ip)) {
1777
28.6k
        IP_Port *tmp = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
1778
1779
28.6k
        if (tmp == nullptr) {
1780
879
            return -1;
1781
879
        }
1782
1783
27.7k
        tmp[0] = parsed;
1784
27.7k
        *res = tmp;
1785
27.7k
        return 1;
1786
28.6k
    }
1787
1788
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1789
0
    if ((true)) {
1790
0
        IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
1791
0
        if (ip_port == nullptr) {
1792
0
            abort();
1793
0
        }
1794
0
        ip_port->ip.ip.v4.uint32 = net_htonl(0x7F000003); // 127.0.0.3
1795
0
        ip_port->ip.family = *make_tox_family(AF_INET);
1796
1797
0
        *res = ip_port;
1798
0
        return 1;
1799
0
    }
1800
0
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
1801
1802
    // It's not an IP address, so now we try doing a DNS lookup.
1803
693
    struct addrinfo *infos;
1804
693
    const int ret = getaddrinfo(node, nullptr, nullptr, &infos);
1805
1806
693
    if (ret != 0) {
1807
96
        return -1;
1808
96
    }
1809
1810
    // Used to avoid calloc parameter overflow
1811
597
    const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
1812
597
    const int type = make_socktype(tox_type);
1813
597
    size_t count = 0;
1814
1815
4.13k
    for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
1816
3.53k
        if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1817
2.35k
            continue;
1818
2.35k
        }
1819
1820
1.17k
        if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
1821
0
            continue;
1822
0
        }
1823
1824
1.17k
        ++count;
1825
1.17k
    }
1826
1827
597
    assert(count <= max_count);
1828
1829
597
    if (count == 0) {
1830
0
        freeaddrinfo(infos);
1831
0
        return 0;
1832
0
    }
1833
1834
597
    IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port));
1835
1836
597
    if (ip_port == nullptr) {
1837
1
        freeaddrinfo(infos);
1838
1
        *res = nullptr;
1839
1
        return -1;
1840
1
    }
1841
1842
596
    *res = ip_port;
1843
1844
4.12k
    for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {
1845
3.52k
        if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1846
2.35k
            continue;
1847
2.35k
        }
1848
1849
1.17k
        if (cur->ai_family == AF_INET) {
1850
1.17k
            const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
1851
1.17k
            memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));
1852
1.17k
        } else if (cur->ai_family == AF_INET6) {
1853
0
            const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;
1854
0
            memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));
1855
0
        } else {
1856
0
            continue;
1857
0
        }
1858
1859
1.17k
        const Family *const family = make_tox_family(cur->ai_family);
1860
1.17k
        assert(family != nullptr);
1861
1862
1.17k
        if (family == nullptr) {
1863
0
            freeaddrinfo(infos);
1864
0
            return -1;
1865
0
        }
1866
1867
1.17k
        ip_port->ip.family = *family;
1868
1869
1.17k
        ++ip_port;
1870
1.17k
    }
1871
1872
596
    freeaddrinfo(infos);
1873
1874
596
    return count;
1875
596
}
net_getipport
Line
Count
Source
1767
1.51k
{
1768
1.51k
    assert(node != nullptr);
1769
1770
    // Try parsing as IP address first.
1771
1.51k
    IP_Port parsed = {{{0}}};
1772
    // Initialise to nullptr. In error paths, at least we initialise the out
1773
    // parameter.
1774
1.51k
    *res = nullptr;
1775
1776
1.51k
    if (addr_parse_ip(node, &parsed.ip)) {
1777
1.51k
        IP_Port *tmp = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
1778
1779
1.51k
        if (tmp == nullptr) {
1780
879
            return -1;
1781
879
        }
1782
1783
631
        tmp[0] = parsed;
1784
631
        *res = tmp;
1785
631
        return 1;
1786
1.51k
    }
1787
1788
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1789
0
    if ((true)) {
1790
0
        IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
1791
0
        if (ip_port == nullptr) {
1792
0
            abort();
1793
0
        }
1794
0
        ip_port->ip.ip.v4.uint32 = net_htonl(0x7F000003); // 127.0.0.3
1795
0
        ip_port->ip.family = *make_tox_family(AF_INET);
1796
1797
0
        *res = ip_port;
1798
0
        return 1;
1799
0
    }
1800
0
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
1801
1802
    // It's not an IP address, so now we try doing a DNS lookup.
1803
0
    struct addrinfo *infos;
1804
0
    const int ret = getaddrinfo(node, nullptr, nullptr, &infos);
1805
1806
0
    if (ret != 0) {
1807
0
        return -1;
1808
0
    }
1809
1810
    // Used to avoid calloc parameter overflow
1811
0
    const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
1812
0
    const int type = make_socktype(tox_type);
1813
0
    size_t count = 0;
1814
1815
0
    for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
1816
0
        if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1817
0
            continue;
1818
0
        }
1819
1820
0
        if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
1821
0
            continue;
1822
0
        }
1823
1824
0
        ++count;
1825
0
    }
1826
1827
0
    assert(count <= max_count);
1828
1829
0
    if (count == 0) {
1830
0
        freeaddrinfo(infos);
1831
0
        return 0;
1832
0
    }
1833
1834
0
    IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port));
1835
1836
0
    if (ip_port == nullptr) {
1837
0
        freeaddrinfo(infos);
1838
0
        *res = nullptr;
1839
0
        return -1;
1840
0
    }
1841
1842
0
    *res = ip_port;
1843
1844
0
    for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {
1845
0
        if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1846
0
            continue;
1847
0
        }
1848
1849
0
        if (cur->ai_family == AF_INET) {
1850
0
            const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
1851
0
            memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));
1852
0
        } else if (cur->ai_family == AF_INET6) {
1853
0
            const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;
1854
0
            memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));
1855
0
        } else {
1856
0
            continue;
1857
0
        }
1858
1859
0
        const Family *const family = make_tox_family(cur->ai_family);
1860
0
        assert(family != nullptr);
1861
1862
0
        if (family == nullptr) {
1863
0
            freeaddrinfo(infos);
1864
0
            return -1;
1865
0
        }
1866
1867
0
        ip_port->ip.family = *family;
1868
1869
0
        ++ip_port;
1870
0
    }
1871
1872
0
    freeaddrinfo(infos);
1873
1874
0
    return count;
1875
0
}
net_getipport
Line
Count
Source
1767
27.7k
{
1768
27.7k
    assert(node != nullptr);
1769
1770
    // Try parsing as IP address first.
1771
27.7k
    IP_Port parsed = {{{0}}};
1772
    // Initialise to nullptr. In error paths, at least we initialise the out
1773
    // parameter.
1774
27.7k
    *res = nullptr;
1775
1776
27.7k
    if (addr_parse_ip(node, &parsed.ip)) {
1777
27.0k
        IP_Port *tmp = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
1778
1779
27.0k
        if (tmp == nullptr) {
1780
0
            return -1;
1781
0
        }
1782
1783
27.0k
        tmp[0] = parsed;
1784
27.0k
        *res = tmp;
1785
27.0k
        return 1;
1786
27.0k
    }
1787
1788
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1789
    if ((true)) {
1790
        IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
1791
        if (ip_port == nullptr) {
1792
            abort();
1793
        }
1794
        ip_port->ip.ip.v4.uint32 = net_htonl(0x7F000003); // 127.0.0.3
1795
        ip_port->ip.family = *make_tox_family(AF_INET);
1796
1797
        *res = ip_port;
1798
        return 1;
1799
    }
1800
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
1801
1802
    // It's not an IP address, so now we try doing a DNS lookup.
1803
693
    struct addrinfo *infos;
1804
693
    const int ret = getaddrinfo(node, nullptr, nullptr, &infos);
1805
1806
693
    if (ret != 0) {
1807
96
        return -1;
1808
96
    }
1809
1810
    // Used to avoid calloc parameter overflow
1811
597
    const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
1812
597
    const int type = make_socktype(tox_type);
1813
597
    size_t count = 0;
1814
1815
4.13k
    for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
1816
3.53k
        if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1817
2.35k
            continue;
1818
2.35k
        }
1819
1820
1.17k
        if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
1821
0
            continue;
1822
0
        }
1823
1824
1.17k
        ++count;
1825
1.17k
    }
1826
1827
597
    assert(count <= max_count);
1828
1829
597
    if (count == 0) {
1830
0
        freeaddrinfo(infos);
1831
0
        return 0;
1832
0
    }
1833
1834
597
    IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port));
1835
1836
597
    if (ip_port == nullptr) {
1837
1
        freeaddrinfo(infos);
1838
1
        *res = nullptr;
1839
1
        return -1;
1840
1
    }
1841
1842
596
    *res = ip_port;
1843
1844
4.12k
    for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {
1845
3.52k
        if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1846
2.35k
            continue;
1847
2.35k
        }
1848
1849
1.17k
        if (cur->ai_family == AF_INET) {
1850
1.17k
            const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
1851
1.17k
            memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));
1852
1.17k
        } else if (cur->ai_family == AF_INET6) {
1853
0
            const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;
1854
0
            memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));
1855
0
        } else {
1856
0
            continue;
1857
0
        }
1858
1859
1.17k
        const Family *const family = make_tox_family(cur->ai_family);
1860
1.17k
        assert(family != nullptr);
1861
1862
1.17k
        if (family == nullptr) {
1863
0
            freeaddrinfo(infos);
1864
0
            return -1;
1865
0
        }
1866
1867
1.17k
        ip_port->ip.family = *family;
1868
1869
1.17k
        ++ip_port;
1870
1.17k
    }
1871
1872
596
    freeaddrinfo(infos);
1873
1874
596
    return count;
1875
596
}
1876
1877
void net_freeipport(const Memory *mem, IP_Port *ip_ports)
1878
29.2k
{
1879
29.2k
    mem_delete(mem, ip_ports);
1880
29.2k
}
1881
1882
bool bind_to_port(const Network *ns, Socket sock, Family family, uint16_t port)
1883
35
{
1884
35
    Network_Addr addr = {{0}};
1885
1886
35
    if (net_family_is_ipv4(family)) {
1887
19
        struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
1888
1889
19
        addr.size = sizeof(struct sockaddr_in);
1890
19
        addr4->sin_family = AF_INET;
1891
19
        addr4->sin_port = net_htons(port);
1892
19
    } else if (net_family_is_ipv6(family)) {
1893
16
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
1894
1895
16
        addr.size = sizeof(struct sockaddr_in6);
1896
16
        addr6->sin6_family = AF_INET6;
1897
16
        addr6->sin6_port = net_htons(port);
1898
16
    } else {
1899
0
        return false;
1900
0
    }
1901
1902
35
    return net_bind(ns, sock, &addr) == 0;
1903
35
}
1904
1905
Socket net_socket(const Network *ns, Family domain, int type, int protocol)
1906
4.50k
{
1907
4.50k
    const int platform_domain = make_family(domain);
1908
4.50k
    const int platform_type = make_socktype(type);
1909
4.50k
    const int platform_prot = make_proto(protocol);
1910
4.50k
    const Socket sock = {ns->funcs->socket(ns->obj, platform_domain, platform_type, platform_prot)};
1911
4.50k
    return sock;
1912
4.50k
}
1913
1914
uint16_t net_socket_data_recv_buffer(const Network *ns, Socket sock)
1915
45.0k
{
1916
45.0k
    const int count = ns->funcs->recvbuf(ns->obj, sock.sock);
1917
45.0k
    return (uint16_t)max_s32(0, min_s32(count, UINT16_MAX));
1918
45.0k
}
1919
1920
uint32_t net_htonl(uint32_t hostlong)
1921
1.38M
{
1922
1.38M
    return htonl(hostlong);
1923
1.38M
}
1924
1925
uint16_t net_htons(uint16_t hostshort)
1926
183k
{
1927
183k
    return htons(hostshort);
1928
183k
}
1929
1930
uint32_t net_ntohl(uint32_t hostlong)
1931
964k
{
1932
964k
    return ntohl(hostlong);
1933
964k
}
1934
1935
uint16_t net_ntohs(uint16_t hostshort)
1936
4.50M
{
1937
4.50M
    return ntohs(hostshort);
1938
4.50M
}
1939
1940
size_t net_pack_bool(uint8_t *bytes, bool v)
1941
20
{
1942
20
    bytes[0] = v ? 1 : 0;
1943
20
    return 1;
1944
20
}
1945
1946
size_t net_pack_u16(uint8_t *bytes, uint16_t v)
1947
217k
{
1948
217k
    bytes[0] = (v >> 8) & 0xff;
1949
217k
    bytes[1] = v & 0xff;
1950
217k
    return sizeof(v);
1951
217k
}
1952
1953
size_t net_pack_u32(uint8_t *bytes, uint32_t v)
1954
103k
{
1955
103k
    uint8_t *p = bytes;
1956
103k
    p += net_pack_u16(p, (v >> 16) & 0xffff);
1957
103k
    p += net_pack_u16(p, v & 0xffff);
1958
103k
    return p - bytes;
1959
103k
}
1960
1961
size_t net_pack_u64(uint8_t *bytes, uint64_t v)
1962
42.6k
{
1963
42.6k
    uint8_t *p = bytes;
1964
42.6k
    p += net_pack_u32(p, (v >> 32) & 0xffffffff);
1965
42.6k
    p += net_pack_u32(p, v & 0xffffffff);
1966
42.6k
    return p - bytes;
1967
42.6k
}
1968
1969
size_t net_unpack_bool(const uint8_t *bytes, bool *v)
1970
8.09k
{
1971
8.09k
    *v = bytes[0] != 0;
1972
8.09k
    return 1;
1973
8.09k
}
1974
1975
size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v)
1976
9.25M
{
1977
9.25M
    const uint8_t hi = bytes[0];
1978
9.25M
    const uint8_t lo = bytes[1];
1979
9.25M
    *v = ((uint16_t)hi << 8) | lo;
1980
9.25M
    return sizeof(*v);
1981
9.25M
}
1982
1983
size_t net_unpack_u32(const uint8_t *bytes, uint32_t *v)
1984
4.51M
{
1985
4.51M
    const uint8_t *p = bytes;
1986
4.51M
    uint16_t hi;
1987
4.51M
    uint16_t lo;
1988
4.51M
    p += net_unpack_u16(p, &hi);
1989
4.51M
    p += net_unpack_u16(p, &lo);
1990
4.51M
    *v = ((uint32_t)hi << 16) | lo;
1991
4.51M
    return p - bytes;
1992
4.51M
}
1993
1994
size_t net_unpack_u64(const uint8_t *bytes, uint64_t *v)
1995
31.9k
{
1996
31.9k
    const uint8_t *p = bytes;
1997
31.9k
    uint32_t hi;
1998
31.9k
    uint32_t lo;
1999
31.9k
    p += net_unpack_u32(p, &hi);
2000
31.9k
    p += net_unpack_u32(p, &lo);
2001
31.9k
    *v = ((uint64_t)hi << 32) | lo;
2002
31.9k
    return p - bytes;
2003
31.9k
}
2004
2005
bool ipv6_ipv4_in_v6(const IP6 *a)
2006
16.2k
{
2007
16.2k
    return a->uint64[0] == 0 && a->uint32[2] == net_htonl(0xffff);
2008
16.2k
}
2009
2010
int net_error(void)
2011
163k
{
2012
#ifdef OS_WIN32
2013
    return WSAGetLastError();
2014
#else
2015
163k
    return errno;
2016
163k
#endif /* OS_WIN32 */
2017
163k
}
2018
2019
#ifdef OS_WIN32
2020
char *net_new_strerror(int error)
2021
{
2022
    char *str = nullptr;
2023
    // Windows API is weird. The 5th function arg is of char* type, but we
2024
    // have to pass char** so that it could assign new memory block to our
2025
    // pointer, so we have to cast our char** to char* for the compilation
2026
    // not to fail (otherwise it would fail to find a variant of this function
2027
    // accepting char** as the 5th arg) and Windows inside casts it back
2028
    // to char** to do the assignment. So no, this cast you see here, although
2029
    // it looks weird, is not a mistake.
2030
    FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
2031
                   error, 0, (char *)&str, 0, nullptr);
2032
    return str;
2033
}
2034
#else
2035
#if defined(_GNU_SOURCE) && defined(__GLIBC__)
2036
non_null()
2037
static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
2038
{
2039
    const char *retstr = strerror_r(error, tmp, tmp_size);
2040
2041
    if (errno != 0) {
2042
        snprintf(tmp, tmp_size, "error %d (strerror_r failed with errno %d)", error, errno);
2043
    }
2044
2045
    return retstr;
2046
}
2047
#else
2048
non_null()
2049
static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
2050
6.82k
{
2051
6.82k
    const int fmt_error = strerror_r(error, tmp, tmp_size);
2052
2053
6.82k
    if (fmt_error != 0) {
2054
0
        snprintf(tmp, tmp_size, "error %d (strerror_r failed with error %d, errno %d)", error, fmt_error, errno);
2055
0
    }
2056
2057
6.82k
    return tmp;
2058
6.82k
}
2059
#endif /* GNU */
2060
char *net_new_strerror(int error)
2061
6.82k
{
2062
6.82k
    char tmp[256];
2063
2064
6.82k
    errno = 0;
2065
2066
6.82k
    const char *retstr = net_strerror_r(error, tmp, sizeof(tmp));
2067
6.82k
    const size_t retstr_len = strlen(retstr);
2068
2069
6.82k
    char *str = (char *)malloc(retstr_len + 1);
2070
2071
6.82k
    if (str == nullptr) {
2072
733
        return nullptr;
2073
733
    }
2074
2075
6.08k
    memcpy(str, retstr, retstr_len + 1);
2076
2077
6.08k
    return str;
2078
6.82k
}
2079
#endif /* OS_WIN32 */
2080
2081
void net_kill_strerror(char *strerror)
2082
6.82k
{
2083
#ifdef OS_WIN32
2084
    LocalFree((char *)strerror);
2085
#else
2086
6.82k
    free(strerror);
2087
6.82k
#endif /* OS_WIN32 */
2088
6.82k
}