@@ -1225,7 +1225,34 @@ ZITI_FUNC
12251225int Ziti_resolve (const char * host , const char * port , const struct addrinfo * hints , struct addrinfo * * addrlist ) {
12261226 in_port_t portnum = port ? (in_port_t ) strtol (port , NULL , 10 ) : 0 ;
12271227 ZITI_LOG (DEBUG , "host[%s] port[%s]" , host , port );
1228- struct addrinfo * res = calloc (1 , sizeof (struct addrinfo ));
1228+
1229+ /**
1230+ * Linux and FreeBSD freeaddrinfo(ai) frees ai->canonname and ai, but not ai->ai_addr.
1231+ * ai is allocated large enough to carry the sockaddr
1232+ */
1233+ union sockaddr_union {
1234+ struct sockaddr sa ;
1235+ struct sockaddr_in in4 ;
1236+ struct sockaddr_in6 in6 ;
1237+ };
1238+
1239+ struct result_storage {
1240+ struct addrinfo addrinfo ;
1241+ union sockaddr_union sockaddr ;
1242+ } * store = calloc (1 , sizeof * store );
1243+
1244+ if (!store )
1245+ goto error ;
1246+
1247+ struct addrinfo * res = & store -> addrinfo ;
1248+ union sockaddr_union * addr = & store -> sockaddr ;
1249+
1250+ res -> ai_family = AF_UNSPEC ;
1251+ res -> ai_socktype = 0 ;
1252+ res -> ai_protocol = 0 ;
1253+
1254+ addr -> sa .sa_family = AF_UNSPEC ;
1255+
12291256 if (hints ) {
12301257 res -> ai_socktype = hints -> ai_socktype ;
12311258 switch (hints -> ai_socktype ) {
@@ -1239,27 +1266,36 @@ int Ziti_resolve(const char *host, const char *port, const struct addrinfo *hint
12391266 res -> ai_protocol = 0 ;
12401267 break ;
12411268 default : // no other protocols are supported
1242- return -1 ;
1269+ goto error ;
1270+ }
1271+
1272+ switch (hints -> ai_family ) {
1273+ case AF_INET :
1274+ case AF_INET6 :
1275+ case AF_UNSPEC :
1276+ res -> ai_family = hints -> ai_family ;
1277+ break ;
1278+ default : // unsupported address family
1279+ goto error ;
12431280 }
12441281 }
12451282
1246- struct sockaddr_in * addr4 = calloc (1 , sizeof (struct sockaddr_in6 ));
1247- int rc = 0 ;
1248- if ((rc = uv_ip4_addr (host , portnum , addr4 )) == 0 ) {
1249- ZITI_LOG (DEBUG , "host[%s] port[%s] rc = %d" , host , port , rc );
1283+ if ((res -> ai_family == AF_UNSPEC || res -> ai_family == AF_INET )
1284+ && uv_ip4_addr (host ? host : "127.0.0.1" , portnum , & addr -> in4 ) == 0 ) {
1285+ ZITI_LOG (DEBUG , "host[%s] port[%s]" , host , port );
12501286
12511287 res -> ai_family = AF_INET ;
1252- res -> ai_addr = (struct sockaddr * ) addr4 ;
1253- res -> ai_addrlen = sizeof (struct sockaddr_in );
1254-
1288+ res -> ai_addr = & addr -> sa ;
1289+ res -> ai_addrlen = sizeof addr -> in4 ;
12551290 * addrlist = res ;
12561291 return 0 ;
1257- } else if (uv_ip6_addr (host , portnum , (struct sockaddr_in6 * ) addr4 ) == 0 ) {
1258- ZITI_LOG (INFO , "host[%s] port[%s] rc = %d" , host , port , rc );
1292+ } else if ((res -> ai_family == AF_UNSPEC || res -> ai_family == AF_INET6 )
1293+ && uv_ip6_addr (host ? host : "::1" , portnum , & addr -> in6 ) == 0 ) {
1294+ ZITI_LOG (INFO , "host[%s] port[%s]" , host , port );
12591295
12601296 res -> ai_family = AF_INET6 ;
1261- res -> ai_addr = ( struct sockaddr * ) addr4 ;
1262- res -> ai_addrlen = sizeof ( struct sockaddr_in6 ) ;
1297+ res -> ai_addr = & addr -> sa ;
1298+ res -> ai_addrlen = sizeof addr -> in6 ;
12631299 * addrlist = res ;
12641300 return 0 ;
12651301 }
@@ -1273,14 +1309,14 @@ int Ziti_resolve(const char *host, const char *port, const struct addrinfo *hint
12731309 tlsuv_parse_url (& url , ctrl );
12741310
12751311 if (strncmp (host , url .hostname , url .hostname_len ) == 0 ) {
1276- return -1 ;
1312+ goto error ;
12771313 }
12781314
12791315 if (wrap -> ztx ) {
12801316 MODEL_MAP_FOR (chit , wrap -> ztx -> channels ) {
12811317 ziti_channel_t * ch = model_map_it_value (chit );
12821318 if (strcmp (ch -> host , host ) == 0 ) {
1283- return -1 ;
1319+ goto error ;
12841320 }
12851321 }
12861322 }
@@ -1300,21 +1336,25 @@ int Ziti_resolve(const char *host, const char *port, const struct addrinfo *hint
13001336 int err = await_future (f );
13011337 set_error (err );
13021338
1303- if (err == 0 ) {
1304- addr4 -> sin_family = AF_INET ;
1305- addr4 -> sin_port = htons (portnum );
1306- addr4 -> sin_addr .s_addr = (in_addr_t )(uintptr_t )f -> result ;
1339+ if (err != 0 )
1340+ goto error ;
13071341
1308- res -> ai_family = AF_INET ;
1309- res -> ai_addr = (struct sockaddr * ) addr4 ;
1310- res -> ai_socktype = hints -> ai_socktype ;
1342+ addr -> in4 .sin_family = AF_INET ;
1343+ addr -> in4 .sin_port = htons (portnum );
1344+ addr -> in4 .sin_addr .s_addr = (in_addr_t )(uintptr_t )f -> result ;
1345+
1346+ res -> ai_family = AF_INET ;
1347+ res -> ai_addr = & addr -> sa ;
1348+ res -> ai_addrlen = sizeof addr -> in4 ;
1349+ * addrlist = res ;
13111350
1312- res -> ai_addrlen = sizeof (* addr4 );
1313- * addrlist = res ;
1314- }
13151351 destroy_future (f );
13161352
1317- return err == 0 ? 0 : -1 ;
1353+ return 0 ;
1354+
1355+ error :
1356+ free (store );
1357+ return -1 ;
13181358}
13191359
13201360int Ziti_check_socket (ziti_socket_t fd ) {
0 commit comments