Skip to content

Commit ac81287

Browse files
committed
feat: implement the last 2 missing network struct functions
and make use of them
1 parent 29d1043 commit ac81287

File tree

9 files changed

+164
-69
lines changed

9 files changed

+164
-69
lines changed

auto_tests/network_test.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ static void test_addr_resolv_localhost(void)
2323
const Network *ns = os_network();
2424
ck_assert(ns != nullptr);
2525

26+
const Memory *mem = os_memory();
27+
ck_assert(mem != nullptr);
28+
2629
const char localhost[] = "localhost";
2730

2831
IP ip;
2932
ip_init(&ip, 0); // ipv6enabled = 0
3033

31-
bool res = addr_resolve_or_parse_ip(ns, localhost, &ip, nullptr, true);
34+
bool res = addr_resolve_or_parse_ip(ns, mem, localhost, &ip, nullptr, true);
3235

3336
int error = net_error();
3437
char *strerror = net_new_strerror(error);
@@ -42,14 +45,14 @@ static void test_addr_resolv_localhost(void)
4245
net_ip_ntoa(&ip, &ip_str));
4346

4447
ip_init(&ip, 1); // ipv6enabled = 1
45-
res = addr_resolve_or_parse_ip(ns, localhost, &ip, nullptr, true);
48+
res = addr_resolve_or_parse_ip(ns, mem, localhost, &ip, nullptr, true);
4649

4750
#if USE_IPV6
4851

4952
int localhost_split = 0;
5053

5154
if (!net_family_is_ipv6(ip.family)) {
52-
res = addr_resolve_or_parse_ip(ns, "ip6-localhost", &ip, nullptr, true);
55+
res = addr_resolve_or_parse_ip(ns, mem, "ip6-localhost", &ip, nullptr, true);
5356
localhost_split = 1;
5457
}
5558

@@ -75,7 +78,7 @@ static void test_addr_resolv_localhost(void)
7578
ip.family = net_family_unspec();
7679
IP extra;
7780
ip_reset(&extra);
78-
res = addr_resolve_or_parse_ip(ns, localhost, &ip, &extra, true);
81+
res = addr_resolve_or_parse_ip(ns, mem, localhost, &ip, &extra, true);
7982
error = net_error();
8083
strerror = net_new_strerror(error);
8184
ck_assert_msg(res, "Resolver failed: %d, %s", error, strerror);

toxcore/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ cc_library(
333333
hdrs = ["network_test_util.hh"],
334334
deps = [
335335
":crypto_core",
336+
":mem",
336337
":network",
337338
":test_util",
338339
],

toxcore/DHT.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1855,7 +1855,7 @@ bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
18551855
ip_extra = &ip_port_v4.ip;
18561856
}
18571857

1858-
if (addr_resolve_or_parse_ip(dht->ns, address, &ip_port_v64.ip, ip_extra, dns_enabled)) {
1858+
if (addr_resolve_or_parse_ip(dht->ns, dht->mem, address, &ip_port_v64.ip, ip_extra, dns_enabled)) {
18591859
ip_port_v64.port = port;
18601860
dht_bootstrap(dht, &ip_port_v64, public_key);
18611861

toxcore/network.c

Lines changed: 135 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,92 @@ static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const
592592
return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen);
593593
}
594594

595+
// sets and fills an array of addrs for address
596+
// returns the number of entries in addrs
597+
non_null()
598+
static int sys_getaddrinfo(void *obj, const Memory *mem, const char *address, int family, int sock_type, Network_Addr **addrs)
599+
{
600+
assert(addrs != nullptr);
601+
602+
struct addrinfo hints = {0};
603+
hints.ai_family = family;
604+
605+
606+
// different platforms favour a different field
607+
// hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
608+
hints.ai_socktype = sock_type;
609+
// hints.ai_protocol = protocol;
610+
611+
struct addrinfo *infos = nullptr;
612+
613+
const int rc = getaddrinfo(address, nullptr, &hints, &infos);
614+
615+
// Lookup failed.
616+
if (rc != 0) {
617+
// TODO(Green-Sky): log error
618+
return 0;
619+
}
620+
621+
const int32_t max_count = INT32_MAX / sizeof(Network_Addr);
622+
623+
// we count number of "valid" results
624+
int result = 0;
625+
for (struct addrinfo *walker = infos; walker != nullptr && result < max_count; walker = walker->ai_next) {
626+
if (walker->ai_family == family || family == AF_UNSPEC) {
627+
++result;
628+
}
629+
630+
// do we need to check socktype/protocol?
631+
}
632+
633+
assert(max_count >= result);
634+
635+
Network_Addr *tmp_addrs = (Network_Addr *)mem_valloc(mem, result, sizeof(Network_Addr));
636+
if (tmp_addrs == nullptr) {
637+
freeaddrinfo(infos);
638+
return 0;
639+
}
640+
641+
// now we fill in
642+
int i = 0;
643+
for (struct addrinfo *walker = infos; walker != nullptr; walker = walker->ai_next) {
644+
if (walker->ai_family == family || family == AF_UNSPEC) {
645+
tmp_addrs[i].size = sizeof(struct sockaddr_storage);
646+
tmp_addrs[i].addr.ss_family = walker->ai_family;
647+
648+
// according to spec, storage is supposed to be large enough (and source shows they are)
649+
// storage is 128 bytes
650+
assert(walker->ai_addrlen <= tmp_addrs[i].size);
651+
652+
memcpy(&tmp_addrs[i].addr, walker->ai_addr, walker->ai_addrlen);
653+
tmp_addrs[i].size = walker->ai_addrlen;
654+
655+
++i;
656+
}
657+
}
658+
659+
assert(i == result);
660+
661+
freeaddrinfo(infos);
662+
663+
*addrs = tmp_addrs;
664+
665+
// number of entries in addrs
666+
return result;
667+
}
668+
669+
non_null()
670+
static int sys_freeaddrinfo(void *obj, const Memory *mem, Network_Addr *addrs)
671+
{
672+
if (addrs == nullptr) {
673+
return 0;
674+
}
675+
676+
mem_delete(mem, addrs);
677+
678+
return 0;
679+
}
680+
595681
static const Network_Funcs os_network_funcs = {
596682
sys_close,
597683
sys_accept,
@@ -607,8 +693,10 @@ static const Network_Funcs os_network_funcs = {
607693
sys_socket_nonblock,
608694
sys_getsockopt,
609695
sys_setsockopt,
696+
sys_getaddrinfo,
697+
sys_freeaddrinfo,
610698
};
611-
static const Network os_network_obj = {&os_network_funcs};
699+
static const Network os_network_obj = {&os_network_funcs, nullptr};
612700

613701
const Network *os_network(void)
614702
{
@@ -1828,8 +1916,8 @@ bool addr_parse_ip(const char *address, IP *to)
18281916
*
18291917
* @return false on failure, true on success.
18301918
*/
1831-
non_null(1, 2, 3) nullable(4)
1832-
static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *extra)
1919+
non_null(1, 2, 3, 4) nullable(5)
1920+
static bool addr_resolve(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra)
18331921
{
18341922
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
18351923
if ((true)) {
@@ -1844,19 +1932,16 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
18441932
const Family tox_family = to->family;
18451933
const int family = make_family(tox_family);
18461934

1847-
struct addrinfo hints = {0};
1848-
hints.ai_family = family;
1849-
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
1850-
1851-
struct addrinfo *server = nullptr;
1935+
Network_Addr *addrs = nullptr;
1936+
const int rc = ns->funcs->getaddrinfo(ns->obj, mem, address, family, 0, &addrs);
18521937

1853-
const int rc = getaddrinfo(address, nullptr, &hints, &server);
1854-
1855-
// Lookup failed.
1856-
if (rc != 0) {
1938+
// Lookup failed / empty.
1939+
if (rc <= 0) {
18571940
return false;
18581941
}
18591942

1943+
assert(addrs != nullptr);
1944+
18601945
IP ip4;
18611946
ip_init(&ip4, false); // ipv6enabled = false
18621947
IP ip6;
@@ -1865,16 +1950,16 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
18651950
int result = 0;
18661951
bool done = false;
18671952

1868-
for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) {
1869-
switch (walker->ai_family) {
1953+
for (int i = 0; i < rc && !done; ++i) {
1954+
switch (addrs[i].addr.ss_family) {
18701955
case AF_INET: {
1871-
if (walker->ai_family == family) { /* AF_INET requested, done */
1872-
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
1956+
if (addrs[i].addr.ss_family == family) { /* AF_INET requested, done */
1957+
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
18731958
get_ip4(&to->ip.v4, &addr->sin_addr);
18741959
result = TOX_ADDR_RESOLVE_INET;
18751960
done = true;
18761961
} else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */
1877-
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
1962+
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
18781963
get_ip4(&ip4.ip.v4, &addr->sin_addr);
18791964
result |= TOX_ADDR_RESOLVE_INET;
18801965
}
@@ -1883,16 +1968,16 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
18831968
}
18841969

18851970
case AF_INET6: {
1886-
if (walker->ai_family == family) { /* AF_INET6 requested, done */
1887-
if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
1888-
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
1971+
if (addrs[i].addr.ss_family == family) { /* AF_INET6 requested, done */
1972+
if (addrs[i].size == sizeof(struct sockaddr_in6)) {
1973+
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
18891974
get_ip6(&to->ip.v6, &addr->sin6_addr);
18901975
result = TOX_ADDR_RESOLVE_INET6;
18911976
done = true;
18921977
}
18931978
} else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */
1894-
if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
1895-
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
1979+
if (addrs[i].size == sizeof(struct sockaddr_in6)) {
1980+
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
18961981
get_ip6(&ip6.ip.v6, &addr->sin6_addr);
18971982
result |= TOX_ADDR_RESOLVE_INET6;
18981983
}
@@ -1917,13 +2002,13 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
19172002
}
19182003
}
19192004

1920-
freeaddrinfo(server);
2005+
ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
19212006
return result != 0;
19222007
}
19232008

1924-
bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra, bool dns_enabled)
2009+
bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra, bool dns_enabled)
19252010
{
1926-
if (dns_enabled && addr_resolve(ns, address, to, extra)) {
2011+
if (dns_enabled && addr_resolve(ns, mem, address, to, extra)) {
19272012
return true;
19282013
}
19292014

@@ -1982,7 +2067,7 @@ bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket
19822067
return true;
19832068
}
19842069

1985-
int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled)
2070+
int32_t net_getipport(const Network *ns, const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled)
19862071
{
19872072
assert(node != nullptr);
19882073

@@ -2022,25 +2107,29 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
20222107
}
20232108
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
20242109

2110+
int type = make_socktype(tox_type);
2111+
// ugly
2112+
if (tox_type == -1) {
2113+
type = 0;
2114+
}
2115+
20252116
// It's not an IP address, so now we try doing a DNS lookup.
2026-
struct addrinfo *infos;
2027-
const int ret = getaddrinfo(node, nullptr, nullptr, &infos);
2117+
Network_Addr *addrs = nullptr;
2118+
const int rc = ns->funcs->getaddrinfo(ns->obj, mem, node, AF_UNSPEC, type, &addrs);
20282119

2029-
if (ret != 0) {
2120+
// Lookup failed / empty.
2121+
if (rc <= 0) {
20302122
return -1;
20312123
}
20322124

2125+
assert(addrs != nullptr);
2126+
20332127
// Used to avoid calloc parameter overflow
20342128
const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
2035-
const int type = make_socktype(tox_type);
20362129
size_t count = 0;
20372130

2038-
for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
2039-
if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
2040-
continue;
2041-
}
2042-
2043-
if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
2131+
for (int i = 0; i < rc && count < max_count; ++i) {
2132+
if (addrs[i].addr.ss_family != AF_INET && addrs[i].addr.ss_family != AF_INET6) {
20442133
continue;
20452134
}
20462135

@@ -2050,40 +2139,36 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
20502139
assert(count <= max_count);
20512140

20522141
if (count == 0) {
2053-
freeaddrinfo(infos);
2142+
ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
20542143
return 0;
20552144
}
20562145

20572146
IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port));
20582147

20592148
if (ip_port == nullptr) {
2060-
freeaddrinfo(infos);
2149+
ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
20612150
*res = nullptr;
20622151
return -1;
20632152
}
20642153

20652154
*res = ip_port;
20662155

2067-
for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {
2068-
if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
2069-
continue;
2070-
}
2071-
2072-
if (cur->ai_family == AF_INET) {
2073-
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
2156+
for (int i = 0; i < rc && count < max_count; ++i) {
2157+
if (addrs[i].addr.ss_family == AF_INET) {
2158+
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
20742159
ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr;
2075-
} else if (cur->ai_family == AF_INET6) {
2076-
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;
2160+
} else if (addrs[i].addr.ss_family == AF_INET6) {
2161+
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)&addrs[i].addr;
20772162
memcpy(ip_port->ip.ip.v6.uint8, addr->sin6_addr.s6_addr, sizeof(IP6));
20782163
} else {
20792164
continue;
20802165
}
20812166

2082-
const Family *const family = make_tox_family(cur->ai_family);
2167+
const Family *const family = make_tox_family(addrs[i].addr.ss_family);
20832168
assert(family != nullptr);
20842169

20852170
if (family == nullptr) {
2086-
freeaddrinfo(infos);
2171+
ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
20872172
return -1;
20882173
}
20892174

@@ -2092,7 +2177,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
20922177
++ip_port;
20932178
}
20942179

2095-
freeaddrinfo(infos);
2180+
ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
20962181

20972182
return count;
20982183
}

0 commit comments

Comments
 (0)