@@ -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+
595681static 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
613701const 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