net: sockets: getaddrinfo: Minor refactoring

Minor refactoring in getaddrinfo() to make the code easier to
read and to make handling IPv4 and IPv6 support more equal.

- Move common wait and error handling code to exec_query()
- Use the same check for CONFIG_NET_IPV4 and CONFIG_NET_IPV6
- Add extra sanity check for family before exec_query()
- Do not set errno when return DNS_EAI_ADDRFAMILY

Fix issue with setting port number for all DNS servers.

Signed-off-by: Stig Bjørlykke <stig.bjorlykke@nordicsemi.no>
This commit is contained in:
Stig Bjørlykke 2023-02-21 08:24:01 +01:00 committed by Carles Cufí
parent d92aaba3bc
commit 0f71a130ef

View file

@ -107,14 +107,41 @@ static int exec_query(const char *host, int family,
struct getaddrinfo_state *ai_state)
{
enum dns_query_type qtype = DNS_QUERY_TYPE_A;
int st, ret;
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
if (family == AF_INET6) {
qtype = DNS_QUERY_TYPE_AAAA;
}
return dns_get_addr_info(host, qtype, &ai_state->dns_id,
dns_resolve_cb, ai_state,
CONFIG_NET_SOCKETS_DNS_TIMEOUT);
ret = dns_get_addr_info(host, qtype, &ai_state->dns_id,
dns_resolve_cb, ai_state,
CONFIG_NET_SOCKETS_DNS_TIMEOUT);
if (ret == 0) {
/* If the DNS query for reason fails so that the
* dns_resolve_cb() would not be called, then we want the
* semaphore to timeout so that we will not hang forever.
* So make the sem timeout longer than the DNS timeout so that
* we do not need to start to cancel any pending DNS queries.
*/
ret = k_sem_take(&ai_state->sem, K_MSEC(CONFIG_NET_SOCKETS_DNS_TIMEOUT + 100));
if (ret == -EAGAIN) {
(void)dns_cancel_addr_info(ai_state->dns_id);
st = DNS_EAI_AGAIN;
} else {
st = ai_state->status;
}
} else if (ret == -EPFNOSUPPORT) {
/* If we are returned -EPFNOSUPPORT then that will indicate
* wrong address family type queried. Check that and return
* DNS_EAI_ADDRFAMILY.
*/
st = DNS_EAI_ADDRFAMILY;
} else {
errno = -ret;
st = DNS_EAI_SYSTEM;
}
return st;
}
static int getaddrinfo_null_host(int port, const struct zsock_addrinfo *hints,
@ -162,12 +189,15 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
long int port = 0;
int st1 = DNS_EAI_ADDRFAMILY, st2 = DNS_EAI_ADDRFAMILY;
struct sockaddr *ai_addr;
int ret;
struct getaddrinfo_state ai_state;
if (hints) {
family = hints->ai_family;
ai_flags = hints->ai_flags;
if ((family != AF_UNSPEC) && (family != AF_INET) && (family != AF_INET6)) {
return DNS_EAI_ADDRFAMILY;
}
}
if (ai_flags & AI_NUMERICHOST) {
@ -201,66 +231,28 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
ai_state.dns_id = 0;
k_sem_init(&ai_state.sem, 0, K_SEM_MAX_LIMIT);
/* In case IPv4 is not supported, force to check only for IPv6 */
if (family == AF_UNSPEC && !IS_ENABLED(CONFIG_NET_IPV4)) {
family = AF_INET6;
}
/* 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
* dns_resolve_cb() would not be called, then we want the
* semaphore to timeout so that we will not hang forever.
* So make the sem timeout longer than the DNS timeout so that
* we do not need to start to cancel any pending DNS queries.
*/
int ret = k_sem_take(&ai_state.sem,
K_MSEC(CONFIG_NET_SOCKETS_DNS_TIMEOUT +
100));
if (ret == -EAGAIN) {
(void)dns_cancel_addr_info(ai_state.dns_id);
return DNS_EAI_AGAIN;
}
st1 = ai_state.status;
} else {
/* If we are returned -EPFNOSUPPORT then that will indicate
* wrong address family type queried. Check that and return
* DNS_EAI_ADDRFAMILY and set errno to EINVAL.
*/
if (ret == -EPFNOSUPPORT) {
errno = EINVAL;
st1 = DNS_EAI_ADDRFAMILY;
} else {
errno = -ret;
st1 = DNS_EAI_SYSTEM;
/* If family is AF_UNSPEC, then we query IPv4 address first
* if IPv4 is enabled in the config.
*/
if ((family != AF_INET6) && IS_ENABLED(CONFIG_NET_IPV4)) {
st1 = exec_query(host, AF_INET, &ai_state);
if (st1 == DNS_EAI_AGAIN) {
return st1;
}
}
/* 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,
K_MSEC(CONFIG_NET_SOCKETS_DNS_TIMEOUT + 100));
if (ret == -EAGAIN) {
(void)dns_cancel_addr_info(ai_state.dns_id);
return DNS_EAI_AGAIN;
}
st2 = ai_state.status;
} else {
errno = -ret;
st2 = DNS_EAI_SYSTEM;
if ((family != AF_INET) && IS_ENABLED(CONFIG_NET_IPV6)) {
st2 = exec_query(host, AF_INET6, &ai_state);
if (st2 == DNS_EAI_AGAIN) {
return st2;
}
}
if (ai_state.idx > 0) {
ai_addr = &ai_state.ai_arr[ai_state.idx - 1]._ai_addr;
for (uint16_t idx = 0; idx < ai_state.idx; idx++) {
ai_addr = &ai_state.ai_arr[idx]._ai_addr;
net_sin(ai_addr)->sin_port = htons(port);
}