diff --git a/include/nuttx/net/dns.h b/include/nuttx/net/dns.h index 5bd39421be537..0205ec67547be 100644 --- a/include/nuttx/net/dns.h +++ b/include/nuttx/net/dns.h @@ -247,6 +247,16 @@ int dns_register_notify(dns_callback_t callback, FAR void *arg); int dns_unregister_notify(dns_callback_t callback, FAR void *arg); +/**************************************************************************** + * Name: dns_set_queryfamily + * + * Description: + * Configure the address family to be used for queries. + * + ****************************************************************************/ + +int dns_set_queryfamily(sa_family_t family); + #undef EXTERN #if defined(__cplusplus) } diff --git a/libs/libc/netdb/CMakeLists.txt b/libs/libc/netdb/CMakeLists.txt index 4ed5835e0285d..c4b7d751b01be 100644 --- a/libs/libc/netdb/CMakeLists.txt +++ b/libs/libc/netdb/CMakeLists.txt @@ -55,6 +55,7 @@ if(CONFIG_LIBC_NETDB) list(APPEND SRCS lib_dnsinit.c lib_dnsbind.c lib_dnsquery.c) list(APPEND SRCS lib_dnsaddserver.c lib_dnsdefaultserver.c) list(APPEND SRCS lib_dnsforeach.c lib_dnsnotify.c) + list(APPEND SRCS lib_dnsqueryfamily.c) if(NOT CONFIG_NETDB_DNSCLIENT_ENTRIES EQUAL 0) list(APPEND SRCS lib_dnscache.c) diff --git a/libs/libc/netdb/Make.defs b/libs/libc/netdb/Make.defs index 16c62396034bb..41f7b28461b69 100644 --- a/libs/libc/netdb/Make.defs +++ b/libs/libc/netdb/Make.defs @@ -44,6 +44,7 @@ ifeq ($(CONFIG_NETDB_DNSCLIENT),y) CSRCS += lib_dnsinit.c lib_dnsbind.c lib_dnsquery.c CSRCS += lib_dnsaddserver.c lib_dnsdefaultserver.c CSRCS += lib_dnsforeach.c lib_dnsnotify.c +CSRCS += lib_dnsqueryfamily.c ifneq ($(CONFIG_NETDB_DNSCLIENT_ENTRIES),0) CSRCS += lib_dnscache.c diff --git a/libs/libc/netdb/lib_dns.h b/libs/libc/netdb/lib_dns.h index 3a05b797a0d3c..40f40c844e614 100644 --- a/libs/libc/netdb/lib_dns.h +++ b/libs/libc/netdb/lib_dns.h @@ -212,6 +212,23 @@ int dns_bind(sa_family_t family); int dns_query(FAR const char *hostname, FAR union dns_addr_u *addr, FAR int *naddr); +/**************************************************************************** + * Name: dns_is_queryfamily + * + * Description: + * Determine if the specified address family is available for DNS query. + * + * Input Parameters: + * family - The address family. AF_INET or AF_INET6 is specified. + * + * Returned Value: + * Returns true if the address family specified in the family argument + * is available. + * + ****************************************************************************/ + +bool dns_is_queryfamily(sa_family_t family); + /**************************************************************************** * Name: dns_save_answer * diff --git a/libs/libc/netdb/lib_dnsquery.c b/libs/libc/netdb/lib_dnsquery.c index 117a2f1b1eb0d..38d25efb89a88 100644 --- a/libs/libc/netdb/lib_dnsquery.c +++ b/libs/libc/netdb/lib_dnsquery.c @@ -643,85 +643,92 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr, for (retries = 0; retries < CONFIG_NETDB_DNSCLIENT_RETRIES; retries++) { #ifdef CONFIG_NET_IPv6 - /* Send the IPv6 query */ - - sd = dns_bind(addr->sa_family); - if (sd < 0) - { - query->result = sd; - return 0; - } - - ret = dns_send_query(sd, query->hostname, - (FAR union dns_addr_u *)addr, - DNS_RECTYPE_AAAA, &qdata->qinfo, qdata->buffer); - if (ret < 0) - { - dns_query_error("ERROR: IPv6 dns_send_query failed", - ret, (FAR union dns_addr_u *)addr); - query->result = ret; - } - else + if (dns_is_queryfamily(AF_INET6)) { - /* Obtain the IPv6 response */ + /* Send the IPv6 query */ - ret = dns_recv_response(sd, &query->addr[next], - *query->naddr - next, &qdata->qinfo, - &query->ttl, qdata->buffer); - if (ret >= 0) + sd = dns_bind(addr->sa_family); + if (sd < 0) { - next += ret; + query->result = sd; + return 0; } - else + + ret = dns_send_query(sd, query->hostname, + (FAR union dns_addr_u *)addr, + DNS_RECTYPE_AAAA, &qdata->qinfo, + qdata->buffer); + if (ret < 0) { - dns_query_error("ERROR: IPv6 dns_recv_response failed", + dns_query_error("ERROR: IPv6 dns_send_query failed", ret, (FAR union dns_addr_u *)addr); query->result = ret; } - } + else + { + /* Obtain the IPv6 response */ + + ret = dns_recv_response(sd, &query->addr[next], + *query->naddr - next, &qdata->qinfo, + &query->ttl, qdata->buffer); + if (ret >= 0) + { + next += ret; + } + else + { + dns_query_error("ERROR: IPv6 dns_recv_response failed", + ret, (FAR union dns_addr_u *)addr); + query->result = ret; + } + } - close(sd); + close(sd); + } #endif #ifdef CONFIG_NET_IPv4 - /* Send the IPv4 query */ - - sd = dns_bind(addr->sa_family); - if (sd < 0) - { - query->result = sd; - return 0; - } - - ret = dns_send_query(sd, query->hostname, - (FAR union dns_addr_u *)addr, - DNS_RECTYPE_A, &qdata->qinfo, qdata->buffer); - if (ret < 0) - { - dns_query_error("ERROR: IPv4 dns_send_query failed", - ret, (FAR union dns_addr_u *)addr); - query->result = ret; - } - else + if (dns_is_queryfamily(AF_INET)) { - /* Obtain the IPv4 response */ + /* Send the IPv4 query */ - ret = dns_recv_response(sd, &query->addr[next], - *query->naddr - next, &qdata->qinfo, - &query->ttl, qdata->buffer); - if (ret >= 0) + sd = dns_bind(addr->sa_family); + if (sd < 0) { - next += ret; + query->result = sd; + return 0; } - else + + ret = dns_send_query(sd, query->hostname, + (FAR union dns_addr_u *)addr, + DNS_RECTYPE_A, &qdata->qinfo, qdata->buffer); + if (ret < 0) { - dns_query_error("ERROR: IPv4 dns_recv_response failed", + dns_query_error("ERROR: IPv4 dns_send_query failed", ret, (FAR union dns_addr_u *)addr); query->result = ret; } - } + else + { + /* Obtain the IPv4 response */ + + ret = dns_recv_response(sd, &query->addr[next], + *query->naddr - next, &qdata->qinfo, + &query->ttl, qdata->buffer); + if (ret >= 0) + { + next += ret; + } + else + { + dns_query_error("ERROR: IPv4 dns_recv_response failed", + ret, (FAR union dns_addr_u *)addr); + query->result = ret; + } + } - close(sd); + close(sd); + } #endif /* CONFIG_NET_IPv4 */ if (next > 0) diff --git a/libs/libc/netdb/lib_dnsqueryfamily.c b/libs/libc/netdb/lib_dnsqueryfamily.c new file mode 100644 index 0000000000000..31b6ab3a0734f --- /dev/null +++ b/libs/libc/netdb/lib_dnsqueryfamily.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * libs/libc/netdb/lib_dnsqueryfamily.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "netdb/lib_dns.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int g_query_family = AF_UNSPEC; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dns_is_queryfamily + * + * Description: + * Determine if the specified address family is available for DNS query. + * + ****************************************************************************/ + +bool dns_is_queryfamily(sa_family_t family) +{ + DEBUGASSERT(family == AF_INET || family == AF_INET6); + + return (g_query_family == AF_UNSPEC) ? true : + (g_query_family == family); +} + +/**************************************************************************** + * Name: dns_set_queryfamily + * + * Description: + * Configure the address family to be used for queries. + * + ****************************************************************************/ + +int dns_set_queryfamily(sa_family_t family) +{ + int ret = OK; + + switch (family) + { +#ifdef CONFIG_NET_IPv4 + case AF_INET: +#endif +#ifdef CONFIG_NET_IPv6 + case AF_INET6: +#endif + case AF_UNSPEC: + dns_lock(); + g_query_family = family; + dns_unlock(); + ninfo("Configure address type for dns query: %d\n", family); + break; + default: + nerr("ERROR: Unsupported family: %d\n", family); + ret = -ENOSYS; + break; + } + +#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0 + dns_clear_answer(); +#endif + + return ret; +} +