You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2020/04/27 11:52:37 UTC

[incubator-nuttx] 02/02: libc/netdb: support multiple DNS nameservers when not using resolv.conf

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit b34d7bf56da4c259af71b34f30549579dc95741a
Author: Juha Niskanen <ju...@haltian.com>
AuthorDate: Fri Apr 24 12:21:37 2020 +0300

    libc/netdb: support multiple DNS nameservers when not using resolv.conf
    
    Signed-off-by: Juha Niskanen <ju...@haltian.com>
---
 include/nuttx/net/dns.h                | 12 +++----
 libs/libc/netdb/Kconfig                | 16 ++++++---
 libs/libc/netdb/Make.defs              |  3 +-
 libs/libc/netdb/lib_dns.h              | 12 ++++---
 libs/libc/netdb/lib_dnsaddserver.c     | 33 ++++++++++++-----
 libs/libc/netdb/lib_dnsdefaultserver.c | 66 ++++++++++++++++++++++++++++++++++
 libs/libc/netdb/lib_dnsforeach.c       | 43 +++++++++++++++++-----
 libs/libc/netdb/lib_dnsinit.c          | 14 +++++---
 8 files changed, 163 insertions(+), 36 deletions(-)

diff --git a/include/nuttx/net/dns.h b/include/nuttx/net/dns.h
index 04e44c5..12b5675 100644
--- a/include/nuttx/net/dns.h
+++ b/include/nuttx/net/dns.h
@@ -136,7 +136,7 @@
  * Public Type Definitions
  ****************************************************************************/
 
- /* The DNS message header */
+/* The DNS message header */
 
 struct dns_header_s
 {
@@ -208,20 +208,20 @@ extern "C"
 int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen);
 
 /****************************************************************************
- * Name: dns_del_nameserver
+ * Name: dns_default_nameserver
  *
  * Description:
- *   Remove a DNS server so it is no longer available for further use.
+ *   Reset the resolver to use only the default DNS server, if any.
  *
  ****************************************************************************/
-/* REVISIT: Not implemented */
+
+int dns_default_nameserver(void);
 
 /****************************************************************************
  * Name: dns_foreach_nameserver
  *
  * Description:
- *   Traverse each nameserver entry in the resolv.conf file and perform the
- *   the provided callback.
+ *   Traverse each nameserver entry and perform the provided callback.
  *
  ****************************************************************************/
 
diff --git a/libs/libc/netdb/Kconfig b/libs/libc/netdb/Kconfig
index b205732..3478001 100644
--- a/libs/libc/netdb/Kconfig
+++ b/libs/libc/netdb/Kconfig
@@ -76,7 +76,7 @@ config NETDB_DNSCLIENT_ENTRIES
 		cached and if the name mapping can be found in that cache, the
 		network query can be avoid.  Of course, this is only useful if you
 		query the same name often and if the IP address of the name is
-		stable.  If the IP address can change, then cachin DNS address
+		stable.  If the IP address can change, then caching DNS address
 		might have undesirable side-effects (see help for
 		CONFIG_NETDB_DNSCLIENT_LIFESEC).
 
@@ -155,6 +155,14 @@ config NETDB_RESOLVCONF_NONSTDPORT
 
 endif # NETDB_RESOLVCONF
 
+config NETDB_DNSSERVER_NAMESERVERS
+	int "Max number of configured nameservers"
+	default 1
+	depends on !NETDB_RESOLVCONF
+	---help---
+		This setting determines how many nameservers there can be
+		in use concurrently.
+
 choice
 	prompt "DNS server address type"
 	default NETDB_DNSSERVER_IPv4 if NET_IPv4
@@ -166,7 +174,7 @@ config NETDB_DNSSERVER_NOADDR
 	bool "No default DNS server address"
 	---help---
 		There is not default DNS nameserver address.  Application must call
-		dns_add_server() at runtime to add the DNS server address.
+		dns_add_nameserver() at runtime to add the DNS server address.
 
 config NETDB_DNSSERVER_IPv4
 	bool "IPv4 DNS server address"
@@ -174,7 +182,7 @@ config NETDB_DNSSERVER_IPv4
 	---help---
 		An IPv4 default DNS nameserver address will be provided.  Application
 		may overwrite this start default server address by calling
-		dns_add_server() at runtime.
+		dns_add_nameserver() at runtime.
 
 config NETDB_DNSSERVER_IPv6
 	bool "IPv6 DNS server address"
@@ -182,7 +190,7 @@ config NETDB_DNSSERVER_IPv6
 	---help---
 		An IPv6 default DNS nameserver address will be provided.  Application
 		may overwrite this start default server address by calling
-		dns_add_server() at runtime.
+		dns_add_nameserver() at runtime.
 
 endchoice # DNS server address type
 
diff --git a/libs/libc/netdb/Make.defs b/libs/libc/netdb/Make.defs
index 56256bb..cdd79c5 100644
--- a/libs/libc/netdb/Make.defs
+++ b/libs/libc/netdb/Make.defs
@@ -55,7 +55,8 @@ endif
 # Add DNS lookup support
 
 ifeq ($(CONFIG_NETDB_DNSCLIENT),y)
-CSRCS += lib_dnsinit.c lib_dnsbind.c lib_dnsquery.c lib_dnsaddserver.c
+CSRCS += lib_dnsinit.c lib_dnsbind.c lib_dnsquery.c
+CSRCS += lib_dnsaddserver.c lib_dnsdefaultserver.c
 CSRCS += lib_dnsforeach.c lib_dnsnotify.c
 
 ifneq ($(CONFIG_NETDB_DNSCLIENT_ENTRIES),0)
diff --git a/libs/libc/netdb/lib_dns.h b/libs/libc/netdb/lib_dns.h
index 6a2b2fc..95e2dcc 100644
--- a/libs/libc/netdb/lib_dns.h
+++ b/libs/libc/netdb/lib_dns.h
@@ -80,6 +80,10 @@
 #  define CONFIG_NETDB_RESOLVCONF_PATH "/etc/resolv.conf"
 #endif
 
+#ifndef CONFIG_NETDB_DNSSERVER_NAMESERVERS
+#  define CONFIG_NETDB_DNSSERVER_NAMESERVERS 1
+#endif
+
 #define DNS_MAX_ADDRSTR   48
 #define DNS_MAX_LINE      64
 #define NETDB_DNS_KEYWORD "nameserver"
@@ -117,10 +121,10 @@ extern "C"
 #endif
 
 #ifndef CONFIG_NETDB_RESOLVCONF
-/* The DNS server address */
+/* The DNS server addresses */
 
-EXTERN union dns_addr_u g_dns_server;
-EXTERN bool g_dns_address;     /* true: We have the address of the DNS server */
+EXTERN union dns_addr_u g_dns_servers[];
+EXTERN uint8_t g_dns_nservers;
 #endif
 
 /****************************************************************************
@@ -141,7 +145,7 @@ bool dns_initialize(void);
  * Name: dns_semtake
  *
  * Description:
- *   Take the DNS semaphore, ignoring errors do to the receipt of signals.
+ *   Take the DNS semaphore, ignoring errors due to the receipt of signals.
  *
  ****************************************************************************/
 
diff --git a/libs/libc/netdb/lib_dnsaddserver.c b/libs/libc/netdb/lib_dnsaddserver.c
index 65fedbd..4bad46b 100644
--- a/libs/libc/netdb/lib_dnsaddserver.c
+++ b/libs/libc/netdb/lib_dnsaddserver.c
@@ -43,10 +43,10 @@
  ****************************************************************************/
 
 #ifndef CONFIG_NETDB_RESOLVCONF
-/* The DNS server address */
+/* The DNS server addresses */
 
-union dns_addr_u g_dns_server;
-bool g_dns_address;     /* true: We have the address of the DNS server */
+union dns_addr_u g_dns_servers[CONFIG_NETDB_DNSSERVER_NAMESERVERS];
+uint8_t g_dns_nservers;    /* Number of currently configured nameservers */
 #endif
 
 /****************************************************************************
@@ -198,10 +198,24 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
 {
   FAR uint16_t *pport;
   size_t copylen;
+  int nservers;
+  int idx;
 
   DEBUGASSERT(addr != NULL);
 
-  /* Copy the new server IP address into our private global data structure */
+  /* Get the index of the next free nameserver slot. */
+
+  dns_semtake();
+  if (g_dns_nservers == CONFIG_NETDB_DNSSERVER_NAMESERVERS)
+    {
+      idx = 0;
+      nservers = g_dns_nservers;
+    }
+  else
+    {
+      idx = g_dns_nservers;
+      nservers = idx + 1;
+    }
 
 #ifdef CONFIG_NET_IPv4
   /* Check for an IPv4 address */
@@ -211,7 +225,7 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
       /* Set up for the IPv4 address copy */
 
       copylen = sizeof(struct sockaddr_in);
-      pport   = &g_dns_server.ipv4.sin_port;
+      pport   = &g_dns_servers[idx].ipv4.sin_port;
     }
   else
 #endif
@@ -224,12 +238,13 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
       /* Set up for the IPv6 address copy */
 
       copylen = sizeof(struct sockaddr_in6);
-      pport   = &g_dns_server.ipv6.sin6_port;
+      pport   = &g_dns_servers[idx].ipv6.sin6_port;
     }
   else
 #endif
     {
       nerr("ERROR: Unsupported family: %d\n", addr->sa_family);
+      dns_semgive();
       return -ENOSYS;
     }
 
@@ -239,10 +254,11 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
     {
       nerr("ERROR: Invalid addrlen %ld for family %d\n",
             (long)addrlen, addr->sa_family);
+      dns_semgive();
       return -EINVAL;
     }
 
-  memcpy(&g_dns_server.addr, addr, copylen);
+  memcpy(&g_dns_servers[idx].addr, addr, copylen);
 
   /* A port number of zero means to use the default DNS server port number */
 
@@ -253,7 +269,8 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
 
   /* We now have a valid DNS address */
 
-  g_dns_address = true;
+  g_dns_nservers = nservers;
+  dns_semgive();
   dns_notify_nameserver(addr, addrlen);
   return OK;
 }
diff --git a/libs/libc/netdb/lib_dnsdefaultserver.c b/libs/libc/netdb/lib_dnsdefaultserver.c
new file mode 100644
index 0000000..5511e02
--- /dev/null
+++ b/libs/libc/netdb/lib_dnsdefaultserver.c
@@ -0,0 +1,66 @@
+/****************************************************************************
+ * libs/libc/netdb/lib_dnsdefaultserver.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 <nuttx/config.h>
+
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/net/dns.h>
+
+#include "netdb/lib_dns.h"
+
+#ifdef CONFIG_NETDB_DNSCLIENT
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: dns_default_nameserver
+ *
+ * Description:
+ *   Reset the resolver to use only the default DNS server, if any.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NETDB_RESOLVCONF
+int dns_default_nameserver(void)
+{
+  /* REVISIT: not implemented */
+
+  return -ENOSYS;
+}
+#else /* CONFIG_NETDB_RESOLVCONF */
+int dns_default_nameserver(void)
+{
+  dns_semtake();
+  g_dns_nservers = 0;
+  dns_semgive();
+  return OK;
+}
+#endif /* CONFIG_NETDB_RESOLVCONF */
+#endif /* CONFIG_NETDB_DNSCLIENT */
diff --git a/libs/libc/netdb/lib_dnsforeach.c b/libs/libc/netdb/lib_dnsforeach.c
index 5543820..4d80c09 100644
--- a/libs/libc/netdb/lib_dnsforeach.c
+++ b/libs/libc/netdb/lib_dnsforeach.c
@@ -81,7 +81,7 @@ static FAR char *find_spaces(FAR char *ptr)
  * Name: dns_foreach_nameserver
  *
  * Description:
- *   Traverse each nameserver entry in the resolv.conf file and perform the
+ *   Traverse each nameserver entry in the resolv.conf file and perform
  *   the provided callback.
  *
  ****************************************************************************/
@@ -247,19 +247,30 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
 
 int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
 {
+  FAR struct sockaddr *addr;
   int ret = OK;
+  int i;
 
-  if (g_dns_address)
+  dns_semtake();
+  for (i = 0; i < g_dns_nservers; i++)
     {
 #ifdef CONFIG_NET_IPv4
       /* Check for an IPv4 address */
 
-      if (g_dns_server.addr.sa_family == AF_INET)
+      if (g_dns_servers[i].addr.sa_family == AF_INET)
         {
+          struct sockaddr_in copy;
+
+          /* Operate on copy of server address, in case it changes. */
+
+          memcpy(&copy, &g_dns_servers[i].ipv4, sizeof(struct sockaddr_in));
+          addr = (FAR struct sockaddr *)&copy;
+
           /* Perform the callback */
 
-          ret = callback(arg, (FAR struct sockaddr *)&g_dns_server.ipv4,
-                         sizeof(struct sockaddr_in));
+          dns_semgive();
+          ret = callback(arg, addr, sizeof(struct sockaddr_in));
+          dns_semtake();
         }
       else
 #endif
@@ -267,22 +278,36 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
 #ifdef CONFIG_NET_IPv6
       /* Check for an IPv6 address */
 
-      if (g_dns_server.addr.sa_family == AF_INET6)
+      if (g_dns_servers[i].addr.sa_family == AF_INET6)
         {
+          struct sockaddr_in6 copy;
+
+          /* Operate on copy of server address, in case it changes. */
+
+          memcpy(&copy, &g_dns_servers[i].ipv6, sizeof(struct sockaddr_in6));
+          addr = (FAR struct sockaddr *)&copy;
+
           /* Perform the callback */
 
-          ret = callback(arg, (FAR struct sockaddr *)&g_dns_server.ipv6,
-                         sizeof(struct sockaddr_in6));
+          dns_semgive();
+          ret = callback(arg, addr, sizeof(struct sockaddr_in6));
+          dns_semtake();
         }
       else
 #endif
         {
           nerr("ERROR: Unsupported family: %d\n",
-                g_dns_server.addr.sa_family);
+                g_dns_servers[i].addr.sa_family);
           ret = -ENOSYS;
         }
+
+      if (ret != OK)
+        {
+          break;
+        }
     }
 
+  dns_semgive();
   return ret;
 }
 
diff --git a/libs/libc/netdb/lib_dnsinit.c b/libs/libc/netdb/lib_dnsinit.c
index efc6a1f..09c2847 100644
--- a/libs/libc/netdb/lib_dnsinit.c
+++ b/libs/libc/netdb/lib_dnsinit.c
@@ -54,7 +54,7 @@
  * Private Data
  ****************************************************************************/
 
-/* Protects g_seqno, DNS cache and notify */
+/* Protects DNS cache, nameserver list and notify list. */
 
 static sem_t g_dns_sem = SEM_INITIALIZER(1);
 
@@ -94,9 +94,15 @@ static const uint16_t g_ipv6_hostaddr[8] =
 bool dns_initialize(void)
 {
 #ifndef CONFIG_NETDB_RESOLVCONF
-  /* Has the DNS server IP address been assigned? */
+  int nservers;
 
-  if (!g_dns_address)
+  dns_semtake();
+  nservers = g_dns_nservers;
+  dns_semgive();
+
+  /* Has at least one DNS server IP address been assigned? */
+
+  if (nservers == 0)
     {
 #if defined(CONFIG_NETDB_DNSSERVER_IPv4)
       struct sockaddr_in addr4;
@@ -147,7 +153,7 @@ bool dns_initialize(void)
  * Name: dns_semtake
  *
  * Description:
- *   Take the DNS semaphore, ignoring errors do to the receipt of signals.
+ *   Take the DNS semaphore, ignoring errors due to the receipt of signals.
  *
  ****************************************************************************/