net: getaddrinfo: Query both IPv4 and IPv6 if family is AF_UNSPEC

We must query both IPv4 and IPv6 addresses if the hints parameter
is NULL i.e., user does not supply hints or if family is set to
AF_UNSPEC.

Fixes #16453

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2019-06-12 15:39:34 +03:00
parent 05cd3420ac
commit 19806a2c1b

View file

@ -105,7 +105,7 @@ static int exec_query(const char *host, int family,
{
enum dns_query_type qtype = DNS_QUERY_TYPE_A;
if (IS_ENABLED(CONFIG_NET_IPV6) && family != AF_INET) {
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
qtype = DNS_QUERY_TYPE_AAAA;
}
@ -205,6 +205,7 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
/* Link entries in advance */
ai_state.ai_arr[0].ai_next = &ai_state.ai_arr[1];
/* If the family is AF_UNSPEC, then we query IPv4 address first */
ret = exec_query(host, family, &ai_state);
if (ret == 0) {
/* If the DNS query for reason fails so that the
@ -226,6 +227,26 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
st1 = DNS_EAI_SYSTEM;
}
/* If family is AF_UNSPEC, the IPv4 query has been already done
* so we can do IPv6 query next if IPv6 is enabled in the config.
*/
if (family == AF_UNSPEC && IS_ENABLED(CONFIG_NET_IPV6)) {
ret = exec_query(host, AF_INET6, &ai_state);
if (ret == 0) {
int ret = k_sem_take(&ai_state.sem,
CONFIG_NET_SOCKETS_DNS_TIMEOUT +
K_MSEC(100));
if (ret == -EAGAIN) {
return DNS_EAI_AGAIN;
}
st2 = ai_state.status;
} else {
errno = -ret;
st2 = DNS_EAI_SYSTEM;
}
}
if (ai_state.idx > 0) {
ai_addr = &ai_state.ai_arr[ai_state.idx - 1]._ai_addr;
net_sin(ai_addr)->sin_port = htons(port);