From 0f71a130effe325a2ab7fc0411c15bfcfb06830e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stig=20Bj=C3=B8rlykke?= Date: Tue, 21 Feb 2023 08:24:01 +0100 Subject: [PATCH] net: sockets: getaddrinfo: Minor refactoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- subsys/net/lib/sockets/getaddrinfo.c | 104 +++++++++++++-------------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/subsys/net/lib/sockets/getaddrinfo.c b/subsys/net/lib/sockets/getaddrinfo.c index 24d0b702fcb..2a499dcebb0 100644 --- a/subsys/net/lib/sockets/getaddrinfo.c +++ b/subsys/net/lib/sockets/getaddrinfo.c @@ -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); }