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 * Functions for the core networking.
8 */
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #ifdef __APPLE__
14 #define _DARWIN_C_SOURCE
15 #endif
16
17 // For Solaris.
18 #ifdef __sun
19 #define __EXTENSIONS__ 1
20 #endif
21
22 // For Linux (and some BSDs).
23 #ifndef _XOPEN_SOURCE
24 #define _XOPEN_SOURCE 700
25 #endif
26
27 #if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
28 #undef _WIN32_WINNT
29 #define _WIN32_WINNT 0x501
30 #endif
31
32 #if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
33 #define OS_WIN32
34 #endif
35
36 #ifdef OS_WIN32
37 #ifndef WINVER
38 // Windows XP
39 #define WINVER 0x0501
40 #endif
41 #endif
42
43 #ifdef PLAN9
44 #include <u.h> // Plan 9 requires this is imported first
45 // Comment line here to avoid reordering by source code formatters.
46 #include <libc.h>
47 #endif
48
49 #ifdef OS_WIN32 /* Put win32 includes here */
50 // The mingw32/64 Windows library warns about including winsock2.h after
51 // windows.h even though with the above it's a valid thing to do. So, to make
52 // mingw32 headers happy, we include winsock2.h first.
53 #include <winsock2.h>
54 // Comment line here to avoid reordering by source code formatters.
55 #include <windows.h>
56 #include <ws2tcpip.h>
57 #endif
58
59 #include "network.h"
60
61 #ifdef __APPLE__
62 #include <mach/clock.h>
63 #include <mach/mach.h>
64 #endif
65
66 #if !defined(OS_WIN32)
67
68 #include <arpa/inet.h>
69 #include <errno.h>
70 #include <fcntl.h>
71 #include <netdb.h>
72 #include <netinet/in.h>
73 #include <sys/ioctl.h>
74 #include <sys/socket.h>
75 #include <sys/time.h>
76 #include <sys/types.h>
77 #include <unistd.h>
78
79 #ifdef __sun
80 #include <stropts.h>
81 #include <sys/filio.h>
82 #endif
83
84 #define TOX_EWOULDBLOCK EWOULDBLOCK
85
inet_ntop4(const struct in_addr * addr,char * buf,size_t bufsize)86 static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)
87 {
88 return inet_ntop(AF_INET, addr, buf, bufsize);
89 }
90
inet_ntop6(const struct in6_addr * addr,char * buf,size_t bufsize)91 static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t bufsize)
92 {
93 return inet_ntop(AF_INET6, addr, buf, bufsize);
94 }
95
inet_pton4(const char * addrString,struct in_addr * addrbuf)96 static int inet_pton4(const char *addrString, struct in_addr *addrbuf)
97 {
98 return inet_pton(AF_INET, addrString, addrbuf);
99 }
100
inet_pton6(const char * addrString,struct in6_addr * addrbuf)101 static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
102 {
103 return inet_pton(AF_INET6, addrString, addrbuf);
104 }
105
106 #else
107 #ifndef IPV6_V6ONLY
108 #define IPV6_V6ONLY 27
109 #endif
110
111 #define TOX_EWOULDBLOCK WSAEWOULDBLOCK
112
inet_ntop4(const struct in_addr * addr,char * buf,size_t bufsize)113 static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)
114 {
115 struct sockaddr_in saddr = {0};
116
117 saddr.sin_family = AF_INET;
118 saddr.sin_addr = *addr;
119
120 DWORD len = bufsize;
121
122 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {
123 return nullptr;
124 }
125
126 return buf;
127 }
128
inet_ntop6(const struct in6_addr * addr,char * buf,size_t bufsize)129 static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t bufsize)
130 {
131 struct sockaddr_in6 saddr = {0};
132
133 saddr.sin6_family = AF_INET6;
134 saddr.sin6_addr = *addr;
135
136 DWORD len = bufsize;
137
138 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), nullptr, buf, &len)) {
139 return nullptr;
140 }
141
142 return buf;
143 }
144
inet_pton4(const char * addrString,struct in_addr * addrbuf)145 static int inet_pton4(const char *addrString, struct in_addr *addrbuf)
146 {
147 struct sockaddr_in saddr = {0};
148
149 INT len = sizeof(saddr);
150
151 if (WSAStringToAddress((LPTSTR)addrString, AF_INET, nullptr, (LPSOCKADDR)&saddr, &len)) {
152 return 0;
153 }
154
155 *addrbuf = saddr.sin_addr;
156
157 return 1;
158 }
159
inet_pton6(const char * addrString,struct in6_addr * addrbuf)160 static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
161 {
162 struct sockaddr_in6 saddr = {0};
163
164 INT len = sizeof(saddr);
165
166 if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, nullptr, (LPSOCKADDR)&saddr, &len)) {
167 return 0;
168 }
169
170 *addrbuf = saddr.sin6_addr;
171
172 return 1;
173 }
174
175 #endif
176
177 #include <assert.h>
178 #include <stdio.h>
179 #include <stdlib.h>
180 #include <string.h>
181
182 #include "logger.h"
183 #include "mono_time.h"
184 #include "util.h"
185
186 // Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
187 #if !defined(MSG_NOSIGNAL)
188 #define MSG_NOSIGNAL 0
189 #endif
190
191 #ifndef IPV6_ADD_MEMBERSHIP
192 #ifdef IPV6_JOIN_GROUP
193 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
194 #endif
195 #endif
196
197 #if TOX_INET6_ADDRSTRLEN < INET6_ADDRSTRLEN
198 #error "TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)"
199 #endif
200
201 #if TOX_INET_ADDRSTRLEN < INET_ADDRSTRLEN
202 #error "TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)"
203 #endif
204
make_proto(int proto)205 static int make_proto(int proto)
206 {
207 switch (proto) {
208 case TOX_PROTO_TCP:
209 return IPPROTO_TCP;
210
211 case TOX_PROTO_UDP:
212 return IPPROTO_UDP;
213
214 default:
215 return proto;
216 }
217 }
218
make_socktype(int type)219 static int make_socktype(int type)
220 {
221 switch (type) {
222 case TOX_SOCK_STREAM:
223 return SOCK_STREAM;
224
225 case TOX_SOCK_DGRAM:
226 return SOCK_DGRAM;
227
228 default:
229 return type;
230 }
231 }
232
make_family(Family tox_family)233 static int make_family(Family tox_family)
234 {
235 switch (tox_family.value) {
236 case TOX_AF_INET:
237 return AF_INET;
238
239 case TOX_AF_INET6:
240 return AF_INET6;
241
242 case TOX_AF_UNSPEC:
243 return AF_UNSPEC;
244
245 default:
246 return tox_family.value;
247 }
248 }
249
make_tox_family(int family)250 static const Family *make_tox_family(int family)
251 {
252 switch (family) {
253 case AF_INET:
254 return &net_family_ipv4;
255
256 case AF_INET6:
257 return &net_family_ipv6;
258
259 case AF_UNSPEC:
260 return &net_family_unspec;
261
262 default:
263 return nullptr;
264 }
265 }
266
get_ip4(IP4 * result,const struct in_addr * addr)267 static void get_ip4(IP4 *result, const struct in_addr *addr)
268 {
269 result->uint32 = addr->s_addr;
270 }
271
get_ip6(IP6 * result,const struct in6_addr * addr)272 static void get_ip6(IP6 *result, const struct in6_addr *addr)
273 {
274 assert(sizeof(result->uint8) == sizeof(addr->s6_addr));
275 memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8));
276 }
277
fill_addr4(IP4 ip,struct in_addr * addr)278 static void fill_addr4(IP4 ip, struct in_addr *addr)
279 {
280 addr->s_addr = ip.uint32;
281 }
282
fill_addr6(IP6 ip,struct in6_addr * addr)283 static void fill_addr6(IP6 ip, struct in6_addr *addr)
284 {
285 assert(sizeof(ip.uint8) == sizeof(addr->s6_addr));
286 memcpy(addr->s6_addr, ip.uint8, sizeof(ip.uint8));
287 }
288
289 #if !defined(INADDR_LOOPBACK)
290 #define INADDR_LOOPBACK 0x7f000001
291 #endif
292
293 const IP4 ip4_broadcast = { INADDR_BROADCAST };
294 const IP6 ip6_broadcast = {
295 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
296 };
297
get_ip4_loopback(void)298 IP4 get_ip4_loopback(void)
299 {
300 IP4 loopback;
301 loopback.uint32 = htonl(INADDR_LOOPBACK);
302 return loopback;
303 }
304
get_ip6_loopback(void)305 IP6 get_ip6_loopback(void)
306 {
307 IP6 loopback;
308 get_ip6(&loopback, &in6addr_loopback);
309 return loopback;
310 }
311
312 #ifndef OS_WIN32
313 #define INVALID_SOCKET (-1)
314 #endif
315
316 const Socket net_invalid_socket = { (int)INVALID_SOCKET };
317
318 const Family net_family_unspec = {TOX_AF_UNSPEC};
319 const Family net_family_ipv4 = {TOX_AF_INET};
320 const Family net_family_ipv6 = {TOX_AF_INET6};
321 const Family net_family_tcp_family = {TCP_FAMILY};
322 const Family net_family_tcp_onion = {TCP_ONION_FAMILY};
323 const Family net_family_tcp_ipv4 = {TCP_INET};
324 const Family net_family_tcp_ipv6 = {TCP_INET6};
325 const Family net_family_tox_tcp_ipv4 = {TOX_TCP_INET};
326 const Family net_family_tox_tcp_ipv6 = {TOX_TCP_INET6};
327
net_family_is_unspec(Family family)328 bool net_family_is_unspec(Family family)
329 {
330 return family.value == net_family_unspec.value;
331 }
332
net_family_is_ipv4(Family family)333 bool net_family_is_ipv4(Family family)
334 {
335 return family.value == net_family_ipv4.value;
336 }
337
net_family_is_ipv6(Family family)338 bool net_family_is_ipv6(Family family)
339 {
340 return family.value == net_family_ipv6.value;
341 }
342
net_family_is_tcp_family(Family family)343 bool net_family_is_tcp_family(Family family)
344 {
345 return family.value == net_family_tcp_family.value;
346 }
347
net_family_is_tcp_onion(Family family)348 bool net_family_is_tcp_onion(Family family)
349 {
350 return family.value == net_family_tcp_onion.value;
351 }
352
net_family_is_tcp_ipv4(Family family)353 bool net_family_is_tcp_ipv4(Family family)
354 {
355 return family.value == net_family_tcp_ipv4.value;
356 }
357
net_family_is_tcp_ipv6(Family family)358 bool net_family_is_tcp_ipv6(Family family)
359 {
360 return family.value == net_family_tcp_ipv6.value;
361 }
362
net_family_is_tox_tcp_ipv4(Family family)363 bool net_family_is_tox_tcp_ipv4(Family family)
364 {
365 return family.value == net_family_tox_tcp_ipv4.value;
366 }
367
net_family_is_tox_tcp_ipv6(Family family)368 bool net_family_is_tox_tcp_ipv6(Family family)
369 {
370 return family.value == net_family_tox_tcp_ipv6.value;
371 }
372
sock_valid(Socket sock)373 bool sock_valid(Socket sock)
374 {
375 return sock.socket != net_invalid_socket.socket;
376 }
377
378 /* Close the socket.
379 */
kill_sock(Socket sock)380 void kill_sock(Socket sock)
381 {
382 #ifdef OS_WIN32
383 closesocket(sock.socket);
384 #else
385 close(sock.socket);
386 #endif
387 }
388
set_socket_nonblock(Socket sock)389 bool set_socket_nonblock(Socket sock)
390 {
391 #ifdef OS_WIN32
392 u_long mode = 1;
393 return ioctlsocket(sock.socket, FIONBIO, &mode) == 0;
394 #else
395 return fcntl(sock.socket, F_SETFL, O_NONBLOCK, 1) == 0;
396 #endif
397 }
398
set_socket_nosigpipe(Socket sock)399 bool set_socket_nosigpipe(Socket sock)
400 {
401 #if defined(__APPLE__)
402 int set = 1;
403 return setsockopt(sock.socket, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set, sizeof(int)) == 0;
404 #else
405 return true;
406 #endif
407 }
408
set_socket_reuseaddr(Socket sock)409 bool set_socket_reuseaddr(Socket sock)
410 {
411 int set = 1;
412 return setsockopt(sock.socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0;
413 }
414
set_socket_dualstack(Socket sock)415 bool set_socket_dualstack(Socket sock)
416 {
417 int ipv6only = 0;
418 socklen_t optsize = sizeof(ipv6only);
419 int res = getsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optsize);
420
421 if ((res == 0) && (ipv6only == 0)) {
422 return true;
423 }
424
425 ipv6only = 0;
426 return setsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6only, sizeof(ipv6only)) == 0;
427 }
428
429
data_0(uint16_t buflen,const uint8_t * buffer)430 static uint32_t data_0(uint16_t buflen, const uint8_t *buffer)
431 {
432 uint32_t data = 0;
433
434 if (buflen > 4) {
435 net_unpack_u32(buffer + 1, &data);
436 }
437
438 return data;
439 }
data_1(uint16_t buflen,const uint8_t * buffer)440 static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)
441 {
442 uint32_t data = 0;
443
444 if (buflen > 7) {
445 net_unpack_u32(buffer + 5, &data);
446 }
447
448 return data;
449 }
450
loglogdata(const Logger * log,const char * message,const uint8_t * buffer,uint16_t buflen,IP_Port ip_port,int res)451 static void loglogdata(const Logger *log, const char *message, const uint8_t *buffer,
452 uint16_t buflen, IP_Port ip_port, int res)
453 {
454 char ip_str[IP_NTOA_LEN];
455
456 if (res < 0) { /* Windows doesn't necessarily know `%zu` */
457 int error = net_error();
458 const char *strerror = net_new_strerror(error);
459 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x",
460 buffer[0], message, min_u16(buflen, 999), 'E',
461 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), error,
462 strerror, data_0(buflen, buffer), data_1(buflen, buffer));
463 net_kill_strerror(strerror);
464 } else if ((res > 0) && ((size_t)res <= buflen)) {
465 LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x",
466 buffer[0], message, min_u16(res, 999), ((size_t)res < buflen ? '<' : '='),
467 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
468 data_0(buflen, buffer), data_1(buflen, buffer));
469 } else { /* empty or overwrite */
470 LOGGER_TRACE(log, "[%2u] %s %u%c%u %s:%u (%u: %s) | %04x%04x",
471 buffer[0], message, res, (!res ? '!' : '>'), buflen,
472 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
473 data_0(buflen, buffer), data_1(buflen, buffer));
474 }
475 }
476
477 typedef struct Packet_Handler {
478 packet_handler_cb *function;
479 void *object;
480 } Packet_Handler;
481
482 struct Networking_Core {
483 const Logger *log;
484 Packet_Handler packethandlers[256];
485
486 Family family;
487 uint16_t port;
488 /* Our UDP socket. */
489 Socket sock;
490 };
491
net_family(const Networking_Core * net)492 Family net_family(const Networking_Core *net)
493 {
494 return net->family;
495 }
496
net_port(const Networking_Core * net)497 uint16_t net_port(const Networking_Core *net)
498 {
499 return net->port;
500 }
501
502 /* Basic network functions:
503 * Function to send packet(data) of length length to ip_port.
504 */
sendpacket(Networking_Core * net,IP_Port ip_port,const uint8_t * data,uint16_t length)505 int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length)
506 {
507 if (net_family_is_unspec(net->family)) { /* Socket not initialized */
508 LOGGER_ERROR(net->log, "attempted to send message of length %u on uninitialised socket", (unsigned)length);
509 return -1;
510 }
511
512 /* socket TOX_AF_INET, but target IP NOT: can't send */
513 if (net_family_is_ipv4(net->family) && !net_family_is_ipv4(ip_port.ip.family)) {
514 LOGGER_ERROR(net->log, "attempted to send message with network family %d (probably IPv6) on IPv4 socket",
515 ip_port.ip.family.value);
516 return -1;
517 }
518
519 if (net_family_is_ipv4(ip_port.ip.family) && net_family_is_ipv6(net->family)) {
520 /* must convert to IPV4-in-IPV6 address */
521 IP6 ip6;
522
523 /* there should be a macro for this in a standards compliant
524 * environment, not found */
525 ip6.uint32[0] = 0;
526 ip6.uint32[1] = 0;
527 ip6.uint32[2] = net_htonl(0xFFFF);
528 ip6.uint32[3] = ip_port.ip.ip.v4.uint32;
529
530 ip_port.ip.family = net_family_ipv6;
531 ip_port.ip.ip.v6 = ip6;
532 }
533
534 struct sockaddr_storage addr;
535
536 size_t addrsize;
537
538 if (net_family_is_ipv4(ip_port.ip.family)) {
539 struct sockaddr_in *const addr4 = (struct sockaddr_in *)&addr;
540
541 addrsize = sizeof(struct sockaddr_in);
542 addr4->sin_family = AF_INET;
543 addr4->sin_port = ip_port.port;
544 fill_addr4(ip_port.ip.ip.v4, &addr4->sin_addr);
545 } else if (net_family_is_ipv6(ip_port.ip.family)) {
546 struct sockaddr_in6 *const addr6 = (struct sockaddr_in6 *)&addr;
547
548 addrsize = sizeof(struct sockaddr_in6);
549 addr6->sin6_family = AF_INET6;
550 addr6->sin6_port = ip_port.port;
551 fill_addr6(ip_port.ip.ip.v6, &addr6->sin6_addr);
552
553 addr6->sin6_flowinfo = 0;
554 addr6->sin6_scope_id = 0;
555 } else {
556 LOGGER_WARNING(net->log, "unknown address type: %d", ip_port.ip.family.value);
557 return -1;
558 }
559
560 const int res = sendto(net->sock.socket, (const char *)data, length, 0, (struct sockaddr *)&addr, addrsize);
561
562 loglogdata(net->log, "O=>", data, length, ip_port, res);
563
564 return res;
565 }
566
567 /* Function to receive data
568 * ip and port of sender is put into ip_port.
569 * Packet data is put into data.
570 * Packet length is put into length.
571 */
receivepacket(const Logger * log,Socket sock,IP_Port * ip_port,uint8_t * data,uint32_t * length)572 static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
573 {
574 memset(ip_port, 0, sizeof(IP_Port));
575 struct sockaddr_storage addr;
576 #ifdef OS_WIN32
577 int addrlen = sizeof(addr);
578 #else
579 socklen_t addrlen = sizeof(addr);
580 #endif
581 *length = 0;
582 int fail_or_len = recvfrom(sock.socket, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
583
584 if (fail_or_len < 0) {
585 int error = net_error();
586
587 if (fail_or_len < 0 && error != TOX_EWOULDBLOCK) {
588 const char *strerror = net_new_strerror(error);
589 LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s", error, strerror);
590 net_kill_strerror(strerror);
591 }
592
593 return -1; /* Nothing received. */
594 }
595
596 *length = (uint32_t)fail_or_len;
597
598 if (addr.ss_family == AF_INET) {
599 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
600
601 const Family *const family = make_tox_family(addr_in->sin_family);
602 assert(family != nullptr);
603
604 if (family == nullptr) {
605 return -1;
606 }
607
608 ip_port->ip.family = *family;
609 get_ip4(&ip_port->ip.ip.v4, &addr_in->sin_addr);
610 ip_port->port = addr_in->sin_port;
611 } else if (addr.ss_family == AF_INET6) {
612 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
613 const Family *const family = make_tox_family(addr_in6->sin6_family);
614 assert(family != nullptr);
615
616 if (family == nullptr) {
617 return -1;
618 }
619
620 ip_port->ip.family = *family;
621 get_ip6(&ip_port->ip.ip.v6, &addr_in6->sin6_addr);
622 ip_port->port = addr_in6->sin6_port;
623
624 if (ipv6_ipv4_in_v6(ip_port->ip.ip.v6)) {
625 ip_port->ip.family = net_family_ipv4;
626 ip_port->ip.ip.v4.uint32 = ip_port->ip.ip.v6.uint32[3];
627 }
628 } else {
629 return -1;
630 }
631
632 loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length);
633
634 return 0;
635 }
636
networking_registerhandler(Networking_Core * net,uint8_t byte,packet_handler_cb * cb,void * object)637 void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_cb *cb, void *object)
638 {
639 net->packethandlers[byte].function = cb;
640 net->packethandlers[byte].object = object;
641 }
642
networking_poll(Networking_Core * net,void * userdata)643 void networking_poll(Networking_Core *net, void *userdata)
644 {
645 if (net_family_is_unspec(net->family)) {
646 /* Socket not initialized */
647 return;
648 }
649
650 IP_Port ip_port;
651 uint8_t data[MAX_UDP_PACKET_SIZE];
652 uint32_t length;
653
654 while (receivepacket(net->log, net->sock, &ip_port, data, &length) != -1) {
655 if (length < 1) {
656 continue;
657 }
658
659 if (!(net->packethandlers[data[0]].function)) {
660 LOGGER_WARNING(net->log, "[%02u] -- Packet has no handler", data[0]);
661 continue;
662 }
663
664 net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length, userdata);
665 }
666 }
667
668 #ifndef VANILLA_NACL
669 /* Used for sodium_init() */
670 #include <sodium.h>
671 #endif
672
673 //!TOKSTYLE-
674 // Global mutable state is not allowed in Tokstyle.
675 static uint8_t at_startup_ran = 0;
676 //!TOKSTYLE+
networking_at_startup(void)677 int networking_at_startup(void)
678 {
679 if (at_startup_ran != 0) {
680 return 0;
681 }
682
683 #ifndef VANILLA_NACL
684
685 #ifdef USE_RANDOMBYTES_STIR
686 randombytes_stir();
687 #else
688
689 if (sodium_init() == -1) {
690 return -1;
691 }
692
693 #endif /*USE_RANDOMBYTES_STIR*/
694
695 #endif/*VANILLA_NACL*/
696
697 #ifdef OS_WIN32
698 WSADATA wsaData;
699
700 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
701 return -1;
702 }
703
704 #endif
705 at_startup_ran = 1;
706 return 0;
707 }
708
709 /* TODO(irungentoo): Put this somewhere */
710 #if 0
711 static void at_shutdown(void)
712 {
713 #ifdef OS_WIN32
714 WSACleanup();
715 #endif
716 }
717 #endif
718
719 /* Initialize networking.
720 * Added for reverse compatibility with old new_networking calls.
721 */
new_networking(const Logger * log,IP ip,uint16_t port)722 Networking_Core *new_networking(const Logger *log, IP ip, uint16_t port)
723 {
724 return new_networking_ex(log, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), nullptr);
725 }
726
727 /* Initialize networking.
728 * Bind to ip and port.
729 * ip must be in network order EX: 127.0.0.1 = (7F000001).
730 * port is in host byte order (this means don't worry about it).
731 *
732 * return Networking_Core object if no problems
733 * return NULL if there are problems.
734 *
735 * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
736 */
new_networking_ex(const Logger * log,IP ip,uint16_t port_from,uint16_t port_to,unsigned int * error)737 Networking_Core *new_networking_ex(const Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error)
738 {
739 /* If both from and to are 0, use default port range
740 * If one is 0 and the other is non-0, use the non-0 value as only port
741 * If from > to, swap
742 */
743 if (port_from == 0 && port_to == 0) {
744 port_from = TOX_PORTRANGE_FROM;
745 port_to = TOX_PORTRANGE_TO;
746 } else if (port_from == 0 && port_to != 0) {
747 port_from = port_to;
748 } else if (port_from != 0 && port_to == 0) {
749 port_to = port_from;
750 } else if (port_from > port_to) {
751 uint16_t temp = port_from;
752 port_from = port_to;
753 port_to = temp;
754 }
755
756 if (error) {
757 *error = 2;
758 }
759
760 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
761 if (!net_family_is_ipv4(ip.family) && !net_family_is_ipv6(ip.family)) {
762 LOGGER_ERROR(log, "invalid address family: %u", ip.family.value);
763 return nullptr;
764 }
765
766 if (networking_at_startup() != 0) {
767 return nullptr;
768 }
769
770 Networking_Core *temp = (Networking_Core *)calloc(1, sizeof(Networking_Core));
771
772 if (temp == nullptr) {
773 return nullptr;
774 }
775
776 temp->log = log;
777 temp->family = ip.family;
778 temp->port = 0;
779
780 /* Initialize our socket. */
781 /* add log message what we're creating */
782 temp->sock = net_socket(temp->family, TOX_SOCK_DGRAM, TOX_PROTO_UDP);
783
784 /* Check for socket error. */
785 if (!sock_valid(temp->sock)) {
786 int neterror = net_error();
787 const char *strerror = net_new_strerror(neterror);
788 LOGGER_ERROR(log, "Failed to get a socket?! %d, %s", neterror, strerror);
789 net_kill_strerror(strerror);
790 free(temp);
791
792 if (error) {
793 *error = 1;
794 }
795
796 return nullptr;
797 }
798
799 /* Functions to increase the size of the send and receive UDP buffers.
800 */
801 int n = 1024 * 1024 * 2;
802 setsockopt(temp->sock.socket, SOL_SOCKET, SO_RCVBUF, (const char *)&n, sizeof(n));
803 setsockopt(temp->sock.socket, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof(n));
804
805 /* Enable broadcast on socket */
806 int broadcast = 1;
807 setsockopt(temp->sock.socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast));
808
809 /* iOS UDP sockets are weird and apparently can SIGPIPE */
810 if (!set_socket_nosigpipe(temp->sock)) {
811 kill_networking(temp);
812
813 if (error) {
814 *error = 1;
815 }
816
817 return nullptr;
818 }
819
820 /* Set socket nonblocking. */
821 if (!set_socket_nonblock(temp->sock)) {
822 kill_networking(temp);
823
824 if (error) {
825 *error = 1;
826 }
827
828 return nullptr;
829 }
830
831 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
832 uint16_t *portptr = nullptr;
833 struct sockaddr_storage addr;
834 size_t addrsize;
835
836 memset(&addr, 0, sizeof(struct sockaddr_storage));
837
838 if (net_family_is_ipv4(temp->family)) {
839 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
840
841 addrsize = sizeof(struct sockaddr_in);
842 addr4->sin_family = AF_INET;
843 addr4->sin_port = 0;
844 fill_addr4(ip.ip.v4, &addr4->sin_addr);
845
846 portptr = &addr4->sin_port;
847 } else if (net_family_is_ipv6(temp->family)) {
848 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
849
850 addrsize = sizeof(struct sockaddr_in6);
851 addr6->sin6_family = AF_INET6;
852 addr6->sin6_port = 0;
853 fill_addr6(ip.ip.v6, &addr6->sin6_addr);
854
855 addr6->sin6_flowinfo = 0;
856 addr6->sin6_scope_id = 0;
857
858 portptr = &addr6->sin6_port;
859 } else {
860 free(temp);
861 return nullptr;
862 }
863
864 if (net_family_is_ipv6(ip.family)) {
865 const int is_dualstack = set_socket_dualstack(temp->sock);
866 LOGGER_DEBUG(log, "Dual-stack socket: %s",
867 is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses");
868 /* multicast local nodes */
869 struct ipv6_mreq mreq;
870 memset(&mreq, 0, sizeof(mreq));
871 mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
872 mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
873 mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
874 mreq.ipv6mr_interface = 0;
875 const int res = setsockopt(temp->sock.socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq));
876
877 int neterror = net_error();
878 const char *strerror = net_new_strerror(neterror);
879
880 if (res < 0) {
881 LOGGER_DEBUG(log, "Failed to activate local multicast membership. (%d, %s)", neterror, strerror);
882 } else {
883 LOGGER_DEBUG(log, "Local multicast group FF02::1 joined successfully. (%d, %s)", neterror, strerror);
884 }
885
886 net_kill_strerror(strerror);
887 }
888
889 /* A hanging program or a different user might block the standard port.
890 * As long as it isn't a parameter coming from the commandline,
891 * try a few ports after it, to see if we can find a "free" one.
892 *
893 * If we go on without binding, the first sendto() automatically binds to
894 * a free port chosen by the system (i.e. anything from 1024 to 65535).
895 *
896 * Returning NULL after bind fails has both advantages and disadvantages:
897 * advantage:
898 * we can rely on getting the port in the range 33445..33450, which
899 * enables us to tell joe user to open their firewall to a small range
900 *
901 * disadvantage:
902 * some clients might not test return of tox_new(), blindly assuming that
903 * it worked ok (which it did previously without a successful bind)
904 */
905 uint16_t port_to_try = port_from;
906 *portptr = net_htons(port_to_try);
907 int tries;
908
909 for (tries = port_from; tries <= port_to; ++tries) {
910 int res = bind(temp->sock.socket, (struct sockaddr *)&addr, addrsize);
911
912 if (!res) {
913 temp->port = *portptr;
914
915 char ip_str[IP_NTOA_LEN];
916 LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip, ip_str, sizeof(ip_str)),
917 net_ntohs(temp->port));
918
919 /* errno isn't reset on success, only set on failure, the failed
920 * binds with parallel clients yield a -EPERM to the outside if
921 * errno isn't cleared here */
922 if (tries > 0) {
923 errno = 0;
924 }
925
926 if (error) {
927 *error = 0;
928 }
929
930 return temp;
931 }
932
933 ++port_to_try;
934
935 if (port_to_try > port_to) {
936 port_to_try = port_from;
937 }
938
939 *portptr = net_htons(port_to_try);
940 }
941
942 char ip_str[IP_NTOA_LEN];
943 int neterror = net_error();
944 const char *strerror = net_new_strerror(neterror);
945 LOGGER_ERROR(log, "Failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", neterror, strerror,
946 ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to);
947 net_kill_strerror(strerror);
948 kill_networking(temp);
949
950 if (error) {
951 *error = 1;
952 }
953
954 return nullptr;
955 }
956
new_networking_no_udp(const Logger * log)957 Networking_Core *new_networking_no_udp(const Logger *log)
958 {
959 if (networking_at_startup() != 0) {
960 return nullptr;
961 }
962
963 /* this is the easiest way to completely disable UDP without changing too much code. */
964 Networking_Core *net = (Networking_Core *)calloc(1, sizeof(Networking_Core));
965
966 if (net == nullptr) {
967 return nullptr;
968 }
969
970 net->log = log;
971
972 return net;
973 }
974
975 /* Function to cleanup networking stuff. */
kill_networking(Networking_Core * net)976 void kill_networking(Networking_Core *net)
977 {
978 if (!net) {
979 return;
980 }
981
982 if (!net_family_is_unspec(net->family)) {
983 /* Socket is initialized, so we close it. */
984 kill_sock(net->sock);
985 }
986
987 free(net);
988 }
989
990
ip_equal(const IP * a,const IP * b)991 bool ip_equal(const IP *a, const IP *b)
992 {
993 if (!a || !b) {
994 return false;
995 }
996
997 /* same family */
998 if (a->family.value == b->family.value) {
999 if (net_family_is_ipv4(a->family) || net_family_is_tcp_ipv4(a->family)) {
1000 struct in_addr addr_a;
1001 struct in_addr addr_b;
1002 fill_addr4(a->ip.v4, &addr_a);
1003 fill_addr4(b->ip.v4, &addr_b);
1004 return addr_a.s_addr == addr_b.s_addr;
1005 }
1006
1007 if (net_family_is_ipv6(a->family) || net_family_is_tcp_ipv6(a->family)) {
1008 return a->ip.v6.uint64[0] == b->ip.v6.uint64[0] &&
1009 a->ip.v6.uint64[1] == b->ip.v6.uint64[1];
1010 }
1011
1012 return false;
1013 }
1014
1015 /* different family: check on the IPv6 one if it is the IPv4 one embedded */
1016 if (net_family_is_ipv4(a->family) && net_family_is_ipv6(b->family)) {
1017 if (ipv6_ipv4_in_v6(b->ip.v6)) {
1018 struct in_addr addr_a;
1019 fill_addr4(a->ip.v4, &addr_a);
1020 return addr_a.s_addr == b->ip.v6.uint32[3];
1021 }
1022 } else if (net_family_is_ipv6(a->family) && net_family_is_ipv4(b->family)) {
1023 if (ipv6_ipv4_in_v6(a->ip.v6)) {
1024 struct in_addr addr_b;
1025 fill_addr4(b->ip.v4, &addr_b);
1026 return a->ip.v6.uint32[3] == addr_b.s_addr;
1027 }
1028 }
1029
1030 return false;
1031 }
1032
ipport_equal(const IP_Port * a,const IP_Port * b)1033 bool ipport_equal(const IP_Port *a, const IP_Port *b)
1034 {
1035 if (!a || !b) {
1036 return false;
1037 }
1038
1039 if (!a->port || (a->port != b->port)) {
1040 return false;
1041 }
1042
1043 return ip_equal(&a->ip, &b->ip);
1044 }
1045
1046 /* nulls out ip */
ip_reset(IP * ip)1047 void ip_reset(IP *ip)
1048 {
1049 if (!ip) {
1050 return;
1051 }
1052
1053 memset(ip, 0, sizeof(IP));
1054 }
1055
1056 /* nulls out ip, sets family according to flag */
ip_init(IP * ip,bool ipv6enabled)1057 void ip_init(IP *ip, bool ipv6enabled)
1058 {
1059 if (!ip) {
1060 return;
1061 }
1062
1063 memset(ip, 0, sizeof(IP));
1064 ip->family = ipv6enabled ? net_family_ipv6 : net_family_ipv4;
1065 }
1066
1067 /* checks if ip is valid */
ip_isset(const IP * ip)1068 bool ip_isset(const IP *ip)
1069 {
1070 if (!ip) {
1071 return false;
1072 }
1073
1074 return !net_family_is_unspec(ip->family);
1075 }
1076
1077 /* checks if ip is valid */
ipport_isset(const IP_Port * ipport)1078 bool ipport_isset(const IP_Port *ipport)
1079 {
1080 if (!ipport) {
1081 return false;
1082 }
1083
1084 if (!ipport->port) {
1085 return false;
1086 }
1087
1088 return ip_isset(&ipport->ip);
1089 }
1090
1091 /* copies an ip structure (careful about direction!) */
ip_copy(IP * target,const IP * source)1092 void ip_copy(IP *target, const IP *source)
1093 {
1094 if (!source || !target) {
1095 return;
1096 }
1097
1098 *target = *source;
1099 }
1100
1101 /* copies an ip_port structure (careful about direction!) */
ipport_copy(IP_Port * target,const IP_Port * source)1102 void ipport_copy(IP_Port *target, const IP_Port *source)
1103 {
1104 if (!source || !target) {
1105 return;
1106 }
1107
1108 *target = *source;
1109 }
1110
1111 /* ip_ntoa
1112 * converts ip into a string
1113 * ip_str must be of length at least IP_NTOA_LEN
1114 *
1115 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
1116 * writes error message into the buffer on error
1117 *
1118 * returns ip_str
1119 */
ip_ntoa(const IP * ip,char * ip_str,size_t length)1120 const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)
1121 {
1122 if (length < IP_NTOA_LEN) {
1123 snprintf(ip_str, length, "Bad buf length");
1124 return ip_str;
1125 }
1126
1127 if (ip) {
1128 if (net_family_is_ipv4(ip->family)) {
1129 /* returns standard quad-dotted notation */
1130 struct in_addr addr;
1131 fill_addr4(ip->ip.v4, &addr);
1132
1133 ip_str[0] = 0;
1134 assert(make_family(ip->family) == AF_INET);
1135 inet_ntop4(&addr, ip_str, length);
1136 } else if (net_family_is_ipv6(ip->family)) {
1137 /* returns hex-groups enclosed into square brackets */
1138 struct in6_addr addr;
1139 fill_addr6(ip->ip.v6, &addr);
1140
1141 ip_str[0] = '[';
1142 assert(make_family(ip->family) == AF_INET6);
1143 inet_ntop6(&addr, &ip_str[1], length - 3);
1144 const size_t len = strlen(ip_str);
1145 ip_str[len] = ']';
1146 ip_str[len + 1] = 0;
1147 } else {
1148 snprintf(ip_str, length, "(IP invalid, family %u)", ip->family.value);
1149 }
1150 } else {
1151 snprintf(ip_str, length, "(IP invalid: NULL)");
1152 }
1153
1154 /* brute force protection against lacking termination */
1155 ip_str[length - 1] = 0;
1156 return ip_str;
1157 }
1158
ip_parse_addr(const IP * ip,char * address,size_t length)1159 bool ip_parse_addr(const IP *ip, char *address, size_t length)
1160 {
1161 if (!address || !ip) {
1162 return false;
1163 }
1164
1165 if (net_family_is_ipv4(ip->family)) {
1166 const struct in_addr *addr = (const struct in_addr *)&ip->ip.v4;
1167 assert(make_family(ip->family) == AF_INET);
1168 return inet_ntop4(addr, address, length) != nullptr;
1169 }
1170
1171 if (net_family_is_ipv6(ip->family)) {
1172 const struct in6_addr *addr = (const struct in6_addr *)&ip->ip.v6;
1173 assert(make_family(ip->family) == AF_INET6);
1174 return inet_ntop6(addr, address, length) != nullptr;
1175 }
1176
1177 return false;
1178 }
1179
addr_parse_ip(const char * address,IP * to)1180 bool addr_parse_ip(const char *address, IP *to)
1181 {
1182 if (!address || !to) {
1183 return false;
1184 }
1185
1186 struct in_addr addr4;
1187
1188 if (inet_pton4(address, &addr4) == 1) {
1189 to->family = net_family_ipv4;
1190 get_ip4(&to->ip.v4, &addr4);
1191 return true;
1192 }
1193
1194 struct in6_addr addr6;
1195
1196 if (inet_pton6(address, &addr6) == 1) {
1197 to->family = net_family_ipv6;
1198 get_ip6(&to->ip.v6, &addr6);
1199 return true;
1200 }
1201
1202 return false;
1203 }
1204
addr_resolve(const char * address,IP * to,IP * extra)1205 int addr_resolve(const char *address, IP *to, IP *extra)
1206 {
1207 if (!address || !to) {
1208 return 0;
1209 }
1210
1211 Family tox_family = to->family;
1212 int family = make_family(tox_family);
1213
1214 struct addrinfo *server = nullptr;
1215 struct addrinfo *walker = nullptr;
1216 struct addrinfo hints;
1217 int rc;
1218 int result = 0;
1219 int done = 0;
1220
1221 memset(&hints, 0, sizeof(hints));
1222 hints.ai_family = family;
1223 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
1224
1225 if (networking_at_startup() != 0) {
1226 return 0;
1227 }
1228
1229 rc = getaddrinfo(address, nullptr, &hints, &server);
1230
1231 // Lookup failed.
1232 if (rc != 0) {
1233 return 0;
1234 }
1235
1236 IP ip4;
1237 ip_init(&ip4, 0); // ipv6enabled = 0
1238 IP ip6;
1239 ip_init(&ip6, 1); // ipv6enabled = 1
1240
1241 for (walker = server; (walker != nullptr) && !done; walker = walker->ai_next) {
1242 switch (walker->ai_family) {
1243 case AF_INET:
1244 if (walker->ai_family == family) { /* AF_INET requested, done */
1245 struct sockaddr_in *addr = (struct sockaddr_in *)(void *)walker->ai_addr;
1246 get_ip4(&to->ip.v4, &addr->sin_addr);
1247 result = TOX_ADDR_RESOLVE_INET;
1248 done = 1;
1249 } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */
1250 struct sockaddr_in *addr = (struct sockaddr_in *)(void *)walker->ai_addr;
1251 get_ip4(&ip4.ip.v4, &addr->sin_addr);
1252 result |= TOX_ADDR_RESOLVE_INET;
1253 }
1254
1255 break; /* switch */
1256
1257 case AF_INET6:
1258 if (walker->ai_family == family) { /* AF_INET6 requested, done */
1259 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
1260 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)walker->ai_addr;
1261 get_ip6(&to->ip.v6, &addr->sin6_addr);
1262 result = TOX_ADDR_RESOLVE_INET6;
1263 done = 1;
1264 }
1265 } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */
1266 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
1267 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)walker->ai_addr;
1268 get_ip6(&ip6.ip.v6, &addr->sin6_addr);
1269 result |= TOX_ADDR_RESOLVE_INET6;
1270 }
1271 }
1272
1273 break; /* switch */
1274 }
1275 }
1276
1277 if (family == AF_UNSPEC) {
1278 if (result & TOX_ADDR_RESOLVE_INET6) {
1279 ip_copy(to, &ip6);
1280
1281 if ((result & TOX_ADDR_RESOLVE_INET) && (extra != nullptr)) {
1282 ip_copy(extra, &ip4);
1283 }
1284 } else if (result & TOX_ADDR_RESOLVE_INET) {
1285 ip_copy(to, &ip4);
1286 } else {
1287 result = 0;
1288 }
1289 }
1290
1291 freeaddrinfo(server);
1292 return result;
1293 }
1294
addr_resolve_or_parse_ip(const char * address,IP * to,IP * extra)1295 bool addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
1296 {
1297 if (!addr_resolve(address, to, extra)) {
1298 if (!addr_parse_ip(address, to)) {
1299 return false;
1300 }
1301 }
1302
1303 return true;
1304 }
1305
net_connect(Socket sock,IP_Port ip_port)1306 int net_connect(Socket sock, IP_Port ip_port)
1307 {
1308 struct sockaddr_storage addr = {0};
1309 size_t addrsize;
1310
1311 if (net_family_is_ipv4(ip_port.ip.family)) {
1312 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
1313
1314 addrsize = sizeof(struct sockaddr_in);
1315 addr4->sin_family = AF_INET;
1316 fill_addr4(ip_port.ip.ip.v4, &addr4->sin_addr);
1317 addr4->sin_port = ip_port.port;
1318 } else if (net_family_is_ipv6(ip_port.ip.family)) {
1319 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
1320
1321 addrsize = sizeof(struct sockaddr_in6);
1322 addr6->sin6_family = AF_INET6;
1323 fill_addr6(ip_port.ip.ip.v6, &addr6->sin6_addr);
1324 addr6->sin6_port = ip_port.port;
1325 } else {
1326 return 0;
1327 }
1328
1329 return connect(sock.socket, (struct sockaddr *)&addr, addrsize);
1330 }
1331
net_getipport(const char * node,IP_Port ** res,int tox_type)1332 int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
1333 {
1334 struct addrinfo *infos;
1335 int ret = getaddrinfo(node, nullptr, nullptr, &infos);
1336 *res = nullptr;
1337
1338 if (ret != 0) {
1339 return -1;
1340 }
1341
1342 // Used to avoid malloc parameter overflow
1343 const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
1344 int type = make_socktype(tox_type);
1345 struct addrinfo *cur;
1346 size_t count = 0;
1347
1348 for (cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
1349 if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1350 continue;
1351 }
1352
1353 if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
1354 continue;
1355 }
1356
1357 ++count;
1358 }
1359
1360 assert(count <= max_count);
1361
1362 if (count == 0) {
1363 freeaddrinfo(infos);
1364 return 0;
1365 }
1366
1367 *res = (IP_Port *)malloc(sizeof(IP_Port) * count);
1368
1369 if (*res == nullptr) {
1370 freeaddrinfo(infos);
1371 return -1;
1372 }
1373
1374 IP_Port *ip_port = *res;
1375
1376 for (cur = infos; cur != nullptr; cur = cur->ai_next) {
1377 if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
1378 continue;
1379 }
1380
1381 if (cur->ai_family == AF_INET) {
1382 struct sockaddr_in *addr = (struct sockaddr_in *)(void *)cur->ai_addr;
1383 memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));
1384 } else if (cur->ai_family == AF_INET6) {
1385 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)cur->ai_addr;
1386 memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));
1387 } else {
1388 continue;
1389 }
1390
1391 const Family *const family = make_tox_family(cur->ai_family);
1392 assert(family != nullptr);
1393
1394 if (family == nullptr) {
1395 freeaddrinfo(infos);
1396 return -1;
1397 }
1398
1399 ip_port->ip.family = *family;
1400
1401 ++ip_port;
1402 }
1403
1404 freeaddrinfo(infos);
1405
1406 return count;
1407 }
1408
net_freeipport(IP_Port * ip_ports)1409 void net_freeipport(IP_Port *ip_ports)
1410 {
1411 free(ip_ports);
1412 }
1413
bind_to_port(Socket sock,Family family,uint16_t port)1414 bool bind_to_port(Socket sock, Family family, uint16_t port)
1415 {
1416 struct sockaddr_storage addr = {0};
1417 size_t addrsize;
1418
1419 if (net_family_is_ipv4(family)) {
1420 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
1421
1422 addrsize = sizeof(struct sockaddr_in);
1423 addr4->sin_family = AF_INET;
1424 addr4->sin_port = net_htons(port);
1425 } else if (net_family_is_ipv6(family)) {
1426 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
1427
1428 addrsize = sizeof(struct sockaddr_in6);
1429 addr6->sin6_family = AF_INET6;
1430 addr6->sin6_port = net_htons(port);
1431 } else {
1432 return false;
1433 }
1434
1435 return bind(sock.socket, (struct sockaddr *)&addr, addrsize) == 0;
1436 }
1437
net_socket(Family domain,int type,int protocol)1438 Socket net_socket(Family domain, int type, int protocol)
1439 {
1440 const int platform_domain = make_family(domain);
1441 const int platform_type = make_socktype(type);
1442 const int platform_prot = make_proto(protocol);
1443 const Socket sock = {(int)socket(platform_domain, platform_type, platform_prot)};
1444 return sock;
1445 }
1446
net_send(Socket sock,const void * buf,size_t len)1447 int net_send(Socket sock, const void *buf, size_t len)
1448 {
1449 return send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL);
1450 }
1451
net_recv(Socket sock,void * buf,size_t len)1452 int net_recv(Socket sock, void *buf, size_t len)
1453 {
1454 return recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL);
1455 }
1456
net_listen(Socket sock,int backlog)1457 int net_listen(Socket sock, int backlog)
1458 {
1459 return listen(sock.socket, backlog);
1460 }
1461
net_accept(Socket sock)1462 Socket net_accept(Socket sock)
1463 {
1464 const Socket newsock = {accept(sock.socket, nullptr, nullptr)};
1465 return newsock;
1466 }
1467
net_socket_data_recv_buffer(Socket sock)1468 size_t net_socket_data_recv_buffer(Socket sock)
1469 {
1470 #ifdef OS_WIN32
1471 unsigned long count = 0;
1472 ioctlsocket(sock.socket, FIONREAD, &count);
1473 #else
1474 int count = 0;
1475 ioctl(sock.socket, FIONREAD, &count);
1476 #endif
1477
1478 return count;
1479 }
1480
net_htonl(uint32_t hostlong)1481 uint32_t net_htonl(uint32_t hostlong)
1482 {
1483 return htonl(hostlong);
1484 }
1485
net_htons(uint16_t hostshort)1486 uint16_t net_htons(uint16_t hostshort)
1487 {
1488 return htons(hostshort);
1489 }
1490
net_ntohl(uint32_t hostlong)1491 uint32_t net_ntohl(uint32_t hostlong)
1492 {
1493 return ntohl(hostlong);
1494 }
1495
net_ntohs(uint16_t hostshort)1496 uint16_t net_ntohs(uint16_t hostshort)
1497 {
1498 return ntohs(hostshort);
1499 }
1500
net_pack_u16(uint8_t * bytes,uint16_t v)1501 size_t net_pack_u16(uint8_t *bytes, uint16_t v)
1502 {
1503 bytes[0] = (v >> 8) & 0xff;
1504 bytes[1] = v & 0xff;
1505 return sizeof(v);
1506 }
1507
net_pack_u32(uint8_t * bytes,uint32_t v)1508 size_t net_pack_u32(uint8_t *bytes, uint32_t v)
1509 {
1510 uint8_t *p = bytes;
1511 p += net_pack_u16(p, (v >> 16) & 0xffff);
1512 p += net_pack_u16(p, v & 0xffff);
1513 return p - bytes;
1514 }
1515
net_pack_u64(uint8_t * bytes,uint64_t v)1516 size_t net_pack_u64(uint8_t *bytes, uint64_t v)
1517 {
1518 uint8_t *p = bytes;
1519 p += net_pack_u32(p, (v >> 32) & 0xffffffff);
1520 p += net_pack_u32(p, v & 0xffffffff);
1521 return p - bytes;
1522 }
1523
net_unpack_u16(const uint8_t * bytes,uint16_t * v)1524 size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v)
1525 {
1526 uint8_t hi = bytes[0];
1527 uint8_t lo = bytes[1];
1528 *v = ((uint16_t)hi << 8) | lo;
1529 return sizeof(*v);
1530 }
1531
net_unpack_u32(const uint8_t * bytes,uint32_t * v)1532 size_t net_unpack_u32(const uint8_t *bytes, uint32_t *v)
1533 {
1534 const uint8_t *p = bytes;
1535 uint16_t hi;
1536 uint16_t lo;
1537 p += net_unpack_u16(p, &hi);
1538 p += net_unpack_u16(p, &lo);
1539 *v = ((uint32_t)hi << 16) | lo;
1540 return p - bytes;
1541 }
1542
net_unpack_u64(const uint8_t * bytes,uint64_t * v)1543 size_t net_unpack_u64(const uint8_t *bytes, uint64_t *v)
1544 {
1545 const uint8_t *p = bytes;
1546 uint32_t hi;
1547 uint32_t lo;
1548 p += net_unpack_u32(p, &hi);
1549 p += net_unpack_u32(p, &lo);
1550 *v = ((uint64_t)hi << 32) | lo;
1551 return p - bytes;
1552 }
1553
ipv6_ipv4_in_v6(IP6 a)1554 bool ipv6_ipv4_in_v6(IP6 a)
1555 {
1556 return a.uint64[0] == 0 && a.uint32[2] == net_htonl(0xffff);
1557 }
1558
net_error(void)1559 int net_error(void)
1560 {
1561 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1562 return WSAGetLastError();
1563 #else
1564 return errno;
1565 #endif
1566 }
1567
net_new_strerror(int error)1568 const char *net_new_strerror(int error)
1569 {
1570 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1571 char *str = nullptr;
1572 // Windows API is weird. The 5th function arg is of char* type, but we
1573 // have to pass char** so that it could assign new memory block to our
1574 // pointer, so we have to cast our char** to char* for the compilation
1575 // not to fail (otherwise it would fail to find a variant of this function
1576 // accepting char** as the 5th arg) and Windows inside casts it back
1577 // to char** to do the assignment. So no, this cast you see here, although
1578 // it looks weird, is not a mistake.
1579 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
1580 error, 0, (char *)&str, 0, nullptr);
1581 return str;
1582 #else
1583 return strerror(error);
1584 #endif
1585 }
1586
net_kill_strerror(const char * strerror)1587 void net_kill_strerror(const char *strerror)
1588 {
1589 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
1590 LocalFree((char *)strerror);
1591 #endif
1592 }
1593