DNS using IPv6 transport

Andrew Lunn andrew.lunn@ascom.ch
Fri May 23 08:32:00 GMT 2003


Hi folks

This patch allows the DNS client to use IPv6 to talk to the DNS
server. 

        Andrew

-------------- next part --------------
? packages/net/openssl
Index: packages/net//common/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/ChangeLog,v
retrieving revision 1.35
diff -u -r1.35 ChangeLog
--- packages/net//common/current/ChangeLog	22 May 2003 14:28:54 -0000	1.35
+++ packages/net//common/current/ChangeLog	23 May 2003 08:30:38 -0000
@@ -1,3 +1,9 @@
+ 2003-05-23  Andrew Lunn  <andrew.lunn@ascom.ch>
+ 
+ 	* src/network_support.c (init_all_network_interfaces): Allow IPv4
+ 	or IPv6 addresses to be used when configuring a default DNS
+ 	server.
+ 
 2003-05-21  Andrew Lunn  <andrew.lunn@ascom.ch>
 
 	* src/getaddrinfo.c (getaddrinfo): Corrected a bad patch merge
Index: packages/net//common/current/src/network_support.c
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/src/network_support.c,v
retrieving revision 1.6
diff -u -r1.6 network_support.c
--- packages/net//common/current/src/network_support.c	12 May 2003 10:13:38 -0000	1.6
+++ packages/net//common/current/src/network_support.c	23 May 2003 08:30:38 -0000
@@ -476,13 +476,7 @@
 #endif
 
 #ifdef CYGDAT_NS_DNS_DEFAULT_SERVER
-#define _SERVER string(CYGDAT_NS_DNS_DEFAULT_SERVER)
-
-    {
-      struct in_addr server;
-      
-      inet_aton(_SERVER, &server);
-      cyg_dns_res_init(&server);
+      cyg_dns_res_start(CYGDAT_NS_DNS_DEFAULT_SERVER);
     }
 #endif
 
Index: packages/net//ns/dns/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/ns/dns/current/ChangeLog,v
retrieving revision 1.15
diff -u -r1.15 ChangeLog
--- packages/net//ns/dns/current/ChangeLog	14 May 2003 16:04:20 -0000	1.15
+++ packages/net//ns/dns/current/ChangeLog	23 May 2003 08:30:39 -0000
@@ -1,3 +1,15 @@
+2003-05-22  Andrew Lunn  <andrew.lunn@ascom.cd>
+
+        * src/dns.c: (cyg_dns_res_start) New: Allow IPv6 to be used to
+	transport queries to the DNS server. This requires a new API
+	function to start the client which if protocol family
+	independent.
+	* tests/dns1.c: Added a test which uses IPv6 as the transport to
+	the DNS server.
+	* doc/dns.sgml: Documentation of new API function for IPv6.
+	* cdl/dns.cdl: Comment that the default DNS server can be an IPv6
+	address.
+
 2003-05-14  Mark Salter  <msalter@redhat.com>
 
 	* include/dns_impl.inl: Use strrchr instead of rindex.
Index: packages/net//ns/dns/current/cdl/dns.cdl
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/ns/dns/current/cdl/dns.cdl,v
retrieving revision 1.7
diff -u -r1.7 dns.cdl
--- packages/net//ns/dns/current/cdl/dns.cdl	12 May 2003 10:06:05 -0000	1.7
+++ packages/net//ns/dns/current/cdl/dns.cdl	23 May 2003 08:30:39 -0000
@@ -77,8 +77,8 @@
         default_value 0
         description   "     
             This option controls the use of a default, hard coded DNS 
-            server. When this is enabled, the IP address in the CDL 
-            option CYGDAT_NS_DNS_DEFAULT_SERVER is used in
+            server. When this is enabled, the IPv4 or IPv6 address in 
+            the CDL option CYGDAT_NS_DNS_DEFAULT_SERVER is used in
             init_all_network_interfaces() to start the resolver using 
             the specified server. The DHCP client or user code may 
             override this by restarting the resolver."
Index: packages/net//ns/dns/current/doc/dns.sgml
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/ns/dns/current/doc/dns.sgml,v
retrieving revision 1.6
diff -u -r1.6 dns.sgml
--- packages/net//ns/dns/current/doc/dns.sgml	12 May 2003 10:06:05 -0000	1.6
+++ packages/net//ns/dns/current/doc/dns.sgml	23 May 2003 08:30:39 -0000
@@ -67,11 +67,10 @@
  and 
 <FUNCTION>gethostbyaddr()</FUNCTION>.
 A call to one will destroy the results from the previous call
-to the other function. <FUNCTION>getaddrinfo()</FUNCTION> is thread
-safe and so is the preferred interface.</PARA>
-</LISTITEM>
-<LISTITEM>
-<PARA>The client only uses IPv4 to access the DNS server.</PARA>
+to the other function. <FUNCTION>getaddrinfo()</FUNCTION> and
+<FUNCTION>getnameinfo()</FUNCTION> are thread
+safe and so these are the preferred interfaces. They are also address
+family independent so making it easier to port code to IPv6.</PARA>
 </LISTITEM>
 <LISTITEM><PARA>The DNS client will only return IPv4 addresses to
 RedBoot. At the moment this is not really a limitation,
@@ -81,9 +80,21 @@
 <PARA>To initialise the DNS client the following function must be
 called:</PARA>
 <PROGRAMLISTING>#include <network.h>
+int cyg_dns_res_start(char * dns_server)</PROGRAMLISTING>
+
+<PARA>Where dns_server is the address of the DNS server. The address
+must be in numeric form and can be either an IPv4 or an IPv6 address.
+</PARA>
+<PARA>There also exists a deprecated function to start the DNS
+client:</PARA>
+<PROGRAMLISTING>
 int cyg_dns_res_init(struct in_addr *dns_server)</PROGRAMLISTING>
 <PARA>where dns_server is the address of the DNS server
-the client should query. On Error this function returns -1, otherwise
+the client should query. The address should be in network order and
+can only be an IPv4 address.
+</PARA>
+
+<PARA> On error both this function returns -1, otherwise
 0 for success. If lookups are attemped before this function has
 been called, they will fail and return NULL, unless numeric host addresses
 are passed. In this cause, the address will be converted and returned
@@ -189,7 +200,8 @@
         information:</PARA>
       <PROGRAMLISTING>
         struct test_info_s {
-            char * dns_server;
+            char * dns_server_v4;
+            char * dns_server_v6;
             char * domain_name;
             char * hostname_v4;
             char * cname_v4;
Index: packages/net//ns/dns/current/include/dns.h
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/ns/dns/current/include/dns.h,v
retrieving revision 1.4
diff -u -r1.4 dns.h
--- packages/net//ns/dns/current/include/dns.h	12 May 2003 10:06:05 -0000	1.4
+++ packages/net//ns/dns/current/include/dns.h	23 May 2003 08:30:40 -0000
@@ -11,6 +11,7 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Andrew Lunn
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
@@ -54,8 +55,14 @@
 #include <netinet/in.h>
 
 #ifndef _POSIX_SOURCE
-/* Initialise the DNS client with the address of the server */
+/* Initialise the DNS client with the address of the server. The
+   address should be a IPv4 or IPv6 numeric address */
+externC int cyg_dns_res_start(char * server);
+
+/* Old interface which  is depricated */
 externC int cyg_dns_res_init(struct in_addr *dns_server);
+
+/* Functions to manipulate the domainname */
 externC int getdomainname(char *name, size_t len);
 externC int setdomainname(const char *name, size_t len);
 #endif
Index: packages/net//ns/dns/current/src/dns.c
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/ns/dns/current/src/dns.c,v
retrieving revision 1.5
diff -u -r1.5 dns.c
--- packages/net//ns/dns/current/src/dns.c	12 May 2003 10:06:06 -0000	1.5
+++ packages/net//ns/dns/current/src/dns.c	23 May 2003 08:30:40 -0000
@@ -250,22 +250,21 @@
 /* Include the DNS client implementation code */
 #include <cyg/ns/dns/dns_impl.inl>
 
-/* Initialise the resolver. Open a socket and bind it to the address
-   of the server.  return -1 if something goes wrong, otherwise 0. If
-   we are being called a second time we have to be careful to allow
-   any ongoing lookups to finish before we close the socket and
-   connect to a different DNS server. The danger here is that we may
-   have to wait for upto 32 seconds if the DNS server is down.
- */
-int  
-cyg_dns_res_init(struct in_addr *dns_server)
-{
-    struct sockaddr_in server;
-    struct servent *sent;
+/* (re)Start the DNS client. This opens a socket to the DNS server
+   who's address is passed in. This address can be either an IPv4 or
+   IPv6 address. This function can be called multiple times. Each
+   invocation will close any previous connection and make a new
+   connection to the new server. Note the address of the server must
+   be in numeric form since its not possible to do a DNS lookup! */
+
+int cyg_dns_res_start(char * dns_server) {
+
     static int init =0;
+    struct addrinfo * res;
+    int err;
 
-    CYG_REPORT_FUNCNAMETYPE( "cyg_dns_res_init", "returning %d" );
-    CYG_REPORT_FUNCARG1( "dns_server=%08x", dns_server );
+    CYG_REPORT_FUNCNAMETYPE( "cyg_dns_res_start", "returning %d" );
+    CYG_REPORT_FUNCARG1( "dns_server=%s", dns_server );
 
     CYG_CHECK_DATA_PTR( dns_server, "dns_server is not a valid pointer!" );
 
@@ -281,39 +280,61 @@
       cyg_drv_mutex_lock(&dns_mutex);
     }
     
-
-    s = socket(PF_INET, SOCK_DGRAM, 0);
-    if (s < 0) {
+    err = getaddrinfo(dns_server,"domain", NULL, &res);
+    if (err != 0) {
         cyg_drv_mutex_unlock(&dns_mutex);
         CYG_REPORT_RETVAL( -1 );
         return -1;
     }
   
-    sent = getservbyname("domain", "udp");
-    if (sent == (struct servent *)0) {
-        s = -1;
+    s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+    if (s == -1) {
         cyg_drv_mutex_unlock(&dns_mutex);
+        freeaddrinfo(res);
         CYG_REPORT_RETVAL( -1 );
         return -1;
     }
-  
-    memcpy((char *)&server.sin_addr, dns_server, sizeof(server.sin_addr));
-    server.sin_port = sent->s_port;
-    server.sin_family = AF_INET;
-    server.sin_len = sizeof(server);
 
-    if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
+    if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
         s = -1;
         cyg_drv_mutex_unlock(&dns_mutex);
+        freeaddrinfo(res);
         CYG_REPORT_RETVAL( -1 );
         return -1;
     }
     ptdindex = cyg_thread_new_data_index();  
   
     cyg_drv_mutex_unlock(&dns_mutex);
-  
+    freeaddrinfo(res);
     CYG_REPORT_RETVAL( 0 );
     return 0;
+}
+
+/* This is the old interface to start the resolver. It is only IPv4
+   capable and so is now depricated in favor of cyg_dns_res_start().
+   Initialise the resolver. Open a socket and bind it to the
+   address of the server.  return -1 if something goes wrong,
+   otherwise 0. If we are being called a second time we have to be
+   careful to allow any ongoing lookups to finish before we close the
+   socket and connect to a different DNS server. The danger here is
+   that we may have to wait for upto 32 seconds if the DNS server is
+   down.  */
+int  
+cyg_dns_res_init(struct in_addr *dns_server)
+{
+  char name[20];
+  unsigned char *bytes = (unsigned char *)dns_server;
+  int ret;
+
+  CYG_REPORT_FUNCNAMETYPE( "cyg_dns_res_init", "returning %d" );
+  CYG_REPORT_FUNCARG1( "dns_server=%08x", dns_server );
+
+  diag_sprintf(name, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
+  
+  ret = cyg_dns_res_start(name);
+  
+  CYG_REPORT_RETVAL( ret );
+  return ret;
 }
 
 /* add_answer checks to see if we already have this answer and if not,
Index: packages/net//ns/dns/current/tests/dns1.c
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/ns/dns/current/tests/dns1.c,v
retrieving revision 1.5
diff -u -r1.5 dns1.c
--- packages/net//ns/dns/current/tests/dns1.c	12 May 2003 10:06:06 -0000	1.5
+++ packages/net//ns/dns/current/tests/dns1.c	23 May 2003 08:30:40 -0000
@@ -70,7 +70,8 @@
 #define NELEM(x) (sizeof(x) / sizeof(x[0]))
 
 struct test_info_s {
-    char * dns_server;
+    char * dns_server_v4;
+    char * dns_server_v6;
     char * domain_name;
     char * hostname_v4;
     char * cname_v4;
@@ -87,6 +88,7 @@
 struct test_info_s test_info[] = {
     {
         "192.168.10.1",
+        "fe80::2ff:8eff:fe04:a18d",
         "lunn.org.",
         "hostnamev4",
         "cnamev4",
@@ -134,7 +136,7 @@
 #endif
     int error;
     
-    if (inet_pton(AF_INET, info->dns_server, (void *)&addr) < 0) {
+    if (inet_pton(AF_INET, info->dns_server_v4, (void *)&addr) < 0) {
       CYG_TEST_FAIL_FINISH("Error with DNS server address");
     }
     cyg_dns_res_init(&addr);
@@ -814,6 +816,64 @@
         diag_sprintf(buffer,"IPv4 & IPv6 FQDN cname: error %s", 
                      gai_strerror(error));
         CYG_TEST_FAIL(buffer);
+    }
+    
+    if (info->dns_server_v6) {
+        cyg_dns_res_start(info->dns_server_v6);
+        // Lookup the IPv4 and IPv6 FQDN cname 
+        error = getaddrinfo(cname, NULL, &hints, &res);
+        
+        if (error == EAI_NONE) {
+#ifdef CYGOPT_NS_DNS_FIRST_FAMILY_AF_INET6
+            ai6 = res;
+            ai4 = res->ai_next;
+            CYG_TEST_PASS_FAIL((NULL != ai6->ai_next),
+                               "[IPv6] IPv6 FQDN hostname not one result");
+            CYG_TEST_PASS_FAIL((NULL == ai4->ai_next),
+                               "[IPv6] IPv4 & IPv6 FQDN hostname two results");
+#else
+            ai4 = res;
+            ai6 = res->ai_next;
+            CYG_TEST_PASS_FAIL((NULL != ai4->ai_next),
+                               "[IPv6] IPv6 FQDN hostname not one result");
+            CYG_TEST_PASS_FAIL((NULL == ai6->ai_next),
+                               "[IPv6] IPv4 & IPv6 FQDN hostname two results");
+#endif
+            getnameinfo(ai4->ai_addr, ai4->ai_addrlen, 
+                        buff, sizeof(buff),
+                        NULL,0,NI_NUMERICHOST);
+            diag_sprintf(buffer,"[IPv6] Lookup %s: Result <%s is %s %s>", 
+                         cname,
+                         ai4->ai_canonname, 
+                         familytoa(ai4->ai_family),
+                         buff);
+            CYG_TEST_INFO(buffer);
+            CYG_TEST_PASS_FAIL((0 == memcmp((void *)&sa4, 
+                                            (void*)ai4->ai_addr,
+                                            sizeof(sa4))) &&
+                               (ai4->ai_family == AF_INET),
+                               "[IPv6] IPv4 & IPv6 FQDN cname address IPv4");
+            CYG_TEST_PASS_FAIL((0 == strcmp(name, ai4->ai_canonname)), 
+                               "[IPv6] IPv4 & IPv6 FQDN cname name");
+            getnameinfo(ai6->ai_addr, ai6->ai_addrlen, 
+                        buff, sizeof(buff),
+                        NULL,0,NI_NUMERICHOST);
+            diag_sprintf(buffer,"[IPv6] Lookup %s: Result <%s %s>", 
+                         cname,
+                         familytoa(ai6->ai_family),
+                         buff);
+            CYG_TEST_INFO(buffer);
+            CYG_TEST_PASS_FAIL((0 == memcmp((void *)&sa6, 
+                                            (void*)ai6->ai_addr,
+                                            sizeof(sa6))) &&
+                               (ai6->ai_family == AF_INET6),
+                               "[IPv6] IPv4 & IPv6 FQDN cname address IPv6");
+            freeaddrinfo(res);
+        } else {
+            diag_sprintf(buffer,"[IPv6] IPv4 & IPv6 FQDN cname: error %s", 
+                         gai_strerror(error));
+            CYG_TEST_FAIL(buffer);
+        }
     }
 #endif
 }


More information about the Ecos-patches mailing list