@@ -592,6 +592,92 @@ static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const
592
592
return setsockopt (net_socket_to_native (sock ), level , optname , (const char * )optval , optlen );
593
593
}
594
594
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
+
595
681
static const Network_Funcs os_network_funcs = {
596
682
sys_close ,
597
683
sys_accept ,
@@ -607,8 +693,10 @@ static const Network_Funcs os_network_funcs = {
607
693
sys_socket_nonblock ,
608
694
sys_getsockopt ,
609
695
sys_setsockopt ,
696
+ sys_getaddrinfo ,
697
+ sys_freeaddrinfo ,
610
698
};
611
- static const Network os_network_obj = {& os_network_funcs };
699
+ static const Network os_network_obj = {& os_network_funcs , nullptr };
612
700
613
701
const Network * os_network (void )
614
702
{
@@ -1828,8 +1916,8 @@ bool addr_parse_ip(const char *address, IP *to)
1828
1916
*
1829
1917
* @return false on failure, true on success.
1830
1918
*/
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 )
1833
1921
{
1834
1922
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1835
1923
if ((true)) {
@@ -1844,19 +1932,16 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
1844
1932
const Family tox_family = to -> family ;
1845
1933
const int family = make_family (tox_family );
1846
1934
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 );
1852
1937
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 ) {
1857
1940
return false;
1858
1941
}
1859
1942
1943
+ assert (addrs != nullptr );
1944
+
1860
1945
IP ip4 ;
1861
1946
ip_init (& ip4 , false); // ipv6enabled = false
1862
1947
IP ip6 ;
@@ -1865,16 +1950,16 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
1865
1950
int result = 0 ;
1866
1951
bool done = false;
1867
1952
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 ) {
1870
1955
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 ;
1873
1958
get_ip4 (& to -> ip .v4 , & addr -> sin_addr );
1874
1959
result = TOX_ADDR_RESOLVE_INET ;
1875
1960
done = true;
1876
1961
} 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 ;
1878
1963
get_ip4 (& ip4 .ip .v4 , & addr -> sin_addr );
1879
1964
result |= TOX_ADDR_RESOLVE_INET ;
1880
1965
}
@@ -1883,16 +1968,16 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
1883
1968
}
1884
1969
1885
1970
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 ;
1889
1974
get_ip6 (& to -> ip .v6 , & addr -> sin6_addr );
1890
1975
result = TOX_ADDR_RESOLVE_INET6 ;
1891
1976
done = true;
1892
1977
}
1893
1978
} 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 ;
1896
1981
get_ip6 (& ip6 .ip .v6 , & addr -> sin6_addr );
1897
1982
result |= TOX_ADDR_RESOLVE_INET6 ;
1898
1983
}
@@ -1917,13 +2002,13 @@ static bool addr_resolve(const Network *ns, const char *address, IP *to, IP *ext
1917
2002
}
1918
2003
}
1919
2004
1920
- freeaddrinfo (server );
2005
+ ns -> funcs -> freeaddrinfo (ns -> obj , mem , addrs );
1921
2006
return result != 0 ;
1922
2007
}
1923
2008
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 )
1925
2010
{
1926
- if (dns_enabled && addr_resolve (ns , address , to , extra )) {
2011
+ if (dns_enabled && addr_resolve (ns , mem , address , to , extra )) {
1927
2012
return true;
1928
2013
}
1929
2014
@@ -1982,7 +2067,7 @@ bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket
1982
2067
return true;
1983
2068
}
1984
2069
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 )
1986
2071
{
1987
2072
assert (node != nullptr );
1988
2073
@@ -2022,25 +2107,29 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
2022
2107
}
2023
2108
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
2024
2109
2110
+ int type = make_socktype (tox_type );
2111
+ // ugly
2112
+ if (tox_type == -1 ) {
2113
+ type = 0 ;
2114
+ }
2115
+
2025
2116
// 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 );
2028
2119
2029
- if (ret != 0 ) {
2120
+ // Lookup failed / empty.
2121
+ if (rc <= 0 ) {
2030
2122
return -1 ;
2031
2123
}
2032
2124
2125
+ assert (addrs != nullptr );
2126
+
2033
2127
// Used to avoid calloc parameter overflow
2034
2128
const size_t max_count = min_u64 (SIZE_MAX , INT32_MAX ) / sizeof (IP_Port );
2035
- const int type = make_socktype (tox_type );
2036
2129
size_t count = 0 ;
2037
2130
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 ) {
2044
2133
continue ;
2045
2134
}
2046
2135
@@ -2050,40 +2139,36 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
2050
2139
assert (count <= max_count );
2051
2140
2052
2141
if (count == 0 ) {
2053
- freeaddrinfo (infos );
2142
+ ns -> funcs -> freeaddrinfo (ns -> obj , mem , addrs );
2054
2143
return 0 ;
2055
2144
}
2056
2145
2057
2146
IP_Port * ip_port = (IP_Port * )mem_valloc (mem , count , sizeof (IP_Port ));
2058
2147
2059
2148
if (ip_port == nullptr ) {
2060
- freeaddrinfo (infos );
2149
+ ns -> funcs -> freeaddrinfo (ns -> obj , mem , addrs );
2061
2150
* res = nullptr ;
2062
2151
return -1 ;
2063
2152
}
2064
2153
2065
2154
* res = ip_port ;
2066
2155
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 ;
2074
2159
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 ;
2077
2162
memcpy (ip_port -> ip .ip .v6 .uint8 , addr -> sin6_addr .s6_addr , sizeof (IP6 ));
2078
2163
} else {
2079
2164
continue ;
2080
2165
}
2081
2166
2082
- const Family * const family = make_tox_family (cur -> ai_family );
2167
+ const Family * const family = make_tox_family (addrs [ i ]. addr . ss_family );
2083
2168
assert (family != nullptr );
2084
2169
2085
2170
if (family == nullptr ) {
2086
- freeaddrinfo (infos );
2171
+ ns -> funcs -> freeaddrinfo (ns -> obj , mem , addrs );
2087
2172
return -1 ;
2088
2173
}
2089
2174
@@ -2092,7 +2177,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
2092
2177
++ ip_port ;
2093
2178
}
2094
2179
2095
- freeaddrinfo (infos );
2180
+ ns -> funcs -> freeaddrinfo (ns -> obj , mem , addrs );
2096
2181
2097
2182
return count ;
2098
2183
}
0 commit comments