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