summaryrefslogtreecommitdiff
path: root/protocols/Tox/libtox/src/toxcore/network.c
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-07-24 16:44:24 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-07-24 16:44:24 +0300
commite55d071e5485a937efd427d159b76c208cccdcce (patch)
tree48d09dc5cf1df2581fd6471b5ccf1560015fa3a4 /protocols/Tox/libtox/src/toxcore/network.c
parentf36629f67153bc500c828cf51de31988122a1024 (diff)
fixes #3118 (Update toxcore to 0.2.18)
Diffstat (limited to 'protocols/Tox/libtox/src/toxcore/network.c')
-rw-r--r--protocols/Tox/libtox/src/toxcore/network.c1041
1 files changed, 602 insertions, 439 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c
index 8569fc17e5..35893b73dc 100644
--- a/protocols/Tox/libtox/src/toxcore/network.c
+++ b/protocols/Tox/libtox/src/toxcore/network.c
@@ -92,16 +92,11 @@
#include <sodium.h>
#endif
+#include "ccompat.h"
#include "logger.h"
#include "mono_time.h"
#include "util.h"
-//!TOKSTYLE-
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-#include "../testing/fuzzing/fuzz_adapter.h"
-#endif
-//!TOKSTYLE+
-
// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
#if !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0
@@ -113,6 +108,12 @@
#endif
#endif
+static_assert(sizeof(IP4) == SIZE_IP4, "IP4 size must be 4");
+
+// TODO(iphydf): Stop relying on this. We memcpy this struct (and IP4 above)
+// into packets but really should be serialising it properly.
+static_assert(sizeof(IP6) == SIZE_IP6, "IP6 size must be 16");
+
#if !defined(OS_WIN32)
static bool should_ignore_recv_error(int err)
@@ -120,21 +121,30 @@ static bool should_ignore_recv_error(int err)
return err == EWOULDBLOCK;
}
+static bool should_ignore_connect_error(int err)
+{
+ return err == EWOULDBLOCK || err == EINPROGRESS;
+}
+
+non_null()
static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)
{
return inet_ntop(AF_INET, addr, buf, bufsize);
}
+non_null()
static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t bufsize)
{
return inet_ntop(AF_INET6, addr, buf, bufsize);
}
+non_null()
static int inet_pton4(const char *addrString, struct in_addr *addrbuf)
{
return inet_pton(AF_INET, addrString, addrbuf);
}
+non_null()
static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
{
return inet_pton(AF_INET6, addrString, addrbuf);
@@ -152,6 +162,12 @@ static bool should_ignore_recv_error(int err)
return err == WSAEWOULDBLOCK || err == WSAECONNRESET;
}
+static bool should_ignore_connect_error(int err)
+{
+ return err == WSAEWOULDBLOCK || err == WSAEINPROGRESS;
+}
+
+non_null()
static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)
{
struct sockaddr_in saddr = {0};
@@ -168,6 +184,7 @@ static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufs
return buf;
}
+non_null()
static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t bufsize)
{
struct sockaddr_in6 saddr = {0};
@@ -184,6 +201,7 @@ static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t buf
return buf;
}
+non_null()
static int inet_pton4(const char *addrString, struct in_addr *addrbuf)
{
struct sockaddr_in saddr = {0};
@@ -199,6 +217,7 @@ static int inet_pton4(const char *addrString, struct in_addr *addrbuf)
return 1;
}
+non_null()
static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
{
struct sockaddr_in6 saddr = {0};
@@ -221,7 +240,6 @@ static_assert(TOX_INET6_ADDRSTRLEN >= INET6_ADDRSTRLEN,
static_assert(TOX_INET_ADDRSTRLEN >= INET_ADDRSTRLEN,
"TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)");
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
static int make_proto(int proto)
{
switch (proto) {
@@ -249,7 +267,6 @@ static int make_socktype(int type)
return type;
}
}
-#endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
static int make_family(Family tox_family)
{
@@ -268,42 +285,58 @@ static int make_family(Family tox_family)
}
}
+static const Family family_unspec = {TOX_AF_UNSPEC};
+static const Family family_ipv4 = {TOX_AF_INET};
+static const Family family_ipv6 = {TOX_AF_INET6};
+static const Family family_tcp_server = {TCP_SERVER_FAMILY};
+static const Family family_tcp_client = {TCP_CLIENT_FAMILY};
+static const Family family_tcp_ipv4 = {TCP_INET};
+static const Family family_tcp_ipv6 = {TCP_INET6};
+static const Family family_tox_tcp_ipv4 = {TOX_TCP_INET};
+static const Family family_tox_tcp_ipv6 = {TOX_TCP_INET6};
+
static const Family *make_tox_family(int family)
{
switch (family) {
case AF_INET:
- return &net_family_ipv4;
+ return &family_ipv4;
case AF_INET6:
- return &net_family_ipv6;
+ return &family_ipv6;
case AF_UNSPEC:
- return &net_family_unspec;
+ return &family_unspec;
default:
return nullptr;
}
}
+non_null()
static void get_ip4(IP4 *result, const struct in_addr *addr)
{
+ static_assert(sizeof(result->uint32) == sizeof(addr->s_addr),
+ "Tox and operating system don't agree on size of IPv4 addresses");
result->uint32 = addr->s_addr;
}
+non_null()
static void get_ip6(IP6 *result, const struct in6_addr *addr)
{
- assert(sizeof(result->uint8) == sizeof(addr->s6_addr));
+ static_assert(sizeof(result->uint8) == sizeof(addr->s6_addr),
+ "Tox and operating system don't agree on size of IPv6 addresses");
memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8));
}
+non_null()
static void fill_addr4(const IP4 *ip, struct in_addr *addr)
{
addr->s_addr = ip->uint32;
}
+non_null()
static void fill_addr6(const IP6 *ip, struct in6_addr *addr)
{
- assert(sizeof(ip->uint8) == sizeof(addr->s6_addr));
memcpy(addr->s6_addr, ip->uint8, sizeof(ip->uint8));
}
@@ -311,6 +344,9 @@ static void fill_addr6(const IP6 *ip, struct in6_addr *addr)
#define INADDR_LOOPBACK 0x7f000001
#endif
+static const IP empty_ip = {{0}};
+const IP_Port empty_ip_port = {{{0}}};
+
const IP4 ip4_broadcast = { INADDR_BROADCAST };
const IP6 ip6_broadcast = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
@@ -326,7 +362,12 @@ IP4 get_ip4_loopback(void)
IP6 get_ip6_loopback(void)
{
IP6 loopback;
+#ifdef ESP_PLATFORM
+ loopback = empty_ip_port.ip.ip.v6;
+ loopback.uint8[15] = 1;
+#else
get_ip6(&loopback, &in6addr_loopback);
+#endif
return loopback;
}
@@ -336,134 +377,262 @@ IP6 get_ip6_loopback(void)
const Socket net_invalid_socket = { (int)INVALID_SOCKET };
-const Family net_family_unspec = {TOX_AF_UNSPEC};
-const Family net_family_ipv4 = {TOX_AF_INET};
-const Family net_family_ipv6 = {TOX_AF_INET6};
-const Family net_family_tcp_family = {TCP_FAMILY};
-const Family net_family_tcp_onion = {TCP_ONION_FAMILY};
-const Family net_family_tcp_ipv4 = {TCP_INET};
-const Family net_family_tcp_ipv6 = {TCP_INET6};
-const Family net_family_tox_tcp_ipv4 = {TOX_TCP_INET};
-const Family net_family_tox_tcp_ipv6 = {TOX_TCP_INET6};
+Family net_family_unspec()
+{
+ return family_unspec;
+}
+
+Family net_family_ipv4()
+{
+ return family_ipv4;
+}
+
+Family net_family_ipv6()
+{
+ return family_ipv6;
+}
+
+Family net_family_tcp_server()
+{
+ return family_tcp_server;
+}
+
+Family net_family_tcp_client()
+{
+ return family_tcp_client;
+}
+
+Family net_family_tcp_ipv4()
+{
+ return family_tcp_ipv4;
+}
+
+Family net_family_tcp_ipv6()
+{
+ return family_tcp_ipv6;
+}
+
+Family net_family_tox_tcp_ipv4()
+{
+ return family_tox_tcp_ipv4;
+}
+
+Family net_family_tox_tcp_ipv6()
+{
+ return family_tox_tcp_ipv6;
+}
bool net_family_is_unspec(Family family)
{
- return family.value == net_family_unspec.value;
+ return family.value == family_unspec.value;
}
bool net_family_is_ipv4(Family family)
{
- return family.value == net_family_ipv4.value;
+ return family.value == family_ipv4.value;
}
bool net_family_is_ipv6(Family family)
{
- return family.value == net_family_ipv6.value;
+ return family.value == family_ipv6.value;
}
-bool net_family_is_tcp_family(Family family)
+bool net_family_is_tcp_server(Family family)
{
- return family.value == net_family_tcp_family.value;
+ return family.value == family_tcp_server.value;
}
-bool net_family_is_tcp_onion(Family family)
+bool net_family_is_tcp_client(Family family)
{
- return family.value == net_family_tcp_onion.value;
+ return family.value == family_tcp_client.value;
}
bool net_family_is_tcp_ipv4(Family family)
{
- return family.value == net_family_tcp_ipv4.value;
+ return family.value == family_tcp_ipv4.value;
}
bool net_family_is_tcp_ipv6(Family family)
{
- return family.value == net_family_tcp_ipv6.value;
+ return family.value == family_tcp_ipv6.value;
}
bool net_family_is_tox_tcp_ipv4(Family family)
{
- return family.value == net_family_tox_tcp_ipv4.value;
+ return family.value == family_tox_tcp_ipv4.value;
}
bool net_family_is_tox_tcp_ipv6(Family family)
{
- return family.value == net_family_tox_tcp_ipv6.value;
+ return family.value == family_tox_tcp_ipv6.value;
}
bool sock_valid(Socket sock)
{
- return sock.socket != net_invalid_socket.socket;
+ return sock.sock != net_invalid_socket.sock;
}
-/** Close the socket.
- */
-void kill_sock(Socket sock)
+struct Network_Addr {
+ struct sockaddr_storage addr;
+ size_t size;
+};
+
+non_null()
+static int sys_close(void *obj, int sock)
+{
+#if defined(OS_WIN32)
+ return closesocket(sock);
+#else // !OS_WIN32
+ return close(sock);
+#endif
+}
+
+non_null()
+static int sys_accept(void *obj, int sock)
+{
+ return accept(sock, nullptr, nullptr);
+}
+
+non_null()
+static int sys_bind(void *obj, int sock, const Network_Addr *addr)
+{
+ return bind(sock, (const struct sockaddr *)&addr->addr, addr->size);
+}
+
+non_null()
+static int sys_listen(void *obj, int sock, int backlog)
+{
+ return listen(sock, backlog);
+}
+
+non_null()
+static int sys_recvbuf(void *obj, int sock)
{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return;
-#else
#ifdef OS_WIN32
- closesocket(sock.socket);
+ u_long count = 0;
+ ioctlsocket(sock, FIONREAD, &count);
#else
- close(sock.socket);
-#endif /* OS_WIN32 */
-#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+ int count = 0;
+ ioctl(sock, FIONREAD, &count);
+#endif
+
+ return count;
}
-bool set_socket_nonblock(Socket sock)
+non_null()
+static int sys_recv(void *obj, int sock, uint8_t *buf, size_t len)
+{
+ return recv(sock, (char *)buf, len, MSG_NOSIGNAL);
+}
+
+non_null()
+static int sys_send(void *obj, int sock, const uint8_t *buf, size_t len)
+{
+ return send(sock, (const char *)buf, len, MSG_NOSIGNAL);
+}
+
+non_null()
+static int sys_sendto(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) {
+ return sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size);
+}
+
+non_null()
+static int sys_recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) {
+ socklen_t size = addr->size;
+ const int ret = recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size);
+ addr->size = size;
+ return ret;
+}
+
+non_null()
+static int sys_socket(void *obj, int domain, int type, int proto)
+{
+ return (int)socket(domain, type, proto);
+}
+
+non_null()
+static int sys_socket_nonblock(void *obj, int sock, bool nonblock)
{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return true;
-#else
#ifdef OS_WIN32
- u_long mode = 1;
- return ioctlsocket(sock.socket, FIONBIO, &mode) == 0;
+ u_long mode = nonblock ? 1 : 0;
+ return ioctlsocket(sock, FIONBIO, &mode);
#else
- return fcntl(sock.socket, F_SETFL, O_NONBLOCK, 1) == 0;
+ return fcntl(sock, F_SETFL, O_NONBLOCK, nonblock ? 1 : 0);
#endif /* OS_WIN32 */
-#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
-bool set_socket_nosigpipe(Socket sock)
+non_null()
+static int sys_getsockopt(void *obj, int sock, int level, int optname, void *optval, size_t *optlen)
{
-#if defined(__APPLE__)
- int set = 1;
- return setsockopt(sock.socket, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set, sizeof(int)) == 0;
-#else
- return true;
-#endif
+ socklen_t len = *optlen;
+ const int ret = getsockopt(sock, level, optname, optval, &len);
+ *optlen = len;
+ return ret;
}
-bool set_socket_reuseaddr(Socket sock)
+non_null()
+static int sys_setsockopt(void *obj, int sock, int level, int optname, const void *optval, size_t optlen)
{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return false;
-#else
- int set = 1;
- return setsockopt(sock.socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0;
-#endif
+ return setsockopt(sock, level, optname, optval, optlen);
}
-bool set_socket_dualstack(Socket sock)
+static const Network_Funcs system_network_funcs = {
+ sys_close,
+ sys_accept,
+ sys_bind,
+ sys_listen,
+ sys_recvbuf,
+ sys_recv,
+ sys_recvfrom,
+ sys_send,
+ sys_sendto,
+ sys_socket,
+ sys_socket_nonblock,
+ sys_getsockopt,
+ sys_setsockopt,
+};
+static const Network system_network_obj = {&system_network_funcs};
+
+const Network *system_network(void)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return false;
-#else
- int ipv6only = 0;
- socklen_t optsize = sizeof(ipv6only);
- int res = getsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optsize);
+ if ((true)) {
+ return nullptr;
+ }
+#endif
+#ifdef OS_WIN32
+ WSADATA wsaData;
- if ((res == 0) && (ipv6only == 0)) {
- return true;
+ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
+ return nullptr;
}
+#endif
+ return &system_network_obj;
+}
- ipv6only = 0;
- return setsockopt(sock.socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6only, sizeof(ipv6only)) == 0;
+#if 0
+/* TODO(iphydf): Call this from functions that use `system_network()`. */
+void system_network_deinit(const Network *ns)
+{
+#ifdef OS_WIN32
+ WSACleanup();
+#endif
+}
#endif
+
+non_null()
+static int net_setsockopt(const Network *ns, Socket sock, int level, int optname, const void *optval, size_t optlen)
+{
+ return ns->funcs->setsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
}
+non_null()
+static int net_getsockopt(const Network *ns, Socket sock, int level, int optname, void *optval, size_t *optlen)
+{
+ return ns->funcs->getsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
+}
+non_null()
static uint32_t data_0(uint16_t buflen, const uint8_t *buffer)
{
uint32_t data = 0;
@@ -474,43 +643,136 @@ static uint32_t data_0(uint16_t buflen, const uint8_t *buffer)
return data;
}
+non_null()
static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)
{
uint32_t data = 0;
- if (buflen > 7) {
+ if (buflen > 8) {
net_unpack_u32(buffer + 5, &data);
}
return data;
}
+non_null()
static void loglogdata(const Logger *log, const char *message, const uint8_t *buffer,
uint16_t buflen, const IP_Port *ip_port, long res)
{
- char ip_str[IP_NTOA_LEN];
-
if (res < 0) { /* Windows doesn't necessarily know `%zu` */
- int error = net_error();
+ Ip_Ntoa ip_str;
+ const int error = net_error();
char *strerror = net_new_strerror(error);
LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
buffer[0], message, min_u16(buflen, 999), 'E',
- ip_ntoa(&ip_port->ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port->port), error,
+ net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error,
strerror, data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
net_kill_strerror(strerror);
} else if ((res > 0) && ((size_t)res <= buflen)) {
+ Ip_Ntoa ip_str;
LOGGER_TRACE(log, "[%2u] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
buffer[0], message, min_u16(res, 999), (size_t)res < buflen ? '<' : '=',
- ip_ntoa(&ip_port->ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port->port), 0, "OK",
+ net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
} else { /* empty or overwrite */
+ Ip_Ntoa ip_str;
LOGGER_TRACE(log, "[%2u] %s %lu%c%u %s:%u (%u: %s) | %08x%08x...%02x",
- buffer[0], message, res, !res ? '!' : '>', buflen,
- ip_ntoa(&ip_port->ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port->port), 0, "OK",
+ buffer[0], message, res, res == 0 ? '!' : '>', buflen,
+ net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
}
}
+int net_send(const Network *ns, const Logger *log,
+ Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port)
+{
+ const int res = ns->funcs->send(ns->obj, sock.sock, buf, len);
+ loglogdata(log, "T=>", buf, len, ip_port, res);
+ return res;
+}
+
+non_null()
+static int net_sendto(
+ const Network *ns,
+ Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr, const IP_Port *ip_port)
+{
+ return ns->funcs->sendto(ns->obj, sock.sock, buf, len, addr);
+}
+
+int net_recv(const Network *ns, const Logger *log,
+ Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port)
+{
+ const int res = ns->funcs->recv(ns->obj, sock.sock, buf, len);
+ loglogdata(log, "=>T", buf, len, ip_port, res);
+ return res;
+}
+
+non_null()
+static int net_recvfrom(const Network *ns,
+ Socket sock, uint8_t *buf, size_t len, Network_Addr *addr)
+{
+ return ns->funcs->recvfrom(ns->obj, sock.sock, buf, len, addr);
+}
+
+int net_listen(const Network *ns, Socket sock, int backlog)
+{
+ return ns->funcs->listen(ns->obj, sock.sock, backlog);
+}
+
+non_null()
+static int net_bind(const Network *ns, Socket sock, const Network_Addr *addr)
+{
+ return ns->funcs->bind(ns->obj, sock.sock, addr);
+}
+
+Socket net_accept(const Network *ns, Socket sock)
+{
+ const Socket newsock = {ns->funcs->accept(ns->obj, sock.sock)};
+ return newsock;
+}
+
+/** Close the socket. */
+void kill_sock(const Network *ns, Socket sock)
+{
+ ns->funcs->close(ns->obj, sock.sock);
+}
+
+bool set_socket_nonblock(const Network *ns, Socket sock)
+{
+ return ns->funcs->socket_nonblock(ns->obj, sock.sock, true) == 0;
+}
+
+bool set_socket_nosigpipe(const Network *ns, Socket sock)
+{
+#if defined(__APPLE__)
+ int set = 1;
+ return net_setsockopt(ns, sock, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(int)) == 0;
+#else
+ return true;
+#endif
+}
+
+bool set_socket_reuseaddr(const Network *ns, Socket sock)
+{
+ int set = 1;
+ return net_setsockopt(ns, sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) == 0;
+}
+
+bool set_socket_dualstack(const Network *ns, Socket sock)
+{
+ int ipv6only = 0;
+ size_t optsize = sizeof(ipv6only);
+ const int res = net_getsockopt(ns, sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize);
+
+ if ((res == 0) && (ipv6only == 0)) {
+ return true;
+ }
+
+ ipv6only = 0;
+ return net_setsockopt(ns, sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0;
+}
+
+
typedef struct Packet_Handler {
packet_handler_cb *function;
void *object;
@@ -519,6 +781,7 @@ typedef struct Packet_Handler {
struct Networking_Core {
const Logger *log;
Packet_Handler packethandlers[256];
+ const Network *ns;
Family family;
uint16_t port;
@@ -543,6 +806,12 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
{
IP_Port ipp_copy = *ip_port;
+ if (net_family_is_unspec(ip_port->ip.family)) {
+ // TODO(iphydf): Make this an error. Currently this fails sometimes when
+ // called from DHT.c:do_ping_and_sendnode_requests.
+ return -1;
+ }
+
if (net_family_is_unspec(net->family)) { /* Socket not initialized */
// TODO(iphydf): Make this an error. Currently, the onion client calls
// this via DHT getnodes.
@@ -570,25 +839,23 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
ip6.uint32[2] = net_htonl(0xFFFF);
ip6.uint32[3] = ipp_copy.ip.ip.v4.uint32;
- ipp_copy.ip.family = net_family_ipv6;
+ ipp_copy.ip.family = net_family_ipv6();
ipp_copy.ip.ip.v6 = ip6;
}
- struct sockaddr_storage addr;
-
- size_t addrsize;
+ Network_Addr addr;
if (net_family_is_ipv4(ipp_copy.ip.family)) {
- struct sockaddr_in *const addr4 = (struct sockaddr_in *)&addr;
+ struct sockaddr_in *const addr4 = (struct sockaddr_in *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in);
+ addr.size = sizeof(struct sockaddr_in);
addr4->sin_family = AF_INET;
addr4->sin_port = ipp_copy.port;
fill_addr4(&ipp_copy.ip.ip.v4, &addr4->sin_addr);
} else if (net_family_is_ipv6(ipp_copy.ip.family)) {
- struct sockaddr_in6 *const addr6 = (struct sockaddr_in6 *)&addr;
+ struct sockaddr_in6 *const addr6 = (struct sockaddr_in6 *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in6);
+ addr.size = sizeof(struct sockaddr_in6);
addr6->sin6_family = AF_INET6;
addr6->sin6_port = ipp_copy.port;
fill_addr6(&ipp_copy.ip.ip.v6, &addr6->sin6_addr);
@@ -596,21 +863,12 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
addr6->sin6_flowinfo = 0;
addr6->sin6_scope_id = 0;
} else {
- // TODO(iphydf): Make this an error. Currently this fails sometimes when
- // called from DHT.c:do_ping_and_sendnode_requests.
- LOGGER_WARNING(net->log, "unknown address type: %d", ipp_copy.ip.family.value);
+ LOGGER_ERROR(net->log, "unknown address type: %d", ipp_copy.ip.family.value);
return -1;
}
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- const long res = fuzz_sendto(net->sock.socket, (const char *)packet.data, packet.length, 0,
- (struct sockaddr *)&addr, addrsize);
-#else
- const long res = sendto(net->sock.socket, (const char *)packet.data, packet.length, 0,
- (struct sockaddr *)&addr, addrsize);
-#endif
-
- loglogdata(net->log, "O=>", packet.data, packet.length, &ipp_copy, res);
+ const long res = net_sendto(net->ns, net->sock, packet.data, packet.length, &addr, &ipp_copy);
+ loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res);
assert(res <= INT_MAX);
return (int)res;
@@ -627,34 +885,27 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t
return send_packet(net, ip_port, packet);
}
-/** Function to receive data
- * ip and port of sender is put into ip_port.
- * Packet data is put into data.
- * Packet length is put into length.
+/** @brief Function to receive data
+ * ip and port of sender is put into ip_port.
+ * Packet data is put into data.
+ * Packet length is put into length.
*/
-static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
+non_null()
+static int receivepacket(const Network *ns, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
{
memset(ip_port, 0, sizeof(IP_Port));
- struct sockaddr_storage addr;
-#ifdef OS_WIN32
- int addrlen = sizeof(addr);
-#else
- socklen_t addrlen = sizeof(addr);
-#endif
+ Network_Addr addr = {{0}};
+ addr.size = sizeof(addr.addr);
*length = 0;
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- int fail_or_len = fuzz_recvfrom(sock.socket, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
-#else
- int fail_or_len = recvfrom(sock.socket, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
-#endif
+ const int fail_or_len = net_recvfrom(ns, sock, data, MAX_UDP_PACKET_SIZE, &addr);
if (fail_or_len < 0) {
- int error = net_error();
+ const int error = net_error();
if (!should_ignore_recv_error(error)) {
char *strerror = net_new_strerror(error);
- LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s", error, strerror);
+ LOGGER_ERROR(log, "unexpected error reading from socket: %u, %s", error, strerror);
net_kill_strerror(strerror);
}
@@ -663,8 +914,8 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8
*length = (uint32_t)fail_or_len;
- if (addr.ss_family == AF_INET) {
- const struct sockaddr_in *addr_in = (const struct sockaddr_in *)&addr;
+ if (addr.addr.ss_family == AF_INET) {
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *)&addr.addr;
const Family *const family = make_tox_family(addr_in->sin_family);
assert(family != nullptr);
@@ -676,8 +927,8 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8
ip_port->ip.family = *family;
get_ip4(&ip_port->ip.ip.v4, &addr_in->sin_addr);
ip_port->port = addr_in->sin_port;
- } else if (addr.ss_family == AF_INET6) {
- const struct sockaddr_in6 *addr_in6 = (const struct sockaddr_in6 *)&addr;
+ } else if (addr.addr.ss_family == AF_INET6) {
+ const struct sockaddr_in6 *addr_in6 = (const struct sockaddr_in6 *)&addr.addr;
const Family *const family = make_tox_family(addr_in6->sin6_family);
assert(family != nullptr);
@@ -690,7 +941,7 @@ static int receivepacket(const Logger *log, Socket sock, IP_Port *ip_port, uint8
ip_port->port = addr_in6->sin6_port;
if (ipv6_ipv4_in_v6(&ip_port->ip.ip.v6)) {
- ip_port->ip.family = net_family_ipv4;
+ ip_port->ip.family = net_family_ipv4();
ip_port->ip.ip.v4.uint32 = ip_port->ip.ip.v6.uint32[3];
}
} else {
@@ -719,89 +970,37 @@ void networking_poll(const Networking_Core *net, void *userdata)
uint8_t data[MAX_UDP_PACKET_SIZE];
uint32_t length;
- while (receivepacket(net->log, net->sock, &ip_port, data, &length) != -1) {
+ while (receivepacket(net->ns, net->log, net->sock, &ip_port, data, &length) != -1) {
if (length < 1) {
continue;
}
- packet_handler_cb *const cb = net->packethandlers[data[0]].function;
- void *const object = net->packethandlers[data[0]].object;
+ const Packet_Handler *const handler = &net->packethandlers[data[0]];
- if (cb == nullptr) {
- LOGGER_WARNING(net->log, "[%02u] -- Packet has no handler", data[0]);
+ if (handler->function == nullptr) {
+ // TODO(https://github.com/TokTok/c-toxcore/issues/1115): Make this
+ // a warning or error again.
+ LOGGER_DEBUG(net->log, "[%02u] -- Packet has no handler", data[0]);
continue;
}
- cb(object, &ip_port, data, length, userdata);
- }
-}
-
-//!TOKSTYLE-
-// Global mutable state is not allowed in Tokstyle.
-static uint8_t at_startup_ran = 0;
-//!TOKSTYLE+
-int networking_at_startup(void)
-{
- if (at_startup_ran != 0) {
- return 0;
- }
-
-#ifndef VANILLA_NACL
-
-#ifdef USE_RANDOMBYTES_STIR
- randombytes_stir();
-#else
-
- if (sodium_init() == -1) {
- return -1;
- }
-
-#endif /*USE_RANDOMBYTES_STIR*/
-
-#endif/*VANILLA_NACL*/
-
-#ifdef OS_WIN32
- WSADATA wsaData;
-
- if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
- return -1;
+ handler->function(handler->object, &ip_port, data, length, userdata);
}
-
-#endif
- at_startup_ran = 1;
- return 0;
-}
-
-/* TODO(irungentoo): Put this somewhere */
-#if 0
-static void at_shutdown(void)
-{
-#ifdef OS_WIN32
- WSACleanup();
-#endif
-}
-#endif
-
-/** Initialize networking.
- * Added for reverse compatibility with old new_networking calls.
- */
-Networking_Core *new_networking(const Logger *log, const IP *ip, uint16_t port)
-{
- return new_networking_ex(log, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), nullptr);
}
-/** Initialize networking.
+/** @brief Initialize networking.
* Bind to ip and port.
* ip must be in network order EX: 127.0.0.1 = (7F000001).
* port is in host byte order (this means don't worry about it).
*
- * return Networking_Core object if no problems
- * return NULL if there are problems.
+ * @return Networking_Core object if no problems
+ * @retval NULL if there are problems.
*
* If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
*/
-Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t port_from, uint16_t port_to,
- unsigned int *error)
+Networking_Core *new_networking_ex(
+ const Logger *log, const Network *ns, const IP *ip,
+ uint16_t port_from, uint16_t port_to, unsigned int *error)
{
/* If both from and to are 0, use default port range
* If one is 0 and the other is non-0, use the non-0 value as only port
@@ -815,12 +1014,12 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
} else if (port_from != 0 && port_to == 0) {
port_to = port_from;
} else if (port_from > port_to) {
- uint16_t temp = port_from;
+ const uint16_t temp_port = port_from;
port_from = port_to;
- port_to = temp;
+ port_to = temp_port;
}
- if (error) {
+ if (error != nullptr) {
*error = 2;
}
@@ -830,69 +1029,60 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
return nullptr;
}
- if (networking_at_startup() != 0) {
- return nullptr;
- }
-
Networking_Core *temp = (Networking_Core *)calloc(1, sizeof(Networking_Core));
if (temp == nullptr) {
return nullptr;
}
+ temp->ns = ns;
temp->log = log;
temp->family = ip->family;
temp->port = 0;
/* Initialize our socket. */
/* add log message what we're creating */
- temp->sock = net_socket(temp->family, TOX_SOCK_DGRAM, TOX_PROTO_UDP);
+ temp->sock = net_socket(ns, temp->family, TOX_SOCK_DGRAM, TOX_PROTO_UDP);
/* Check for socket error. */
if (!sock_valid(temp->sock)) {
- int neterror = net_error();
+ const int neterror = net_error();
char *strerror = net_new_strerror(neterror);
- LOGGER_ERROR(log, "Failed to get a socket?! %d, %s", neterror, strerror);
+ LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, strerror);
net_kill_strerror(strerror);
free(temp);
- if (error) {
+ if (error != nullptr) {
*error = 1;
}
return nullptr;
}
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Functions to increase the size of the send and receive UDP buffers.
*/
int n = 1024 * 1024 * 2;
- if (setsockopt(temp->sock.socket, SOL_SOCKET, SO_RCVBUF, (const char *)&n, sizeof(n)) != 0) {
- LOGGER_WARNING(log, "Failed to set socket option %d", SO_RCVBUF);
+ if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) != 0) {
+ LOGGER_ERROR(log, "failed to set socket option %d", SO_RCVBUF);
}
- if (setsockopt(temp->sock.socket, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof(n)) != 0) {
- LOGGER_WARNING(log, "Failed to set socket option %d", SO_SNDBUF);
+ if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)) != 0) {
+ LOGGER_ERROR(log, "failed to set socket option %d", SO_SNDBUF);
}
-#endif
-
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Enable broadcast on socket */
int broadcast = 1;
- if (setsockopt(temp->sock.socket, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) != 0) {
- LOGGER_WARNING(log, "Failed to set socket option %d", SO_BROADCAST);
+ if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) != 0) {
+ LOGGER_ERROR(log, "failed to set socket option %d", SO_BROADCAST);
}
-#endif
-
/* iOS UDP sockets are weird and apparently can SIGPIPE */
- if (!set_socket_nosigpipe(temp->sock)) {
+ if (!set_socket_nosigpipe(ns, temp->sock)) {
kill_networking(temp);
- if (error) {
+ if (error != nullptr) {
*error = 1;
}
@@ -900,10 +1090,10 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
}
/* Set socket nonblocking. */
- if (!set_socket_nonblock(temp->sock)) {
+ if (!set_socket_nonblock(ns, temp->sock)) {
kill_networking(temp);
- if (error) {
+ if (error != nullptr) {
*error = 1;
}
@@ -912,24 +1102,23 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
/* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
uint16_t *portptr = nullptr;
- struct sockaddr_storage addr;
- size_t addrsize;
+ Network_Addr addr;
- memset(&addr, 0, sizeof(struct sockaddr_storage));
+ memset(&addr.addr, 0, sizeof(struct sockaddr_storage));
if (net_family_is_ipv4(temp->family)) {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in);
+ addr.size = sizeof(struct sockaddr_in);
addr4->sin_family = AF_INET;
addr4->sin_port = 0;
fill_addr4(&ip->ip.v4, &addr4->sin_addr);
portptr = &addr4->sin_port;
} else if (net_family_is_ipv6(temp->family)) {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in6);
+ addr.size = sizeof(struct sockaddr_in6);
addr6->sin6_family = AF_INET6;
addr6->sin6_port = 0;
fill_addr6(&ip->ip.v6, &addr6->sin6_addr);
@@ -943,12 +1132,16 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
return nullptr;
}
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-
if (net_family_is_ipv6(ip->family)) {
- const int is_dualstack = set_socket_dualstack(temp->sock);
- LOGGER_DEBUG(log, "Dual-stack socket: %s",
- is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses");
+ const bool is_dualstack = set_socket_dualstack(ns, temp->sock);
+
+ if (is_dualstack) {
+ LOGGER_TRACE(log, "Dual-stack socket: enabled");
+ } else {
+ LOGGER_ERROR(log, "Dual-stack socket failed to enable, won't be able to receive from/send to IPv4 addresses");
+ }
+
+#ifndef ESP_PLATFORM
/* multicast local nodes */
struct ipv6_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
@@ -957,21 +1150,20 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
mreq.ipv6mr_interface = 0;
- const int res = setsockopt(temp->sock.socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq));
+ const int res = net_setsockopt(ns, temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
int neterror = net_error();
char *strerror = net_new_strerror(neterror);
if (res < 0) {
- LOGGER_DEBUG(log, "Failed to activate local multicast membership. (%d, %s)", neterror, strerror);
+ LOGGER_INFO(log, "Failed to activate local multicast membership in FF02::1. (%d, %s)", neterror, strerror);
} else {
- LOGGER_DEBUG(log, "Local multicast group FF02::1 joined successfully. (%d, %s)", neterror, strerror);
+ LOGGER_TRACE(log, "Local multicast group joined successfully. (%d, %s)", neterror, strerror);
}
net_kill_strerror(strerror);
- }
-
#endif
+ }
/* A hanging program or a different user might block the standard port.
* As long as it isn't a parameter coming from the commandline,
@@ -993,17 +1185,13 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
*portptr = net_htons(port_to_try);
for (uint16_t tries = port_from; tries <= port_to; ++tries) {
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- int res = 0;
-#else
- int res = bind(temp->sock.socket, (struct sockaddr *)&addr, addrsize);
-#endif
+ const int res = net_bind(ns, temp->sock, &addr);
- if (!res) {
+ if (res == 0) {
temp->port = *portptr;
- char ip_str[IP_NTOA_LEN];
- LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(ip, ip_str, sizeof(ip_str)),
+ Ip_Ntoa ip_str;
+ LOGGER_DEBUG(log, "Bound successfully to %s:%u", net_ip_ntoa(ip, &ip_str),
net_ntohs(temp->port));
/* errno isn't reset on success, only set on failure, the failed
@@ -1013,7 +1201,7 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
errno = 0;
}
- if (error) {
+ if (error != nullptr) {
*error = 0;
}
@@ -1029,27 +1217,23 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
*portptr = net_htons(port_to_try);
}
- char ip_str[IP_NTOA_LEN];
+ Ip_Ntoa ip_str;
int neterror = net_error();
char *strerror = net_new_strerror(neterror);
- LOGGER_ERROR(log, "Failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", neterror, strerror,
- ip_ntoa(ip, ip_str, sizeof(ip_str)), port_from, port_to);
+ LOGGER_ERROR(log, "failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", neterror, strerror,
+ net_ip_ntoa(ip, &ip_str), port_from, port_to);
net_kill_strerror(strerror);
kill_networking(temp);
- if (error) {
+ if (error != nullptr) {
*error = 1;
}
return nullptr;
}
-Networking_Core *new_networking_no_udp(const Logger *log)
+Networking_Core *new_networking_no_udp(const Logger *log, const Network *ns)
{
- if (networking_at_startup() != 0) {
- return nullptr;
- }
-
/* this is the easiest way to completely disable UDP without changing too much code. */
Networking_Core *net = (Networking_Core *)calloc(1, sizeof(Networking_Core));
@@ -1057,6 +1241,7 @@ Networking_Core *new_networking_no_udp(const Logger *log)
return nullptr;
}
+ net->ns = ns;
net->log = log;
return net;
@@ -1065,13 +1250,13 @@ Networking_Core *new_networking_no_udp(const Logger *log)
/** Function to cleanup networking stuff (doesn't do much right now). */
void kill_networking(Networking_Core *net)
{
- if (!net) {
+ if (net == nullptr) {
return;
}
if (!net_family_is_unspec(net->family)) {
/* Socket is initialized, so we close it. */
- kill_sock(net->sock);
+ kill_sock(net->ns, net->sock);
}
free(net);
@@ -1080,7 +1265,7 @@ void kill_networking(Networking_Core *net)
bool ip_equal(const IP *a, const IP *b)
{
- if (!a || !b) {
+ if (a == nullptr || b == nullptr) {
return false;
}
@@ -1122,11 +1307,11 @@ bool ip_equal(const IP *a, const IP *b)
bool ipport_equal(const IP_Port *a, const IP_Port *b)
{
- if (!a || !b) {
+ if (a == nullptr || b == nullptr) {
return false;
}
- if (!a->port || (a->port != b->port)) {
+ if (a->port == 0 || (a->port != b->port)) {
return false;
}
@@ -1136,38 +1321,38 @@ bool ipport_equal(const IP_Port *a, const IP_Port *b)
/** nulls out ip */
void ip_reset(IP *ip)
{
- if (!ip) {
+ if (ip == nullptr) {
return;
}
- memset(ip, 0, sizeof(IP));
+ *ip = empty_ip;
}
/** nulls out ip_port */
void ipport_reset(IP_Port *ipport)
{
- if (!ipport) {
+ if (ipport == nullptr) {
return;
}
- memset(ipport, 0, sizeof(IP_Port));
+ *ipport = empty_ip_port;
}
/** nulls out ip, sets family according to flag */
void ip_init(IP *ip, bool ipv6enabled)
{
- if (!ip) {
+ if (ip == nullptr) {
return;
}
- memset(ip, 0, sizeof(IP));
- ip->family = ipv6enabled ? net_family_ipv6 : net_family_ipv4;
+ *ip = empty_ip;
+ ip->family = ipv6enabled ? net_family_ipv6() : net_family_ipv4();
}
/** checks if ip is valid */
bool ip_isset(const IP *ip)
{
- if (!ip) {
+ if (ip == nullptr) {
return false;
}
@@ -1177,96 +1362,82 @@ bool ip_isset(const IP *ip)
/** checks if ip is valid */
bool ipport_isset(const IP_Port *ipport)
{
- if (!ipport) {
+ if (ipport == nullptr) {
return false;
}
- if (!ipport->port) {
+ if (ipport->port == 0) {
return false;
}
return ip_isset(&ipport->ip);
}
-/** copies an ip structure (careful about direction!) */
+/** copies an ip structure (careful about direction) */
void ip_copy(IP *target, const IP *source)
{
- if (!source || !target) {
+ if (source == nullptr || target == nullptr) {
return;
}
*target = *source;
}
-/** copies an ip_port structure (careful about direction!) */
+/** copies an ip_port structure (careful about direction) */
void ipport_copy(IP_Port *target, const IP_Port *source)
{
- if (!source || !target) {
+ if (source == nullptr || target == nullptr) {
return;
}
*target = *source;
}
-/** ip_ntoa
- * converts ip into a string
- * ip_str must be of length at least IP_NTOA_LEN
+/** @brief Converts IP into a string.
+ *
+ * Writes error message into the buffer on error.
*
- * writes error message into the buffer on error
+ * @param ip_str contains a buffer of the required size.
*
- * returns ip_str
+ * @return Pointer to the buffer inside `ip_str` containing the IP string.
*/
-const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)
+const char *net_ip_ntoa(const IP *ip, Ip_Ntoa *ip_str)
{
- if (length < IP_NTOA_LEN) {
- snprintf(ip_str, length, "Bad buf length");
- return ip_str;
- }
-
- if (ip) {
- if (net_family_is_ipv4(ip->family)) {
- /* returns standard quad-dotted notation */
- struct in_addr addr;
- fill_addr4(&ip->ip.v4, &addr);
+ assert(ip_str != nullptr);
- ip_str[0] = '\0';
- assert(make_family(ip->family) == AF_INET);
- inet_ntop4(&addr, ip_str, length);
- } else if (net_family_is_ipv6(ip->family)) {
- /* returns hex-groups enclosed into square brackets */
- struct in6_addr addr;
- fill_addr6(&ip->ip.v6, &addr);
+ if (ip == nullptr) {
+ snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid: NULL)");
+ return ip_str->buf;
+ }
- assert(make_family(ip->family) == AF_INET6);
- inet_ntop6(&addr, ip_str, length);
- } else {
- snprintf(ip_str, length, "(IP invalid, family %u)", ip->family.value);
- }
- } else {
- snprintf(ip_str, length, "(IP invalid: NULL)");
+ if (!ip_parse_addr(ip, ip_str->buf, sizeof(ip_str->buf))) {
+ snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid, family %u)", ip->family.value);
+ return ip_str->buf;
}
/* brute force protection against lacking termination */
- ip_str[length - 1] = '\0';
- return ip_str;
+ ip_str->buf[sizeof(ip_str->buf) - 1] = '\0';
+ return ip_str->buf;
}
bool ip_parse_addr(const IP *ip, char *address, size_t length)
{
- if (!address || !ip) {
+ if (address == nullptr || ip == nullptr) {
return false;
}
if (net_family_is_ipv4(ip->family)) {
- const struct in_addr *addr = (const struct in_addr *)&ip->ip.v4;
+ struct in_addr addr;
assert(make_family(ip->family) == AF_INET);
- return inet_ntop4(addr, address, length) != nullptr;
+ fill_addr4(&ip->ip.v4, &addr);
+ return inet_ntop4(&addr, address, length) != nullptr;
}
if (net_family_is_ipv6(ip->family)) {
- const struct in6_addr *addr = (const struct in6_addr *)&ip->ip.v6;
+ struct in6_addr addr;
assert(make_family(ip->family) == AF_INET6);
- return inet_ntop6(addr, address, length) != nullptr;
+ fill_addr6(&ip->ip.v6, &addr);
+ return inet_ntop6(&addr, address, length) != nullptr;
}
return false;
@@ -1274,14 +1445,14 @@ bool ip_parse_addr(const IP *ip, char *address, size_t length)
bool addr_parse_ip(const char *address, IP *to)
{
- if (!address || !to) {
+ if (address == nullptr || to == nullptr) {
return false;
}
struct in_addr addr4;
if (inet_pton4(address, &addr4) == 1) {
- to->family = net_family_ipv4;
+ to->family = net_family_ipv4();
get_ip4(&to->ip.v4, &addr4);
return true;
}
@@ -1289,7 +1460,7 @@ bool addr_parse_ip(const char *address, IP *to)
struct in6_addr addr6;
if (inet_pton6(address, &addr6) == 1) {
- to->family = net_family_ipv6;
+ to->family = net_family_ipv6();
get_ip6(&to->ip.v6, &addr6);
return true;
}
@@ -1297,28 +1468,48 @@ bool addr_parse_ip(const char *address, IP *to)
return false;
}
-int addr_resolve(const char *address, IP *to, IP *extra)
+/** addr_resolve return values */
+#define TOX_ADDR_RESOLVE_INET 1
+#define TOX_ADDR_RESOLVE_INET6 2
+
+/**
+ * Uses getaddrinfo to resolve an address into an IP address.
+ *
+ * Uses the first IPv4/IPv6 addresses returned by getaddrinfo.
+ *
+ * @param address a hostname (or something parseable to an IP address)
+ * @param to to.family MUST be initialized, either set to a specific IP version
+ * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (0), if both
+ * IP versions are acceptable
+ * @param extra can be NULL and is only set in special circumstances, see returns
+ *
+ * Returns in `*to` a valid IPAny (v4/v6),
+ * prefers v6 if `ip.family` was TOX_AF_UNSPEC and both available
+ * Returns in `*extra` an IPv4 address, if family was TOX_AF_UNSPEC and `*to` is TOX_AF_INET6
+ *
+ * @return 0 on failure, `TOX_ADDR_RESOLVE_*` on success.
+ */
+non_null(1, 2, 3) nullable(4)
+static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return false;
-#else
+ if ((true)) {
+ return 0;
+ }
+#endif
- if (!address || !to) {
+ if (address == nullptr || to == nullptr) {
return 0;
}
- Family tox_family = to->family;
- int family = make_family(tox_family);
+ const Family tox_family = to->family;
+ const int family = make_family(tox_family);
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
- if (networking_at_startup() != 0) {
- return 0;
- }
-
struct addrinfo *server = nullptr;
const int rc = getaddrinfo(address, nullptr, &hints, &server);
@@ -1329,9 +1520,9 @@ int addr_resolve(const char *address, IP *to, IP *extra)
}
IP ip4;
- ip_init(&ip4, 0); // ipv6enabled = 0
+ ip_init(&ip4, false); // ipv6enabled = false
IP ip6;
- ip_init(&ip6, 1); // ipv6enabled = 1
+ ip_init(&ip6, true); // ipv6enabled = true
int result = 0;
bool done = false;
@@ -1340,12 +1531,12 @@ int addr_resolve(const char *address, IP *to, IP *extra)
switch (walker->ai_family) {
case AF_INET: {
if (walker->ai_family == family) { /* AF_INET requested, done */
- const struct sockaddr_in *addr = (const struct sockaddr_in *)(void *)walker->ai_addr;
+ const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
get_ip4(&to->ip.v4, &addr->sin_addr);
result = TOX_ADDR_RESOLVE_INET;
done = true;
- } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */
- const struct sockaddr_in *addr = (const struct sockaddr_in *)(void *)walker->ai_addr;
+ } else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */
+ const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
get_ip4(&ip4.ip.v4, &addr->sin_addr);
result |= TOX_ADDR_RESOLVE_INET;
}
@@ -1361,7 +1552,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)
result = TOX_ADDR_RESOLVE_INET6;
done = true;
}
- } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */
+ } else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */
if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
get_ip6(&ip6.ip.v6, &addr->sin6_addr);
@@ -1375,13 +1566,13 @@ int addr_resolve(const char *address, IP *to, IP *extra)
}
if (family == AF_UNSPEC) {
- if (result & TOX_ADDR_RESOLVE_INET6) {
+ if ((result & TOX_ADDR_RESOLVE_INET6) != 0) {
ip_copy(to, &ip6);
- if ((result & TOX_ADDR_RESOLVE_INET) && (extra != nullptr)) {
+ if ((result & TOX_ADDR_RESOLVE_INET) != 0 && (extra != nullptr)) {
ip_copy(extra, &ip4);
}
- } else if (result & TOX_ADDR_RESOLVE_INET) {
+ } else if ((result & TOX_ADDR_RESOLVE_INET) != 0) {
ip_copy(to, &ip4);
} else {
result = 0;
@@ -1390,12 +1581,11 @@ int addr_resolve(const char *address, IP *to, IP *extra)
freeaddrinfo(server);
return result;
-#endif
}
-bool addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
+bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra)
{
- if (!addr_resolve(address, to, extra)) {
+ if (addr_resolve(ns, address, to, extra) == 0) {
if (!addr_parse_ip(address, to)) {
return false;
}
@@ -1404,7 +1594,7 @@ bool addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
return true;
}
-int net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)
+bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)
{
struct sockaddr_storage addr = {0};
size_t addrsize;
@@ -1424,30 +1614,55 @@ int net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)
fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr);
addr6->sin6_port = ip_port->port;
} else {
- return 0;
+ Ip_Ntoa ip_str;
+ LOGGER_ERROR(log, "cannot connect to %s:%d which is neither IPv4 nor IPv6",
+ net_ip_ntoa(&ip_port->ip, &ip_str), ip_port->port);
+ return false;
}
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return 0;
-#else
- LOGGER_DEBUG(log, "connecting socket %d", (int)sock.socket);
- return connect(sock.socket, (struct sockaddr *)&addr, addrsize);
+ if ((true)) {
+ return true;
+ }
#endif
+
+ Ip_Ntoa ip_str;
+ LOGGER_DEBUG(log, "connecting socket %d to %s:%d",
+ (int)sock.sock, net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
+ errno = 0;
+
+ if (connect(sock.sock, (struct sockaddr *)&addr, addrsize) == -1) {
+ const int error = net_error();
+
+ // Non-blocking socket: "Operation in progress" means it's connecting.
+ if (!should_ignore_connect_error(error)) {
+ char *net_strerror = net_new_strerror(error);
+ LOGGER_ERROR(log, "failed to connect to %s:%d: %d (%s)",
+ net_ip_ntoa(&ip_port->ip, &ip_str), ip_port->port, error, net_strerror);
+ net_kill_strerror(net_strerror);
+ return false;
+ }
+ }
+
+ return true;
}
int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- *res = (IP_Port *)calloc(1, sizeof(IP_Port));
- assert(*res != nullptr);
- IP_Port *ip_port = *res;
- ip_port->ip.ip.v4.uint32 = 0x7F000003; // 127.0.0.3
- ip_port->ip.family = *make_tox_family(AF_INET);
+ if ((true)) {
+ *res = (IP_Port *)calloc(1, sizeof(IP_Port));
+ assert(*res != nullptr);
+ IP_Port *ip_port = *res;
+ ip_port->ip.ip.v4.uint32 = 0x7F000003; // 127.0.0.3
+ ip_port->ip.family = *make_tox_family(AF_INET);
+
+ return 1;
+ }
+#endif
- return 1;
-#else
// Try parsing as IP address first.
- IP_Port parsed = {0};
+ IP_Port parsed = {{{0}}};
if (addr_parse_ip(node, &parsed.ip)) {
IP_Port *tmp = (IP_Port *)calloc(1, sizeof(IP_Port));
@@ -1534,7 +1749,6 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
freeaddrinfo(infos);
return count;
-#endif
}
void net_freeipport(IP_Port *ip_ports)
@@ -1542,106 +1756,42 @@ void net_freeipport(IP_Port *ip_ports)
free(ip_ports);
}
-bool bind_to_port(Socket sock, Family family, uint16_t port)
+bool bind_to_port(const Network *ns, Socket sock, Family family, uint16_t port)
{
- struct sockaddr_storage addr = {0};
- size_t addrsize;
+ Network_Addr addr = {{0}};
if (net_family_is_ipv4(family)) {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in);
+ addr.size = sizeof(struct sockaddr_in);
addr4->sin_family = AF_INET;
addr4->sin_port = net_htons(port);
} else if (net_family_is_ipv6(family)) {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in6);
+ addr.size = sizeof(struct sockaddr_in6);
addr6->sin6_family = AF_INET6;
addr6->sin6_port = net_htons(port);
} else {
return false;
}
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return true;
-#else
- return bind(sock.socket, (struct sockaddr *)&addr, addrsize) == 0;
-#endif
+ return net_bind(ns, sock, &addr) == 0;
}
-Socket net_socket(Family domain, int type, int protocol)
+Socket net_socket(const Network *ns, Family domain, int type, int protocol)
{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- const Socket sock = {1};
- return sock;
-#else
const int platform_domain = make_family(domain);
const int platform_type = make_socktype(type);
const int platform_prot = make_proto(protocol);
- const Socket sock = {(int)socket(platform_domain, platform_type, platform_prot)};
+ const Socket sock = {ns->funcs->socket(ns->obj, platform_domain, platform_type, platform_prot)};
return sock;
-#endif
-}
-
-int net_send(const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port)
-{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- int res = fuzz_send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL);
-#else
- int res = send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL);
-#endif
- loglogdata(log, "T=>", buf, len, ip_port, res);
- return res;
-}
-
-int net_recv(const Logger *log, Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port)
-{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- int res = fuzz_recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL);
-#else
- int res = recv(sock.socket, (char *)buf, len, MSG_NOSIGNAL);
-#endif
- loglogdata(log, "=>T", buf, len, ip_port, res);
- return res;
-}
-
-int net_listen(Socket sock, int backlog)
-{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return 0;
-#else
- return listen(sock.socket, backlog);
-#endif
-}
-
-Socket net_accept(Socket sock)
-{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- const Socket newsock = {2};
- return newsock;
-#else
- const Socket newsock = {accept(sock.socket, nullptr, nullptr)};
- return newsock;
-#endif
}
-uint16_t net_socket_data_recv_buffer(Socket sock)
+uint16_t net_socket_data_recv_buffer(const Network *ns, Socket sock)
{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- return 0;
-#else
-
-#ifdef OS_WIN32
- u_long count = 0;
- ioctlsocket(sock.socket, FIONREAD, &count);
-#else
- int count = 0;
- ioctl(sock.socket, FIONREAD, &count);
-#endif
-
- return (uint16_t)count;
-#endif
+ const int count = ns->funcs->recvbuf(ns->obj, sock.sock);
+ return (uint16_t)max_s32(0, min_s32(count, UINT16_MAX));
}
uint32_t net_htonl(uint32_t hostlong)
@@ -1689,8 +1839,8 @@ size_t net_pack_u64(uint8_t *bytes, uint64_t v)
size_t net_unpack_u16(const uint8_t *bytes, uint16_t *v)
{
- uint8_t hi = bytes[0];
- uint8_t lo = bytes[1];
+ const uint8_t hi = bytes[0];
+ const uint8_t lo = bytes[1];
*v = ((uint16_t)hi << 8) | lo;
return sizeof(*v);
}
@@ -1731,9 +1881,9 @@ int net_error(void)
#endif
}
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
char *net_new_strerror(int error)
{
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
char *str = nullptr;
// Windows API is weird. The 5th function arg is of char* type, but we
// have to pass char** so that it could assign new memory block to our
@@ -1745,29 +1895,42 @@ char *net_new_strerror(int error)
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
error, 0, (char *)&str, 0, nullptr);
return str;
+}
#else
- char tmp[256];
-
- errno = 0;
-
#ifdef _GNU_SOURCE
- const char *retstr = strerror_r(error, tmp, sizeof(tmp));
+non_null()
+static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
+{
+ const char *retstr = strerror_r(error, tmp, tmp_size);
if (errno != 0) {
- snprintf(tmp, sizeof(tmp), "error %d (strerror_r failed with errno %d)", error, errno);
+ snprintf(tmp, tmp_size, "error %d (strerror_r failed with errno %d)", error, errno);
}
+ return retstr;
+}
#else
- const int fmt_error = strerror_r(error, tmp, sizeof(tmp));
+non_null()
+static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
+{
+ const int fmt_error = strerror_r(error, tmp, tmp_size);
if (fmt_error != 0) {
- snprintf(tmp, sizeof(tmp), "error %d (strerror_r failed with error %d, errno %d)", error, fmt_error, errno);
+ snprintf(tmp, tmp_size, "error %d (strerror_r failed with error %d, errno %d)", error, fmt_error, errno);
}
- const char *retstr = tmp;
+ return tmp;
+}
#endif
+char *net_new_strerror(int error)
+{
+ char tmp[256];
+
+ errno = 0;
+ const char *retstr = net_strerror_r(error, tmp, sizeof(tmp));
const size_t retstr_len = strlen(retstr);
+
char *str = (char *)malloc(retstr_len + 1);
if (str == nullptr) {
@@ -1777,8 +1940,8 @@ char *net_new_strerror(int error)
memcpy(str, retstr, retstr_len + 1);
return str;
-#endif
}
+#endif
void net_kill_strerror(char *strerror)
{