diff --git a/ChangeLog b/ChangeLog index 95ea69ac75..6ef4685fc8 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10698,4 +10698,10 @@ lookup before consulting the host table (if so enabled) (2015-07-10). * arch/arm/src/samdl/chip/saml_usb.h: Several fixes to register definitions and types. From Janne Rosberg (2015-07-10). - + * include/nuttx/net/ and libc/netdb: Repartitioning of DNS client + logic in preparation for IPv6 support (2015-07-12): + - Rename include/nuttx/net/dnsclient.h to dns.h + - Move internal DNS prototypes from dns.h to libc/netdb/lib_dns.h + - Global standard DNS definitions from libc/netdb/dns_soccket.c to dns.h + - Eliminate dns_gethostip(). This is now an internal part of gethostbyname() + - Eliminate interface dns_whois(). Not needed in this new context. diff --git a/include/nuttx/net/dnsclient.h b/include/nuttx/net/dns.h similarity index 64% rename from include/nuttx/net/dnsclient.h rename to include/nuttx/net/dns.h index 785c2a9ec9..f03e1679f5 100644 --- a/include/nuttx/net/dnsclient.h +++ b/include/nuttx/net/dns.h @@ -1,8 +1,8 @@ /**************************************************************************** - * include/nuttx/net/dnsclient.h + * include/nuttx/net/dns.h * DNS resolver code header file. * - * Copyright (C) 2007-2009, 2011-2012, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011-2012, 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Inspired by/based on uIP logic by Adam Dunkels: @@ -36,8 +36,8 @@ * ****************************************************************************/ -#ifndef __INCLUDE_NUTTX_NET_DNSCLIENT_H -#define __INCLUDE_NUTTX_NET_DNSCLIENT_H +#ifndef __INCLUDE_NUTTX_NET_DNS_H +#define __INCLUDE_NUTTX_NET_DNS_H /**************************************************************************** * Included Files @@ -66,6 +66,54 @@ # endif #endif +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + + /* The DNS message header */ + +struct dns_header_s +{ + uint16_t id; + uint8_t flags1; + uint8_t flags2; + uint16_t numquestions; + uint16_t numanswers; + uint16_t numauthrr; + uint16_t numextrarr; +}; + +/* The DNS answer message structure */ + +struct dns_answer_s +{ + /* DNS answer record starts with either a domain name or a pointer + * to a name already present somewhere in the packet. + */ + + uint16_t type; + uint16_t class; + uint16_t ttl[2]; + uint16_t len; +#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 + struct in6_addr ipaddr; +#else + struct in_addr ipaddr; +#endif +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -79,45 +127,11 @@ extern "C" #define EXTERN extern #endif -/**************************************************************************** - * Name: dns_bind - * - * Description: - * Initialize the DNS resolver using the caller provided socket. - * - ****************************************************************************/ - -int dns_bind(FAR int *sockfd); - -/**************************************************************************** - * Name: dns_free - * - * Description: - * Release the DNS resolver by closing the socket. - * - ****************************************************************************/ - -int dns_free(FAR int *sockfd); - -/**************************************************************************** - * Name: dns_query - * - * Description: - * Using the DNS resolver socket (sockfd), look up the the 'hostname', and - * return its IP address in 'ipaddr' - * - * Returned Value: - * Returns zero (OK) if the query was successful. - * - ****************************************************************************/ - -int dns_query(int sockfd, FAR const char *hostname, FAR in_addr_t *ipaddr); - /**************************************************************************** * Name: dns_setserver * * Description: - * Configure which DNS server to use for queries + * Configure which DNS server to use for queries. * ****************************************************************************/ @@ -141,41 +155,9 @@ void dns_getserver(FAR struct in6_addr *dnsserver); void dns_getserver(FAR struct in_addr *dnsserver); #endif -/**************************************************************************** - * Name: dns_whois - * - * Description: - * Get the binding for 'name' using the DNS server accessed via 'sockfd' - * - ****************************************************************************/ - -#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 -int dns_whois(int sockfd, FAR const char *name, - FAR struct sockaddr_in6 *addr); -#else -int dns_whois(int sockfd, FAR const char *name, - FAR struct sockaddr_in *addr); -#endif - -/**************************************************************************** - * Name: dns_gethostip - * - * Descriptions: - * Combines the operations of dns_bind(), dns_query(), and - * dns_free() to obtain the the IP address ('ipaddr') associated with - * the 'hostname' in one operation. - * - ****************************************************************************/ - -#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 -int dns_gethostip(FAR const char *hostname, FAR struct in6_addr *ipaddr); -#else -int dns_gethostip(FAR const char *hostname, FAR in_addr_t *ipaddr); -#endif - #undef EXTERN #if defined(__cplusplus) } #endif -#endif /* __INCLUDE_NUTTX_NET_DNSCLIENT_H */ +#endif /* __INCLUDE_NUTTX_NET_DNS_H */ diff --git a/libc/netdb/Make.defs b/libc/netdb/Make.defs index 222c53743d..ada616983d 100644 --- a/libc/netdb/Make.defs +++ b/libc/netdb/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # libc/netdb/Make.defs # -# Copyright (C) 2011-2013 Gregory Nutt. All rights reserved. +# Copyright (C) 2015 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -52,7 +52,7 @@ ifeq ($(CONFIG_NETDB_DNSCLIENT),y) ifneq ($(CONFIG_NETDB_HOSTFILE),y) CSRCS += lib_gethostbyname.c lib_gethostbynamer.c endif -CSRCS += dns_socket.c dns_gethostip.c +CSRCS += lib_dnsclient.c endif # Add the net directory to the build diff --git a/libc/netdb/dns_gethostip.c b/libc/netdb/dns_gethostip.c deleted file mode 100644 index 1b371f1183..0000000000 --- a/libc/netdb/dns_gethostip.c +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** - * libc/netdb/dns_gethostip.c - * - * Copyright (C) 2007, 2009, 2012, 2014 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Based heavily on portions of uIP: - * - * Author: Adam Dunkels - * Copyright (c) 2002-2003, Adam Dunkels. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: dns_gethostip - * - * Descriptions: - * Combines the operations of dns_bind(), dns_query(), and - * dns_free() to obtain the the IP address ('ipaddr') associated with - * the 'hostname' in one operation. - * - ****************************************************************************/ - -#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 -int dns_gethostip(FAR const char *hostname, FAR struct in6_addr *ipaddr) -#else -int dns_gethostip(FAR const char *hostname, FAR in_addr_t *ipaddr) -#endif -{ - int sockfd = -1; - int ret = ERROR; - - dns_bind(&sockfd); - if (sockfd >= 0) - { - ret = dns_query(sockfd, hostname, ipaddr); - dns_free(&sockfd); - } - - return ret; -} diff --git a/libc/netdb/dns_socket.c b/libc/netdb/lib_dnsclient.c similarity index 63% rename from libc/netdb/dns_socket.c rename to libc/netdb/lib_dnsclient.c index a0c32b21ee..168a3eecc9 100644 --- a/libc/netdb/dns_socket.c +++ b/libc/netdb/lib_dnsclient.c @@ -1,13 +1,11 @@ /**************************************************************************** - * libc/netdb/dns_socket.c + * libc/netdb/lib_dnsclient.c * DNS host name to IP address resolver. * * The uIP DNS resolver functions are used to lookup a hostname and - * map it to a numerical IP address. It maintains a list of resolved - * hostnames that can be queried. New hostnames can be resolved using the - * dns_whois() function. + * map it to a numerical IP address. * - * Copyright (C) 2007, 2009, 2012, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2012, 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Based heavily on portions of uIP: @@ -60,46 +58,24 @@ #include #include -#include -#include +#include + +#include "netdb/lib_dns.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#ifndef CONFIG_NETDB_DNSCLIENT_ENTRIES -# define RESOLV_ENTRIES 4 -#else /* CONFIG_NETDB_DNSCLIENT_ENTRIES */ -# define RESOLV_ENTRIES CONFIG_NETDB_DNSCLIENT_ENTRIES -#endif /* CONFIG_NETDB_DNSCLIENT_ENTRIES */ - -#ifndef NULL -# define NULL (void *)0 -#endif /* NULL */ - /* The maximum number of retries when asking for a name */ -#define MAX_RETRIES 8 +#define MAX_RETRIES 8 -#define DNS_FLAG1_RESPONSE 0x80 -#define DNS_FLAG1_OPCODE_STATUS 0x10 -#define DNS_FLAG1_OPCODE_INVERSE 0x08 -#define DNS_FLAG1_OPCODE_STANDARD 0x00 -#define DNS_FLAG1_AUTHORATIVE 0x04 -#define DNS_FLAG1_TRUNC 0x02 -#define DNS_FLAG1_RD 0x01 -#define DNS_FLAG2_RA 0x80 -#define DNS_FLAG2_ERR_MASK 0x0f -#define DNS_FLAG2_ERR_NONE 0x00 -#define DNS_FLAG2_ERR_NAME 0x03 +/* Buffer sizes */ #define SEND_BUFFER_SIZE 64 +#define RECV_BUFFER_SIZE CONFIG_NETDB_DNSCLIENT_MAXRESPONSE -#ifdef CONFIG_NETDB_DNSCLIENT_MAXRESPONSE -# define RECV_BUFFER_SIZE CONFIG_NETDB_DNSCLIENT_MAXRESPONSE -#else -# define RECV_BUFFER_SIZE 96 -#endif +/* The size of an IP address */ #ifdef CONFIG_NETDB_DNSCLIENT_IPv6 # define ADDRLEN sizeof(struct sockaddr_in6) @@ -111,53 +87,6 @@ * Private Types ****************************************************************************/ -/* The DNS message header */ - -struct dns_hdr -{ - uint16_t id; - uint8_t flags1; - uint8_t flags2; - uint16_t numquestions; - uint16_t numanswers; - uint16_t numauthrr; - uint16_t numextrarr; -}; - -/* The DNS answer message structure */ - -struct dns_answer -{ - /* DNS answer record starts with either a domain name or a pointer - * to a name already present somewhere in the packet. - */ - - uint16_t type; - uint16_t class; - uint16_t ttl[2]; - uint16_t len; -#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 - struct in6_addr ipaddr; -#else - struct in_addr ipaddr; -#endif -}; - -struct namemap -{ - uint8_t state; - uint8_t tmr; - uint8_t retries; - uint8_t seqno; - uint8_t err; - char name[32]; -#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 - struct in6_addr ipaddr; -#else - struct in_addr ipaddr; -#endif -}; - /**************************************************************************** * Private Data ****************************************************************************/ @@ -210,24 +139,26 @@ static FAR unsigned char *dns_parse_name(FAR unsigned char *query) ****************************************************************************/ #ifdef CONFIG_NETDB_DNSCLIENT_IPv6 -static int dns_send_query(int sockfd, FAR const char *name, +static int dns_send_query(int sd, FAR const char *name, FAR struct sockaddr_in6 *addr) #else -static int dns_send_query(int sockfd, FAR const char *name, +static int dns_send_query(int sd, FAR const char *name, FAR struct sockaddr_in *addr) #endif { - register FAR struct dns_hdr *hdr; + register FAR struct dns_header_s *hdr; FAR char *query; FAR char *nptr; FAR const char *nameptr; uint8_t seqno = g_seqno++; static unsigned char endquery[] = {0, 0, 1, 0, 1}; char buffer[SEND_BUFFER_SIZE]; + int errcode; + int ret; int n; - hdr = (FAR struct dns_hdr *)buffer; - memset(hdr, 0, sizeof(struct dns_hdr)); + hdr = (FAR struct dns_header_s *)buffer; + memset(hdr, 0, sizeof(struct dns_header_s)); hdr->id = htons(seqno); hdr->flags1 = DNS_FLAG1_RD; hdr->numquestions = HTONS(1); @@ -252,8 +183,21 @@ static int dns_send_query(int sockfd, FAR const char *name, memcpy(query, endquery, 5); - return sendto(sockfd, buffer, query + 5 - buffer, - 0, (struct sockaddr*)addr, ADDRLEN); + /* Send the request */ + + ret = sendto(sd, buffer, query + 5 - buffer, 0, (struct sockaddr*)addr, + ADDRLEN); + + /* Return the negated errno value on sendto failure */ + + if (ret < 0) + { + errcode = get_errno(); + ndbg("ERROR: sendto failed: %d\n", errcode); + return -errcode; + } + + return OK; } /**************************************************************************** @@ -267,41 +211,45 @@ static int dns_send_query(int sockfd, FAR const char *name, #ifdef CONFIG_NETDB_DNSCLIENT_IPv6 # error "Not implemented" #else -static int dns_recv_response(int sockfd, FAR struct sockaddr_in *addr) +static int dns_recv_response(int sd, FAR struct sockaddr_in *addr) #endif { FAR unsigned char *nameptr; char buffer[RECV_BUFFER_SIZE]; - FAR struct dns_answer *ans; - FAR struct dns_hdr *hdr; + FAR struct dns_answer_s *ans; + FAR struct dns_header_s *hdr; #if 0 /* Not used */ uint8_t nquestions; #endif uint8_t nanswers; + int errcode; int ret; /* Receive the response */ - ret = recv(sockfd, buffer, RECV_BUFFER_SIZE, 0); + ret = recv(sd, buffer, RECV_BUFFER_SIZE, 0); if (ret < 0) { - return ret; + errcode = get_errno(); + ndbg("ERROR: recv failed: %d\n", errcode); + return -errcode; } - hdr = (FAR struct dns_hdr *)buffer; + hdr = (FAR struct dns_header_s *)buffer; - ndbg("ID %d\n", htons(hdr->id)); - ndbg("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE); - ndbg("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK); - ndbg("Num questions %d, answers %d, authrr %d, extrarr %d\n", - htons(hdr->numquestions), htons(hdr->numanswers), - htons(hdr->numauthrr), htons(hdr->numextrarr)); + nvdbg("ID %d\n", htons(hdr->id)); + nvdbg("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE); + nvdbg("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK); + nvdbg("Num questions %d, answers %d, authrr %d, extrarr %d\n", + htons(hdr->numquestions), htons(hdr->numanswers), + htons(hdr->numauthrr), htons(hdr->numextrarr)); - /* Check for error. If so, call callback to inform */ + /* Check for error */ if ((hdr->flags2 & DNS_FLAG2_ERR_MASK) != 0) { - return ERROR; + ndbg("ERROR: DNS reported error: flags2=%02x\n", hdr->flags2); + return -EPROTO; } /* We only care about the question(s) and the answers. The authrr @@ -352,7 +300,7 @@ static int dns_recv_response(int sockfd, FAR struct sockaddr_in *addr) /* Compressed name. */ nameptr += 2; - ndbg("Compressed answer\n"); + nvdbg("Compressed answer\n"); } else { @@ -361,11 +309,11 @@ static int dns_recv_response(int sockfd, FAR struct sockaddr_in *addr) nameptr = dns_parse_name(nameptr); } - ans = (struct dns_answer *)nameptr; - ndbg("Answer: type %x, class %x, ttl %x, length %x \n", /* 0x%08X\n", */ - htons(ans->type), htons(ans->class), - (htons(ans->ttl[0]) << 16) | htons(ans->ttl[1]), - htons(ans->len) /* , ans->ipaddr.s_addr */); + ans = (struct dns_answer_s *)nameptr; + nvdbg("Answer: type %x, class %x, ttl %x, length %x \n", /* 0x%08X\n", */ + htons(ans->type), htons(ans->class), + (htons(ans->ttl[0]) << 16) | htons(ans->ttl[1]), + htons(ans->len) /* , ans->ipaddr.s_addr */); /* Check for IP address type and Internet class. Others are discarded. */ @@ -375,11 +323,11 @@ static int dns_recv_response(int sockfd, FAR struct sockaddr_in *addr) { ans->ipaddr.s_addr = *(FAR uint32_t *)(nameptr + 10); - ndbg("IP address %d.%d.%d.%d\n", - (ans->ipaddr.s_addr ) & 0xff, - (ans->ipaddr.s_addr >> 8 ) & 0xff, - (ans->ipaddr.s_addr >> 16 ) & 0xff, - (ans->ipaddr.s_addr >> 24 ) & 0xff); + nvdbg("IP address %d.%d.%d.%d\n", + (ans->ipaddr.s_addr ) & 0xff, + (ans->ipaddr.s_addr >> 8 ) & 0xff, + (ans->ipaddr.s_addr >> 16 ) & 0xff, + (ans->ipaddr.s_addr >> 24 ) & 0xff); /* TODO: we should really check that this IP address is the one * we want. @@ -394,7 +342,7 @@ static int dns_recv_response(int sockfd, FAR struct sockaddr_in *addr) } } - return ERROR; + return -EADDRNOTAVAIL; } /**************************************************************************** @@ -405,29 +353,33 @@ static int dns_recv_response(int sockfd, FAR struct sockaddr_in *addr) * Name: dns_bind * * Description: - * Initialize the DNS resolver using the caller provided socket. + * Initialize the DNS resolver and return a socket bound to the DNS name + * server. The name server was previously selected via dns_server(). + * + * Input Parameters: + * None + * + * Returned Value: + * On success, the bound, non-negative socket descriptor is returned. A + * negated errno value is returned on any failure. * ****************************************************************************/ -int dns_bind(FAR int *sockfd) +int dns_bind(void) { struct timeval tv; + int errcode; + int sd; int ret; - /* If the socket is already open, then close it now */ - - if (*sockfd >= 0) - { - dns_free(sockfd); - } - /* Create a new socket */ - *sockfd = socket(PF_INET, SOCK_DGRAM, 0); - if (*sockfd < 0) + sd = socket(PF_INET, SOCK_DGRAM, 0); + if (sd < 0) { - ndbg("ERROR: socket() failed: %d\n", errno); - return ERROR; + errcode = get_errno(); + ndbg("ERROR: socket() failed: %d\n", errcode); + return -errcode; } /* Set up a receive timeout */ @@ -435,44 +387,23 @@ int dns_bind(FAR int *sockfd) tv.tv_sec = 30; tv.tv_usec = 0; - ret = setsockopt(*sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, - sizeof(struct timeval)); - + ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); if (ret < 0) { - ndbg("ERROR: setsockopt() failed: %d\n", errno); - close(*sockfd); - *sockfd = -1; - return ERROR; + errcode = get_errno(); + ndbg("ERROR: setsockopt() failed: %d\n", errcode); + close(sd); + return -errcode; } - return OK; -} - -/**************************************************************************** - * Name: dns_free - * - * Description: - * Release the DNS resolver by closing the socket. - * - ****************************************************************************/ - -int dns_free(FAR int *sockfd) -{ - if (*sockfd >= 0) - { - close(*sockfd); - *sockfd = -1; - } - - return OK; + return sd; } /**************************************************************************** * Name: dns_query * * Description: - * Using the DNS resolver socket (sockfd), look up the the 'hostname', and + * Using the DNS resolver socket (sd), look up the the 'hostname', and * return its IP address in 'ipaddr' * * Returned Value: @@ -480,35 +411,54 @@ int dns_free(FAR int *sockfd) * ****************************************************************************/ -int dns_query(int sockfd, FAR const char *hostname, FAR in_addr_t *ipaddr) +int dns_query(int sd, FAR const char *hostname, FAR in_addr_t *ipaddr) { #ifdef CONFIG_NETDB_DNSCLIENT_IPv6 struct sockaddr_in6 addr; #else struct sockaddr_in addr; #endif + int retries; + int ret; - /* First check if the host is an IP address. */ + /* Loop while receive timeout errors occur and there are remaining retries */ - if (!netlib_ipaddrconv(hostname, (uint8_t*)ipaddr)) + for (retries = 0; retries < 3; retries++) { - /* 'host' does not point to a valid address string. Try to resolve - * the host name to an IP address. - */ + /* Send the query */ - if (dns_whois(sockfd, hostname, &addr) < 0) + ret = dns_send_query(sd, hostname, &g_dnsserver); + if (ret < 0) { - /* Needs to set the errno here */ - - return ERROR; + ndbg("ERROR: dns_send_query failed: %d\n", ret); + return ret; } - /* Save the host address -- Needs fixed for IPv6 */ + /* Obtain the response */ - *ipaddr = addr.sin_addr.s_addr; - } + ret = dns_recv_response(sd, &addr); + if (ret >= 0) + { + /* Response received successfully */ + /* Save the host address -- Needs fixed for IPv6 */ - return OK; + *ipaddr = addr.sin_addr.s_addr; + return OK; + } + + /* Handler errors */ + + ndbg("ERROR: dns_recv_response failed: %d\n", ret); + + if (ret != -EAGAIN) + { + /* Some failure other than receive timeout occurred */ + + return ret; + } + } + + return -ETIMEDOUT; } /**************************************************************************** @@ -558,51 +508,3 @@ void dns_getserver(FAR struct in_addr *dnsserver) dnsserver->s_addr = g_dnsserver.sin_addr.s_addr; #endif } - -/**************************************************************************** - * Name: dns_whois - * - * Description: - * Get the binding for 'name' using the DNS server accessed via 'sockfd' - * - ****************************************************************************/ - -#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 -int dns_whois(int sockfd, FAR const char *name, - FAR struct sockaddr_in6 *addr) -#else -int dns_whois(int sockfd, FAR const char *name, - FAR struct sockaddr_in *addr) -#endif -{ - int retries; - int ret; - - /* Loop while receive timeout errors occur and there are remaining retries */ - - for (retries = 0; retries < 3; retries++) - { - ret = dns_send_query(sockfd, name, &g_dnsserver); - if (ret < 0) - { - return ERROR; - } - - ret = dns_recv_response(sockfd, addr); - if (ret >= 0) - { - /* Response received successfully */ - - return OK; - } - - else if (errno != EAGAIN) - { - /* Some failure other than receive timeout occurred */ - - return ERROR; - } - } - - return ERROR; -} diff --git a/libc/netdb/lib_gethostbynamer.c b/libc/netdb/lib_gethostbynamer.c index e7f3aab603..0ba4e1b6b5 100644 --- a/libc/netdb/lib_gethostbynamer.c +++ b/libc/netdb/lib_gethostbynamer.c @@ -47,9 +47,10 @@ #include -#include +#include #include "lib_internal.h" +#include "netdb/lib_dns.h" #ifdef CONFIG_LIBC_NETDB @@ -190,6 +191,43 @@ static int lib_numeric_address(FAR const char *name, FAR struct hostent *host, return 0; } +/**************************************************************************** + * Name: lib_dns_query + * + * Descriptions: + * Combines the operations of dns_bind(), dns_query(), and dns_free() to + * obtain the IP address ('ipaddr') associated with the 'hostname' in one + * operation. + * + ****************************************************************************/ + +#ifdef CONFIG_NETDB_DNSCLIENT_IPv6 +static int lib_dns_query(FAR const char *hostname, FAR struct in6_addr *ipaddr) +#else +static int lib_dns_query(FAR const char *hostname, FAR in_addr_t *ipaddr) +#endif +{ + int sd; + int ret; + + /* Create and bind a socket to the DNS server */ + + sd = dns_bind(); + if (sd < 0) + { + return sd; + } + + /* Perform the query to get the IP address */ + + ret = dns_query(sd, hostname, ipaddr); + + /* Release the socket */ + + close(sd); + return ret; +} + /**************************************************************************** * Name: lib_dns_lookup * @@ -242,11 +280,11 @@ static int lib_dns_lookup(FAR const char *name, FAR struct hostent *host, #ifdef CONFIG_NETDB_DNSCLIENT_IPv6 addrlen = sizeof(struct in6_addr); addrtype = AF_INET6; - ret = dns_gethostip(name, (FAR struct in6_addr *)ptr); + ret = lib_dns_query(name, (FAR struct in6_addr *)ptr); #else addrlen = sizeof(struct in6_addr); addrtype = AF_INET; - ret = dns_gethostip(name, (FAR in_addr_t *)ptr); + ret = lib_dns_query(name, (FAR in_addr_t *)ptr); #endif /* Was the DNS lookup successful? */ diff --git a/libc/netdb/lib_parsehostfile.c b/libc/netdb/lib_parsehostfile.c index d48b9e1015..def79926fd 100644 --- a/libc/netdb/lib_parsehostfile.c +++ b/libc/netdb/lib_parsehostfile.c @@ -92,6 +92,20 @@ int h_errno; /**************************************************************************** * Name: lib_skipspaces + * + * Description: + * Read from the 'stream' until a non-whitespace character is read or the + * end-of-line or end-of-file is encountered. + * + * Input Parameters: + * stream - The stream to read from + * nread - A count to the pointer of characters read. Will be + * incremented after each successful character read. + * + * Returned Value: + * The first non-whitespace character read. This will be the newline + * character of EROF if the end-of-line or end-of-file is encountered. + * ****************************************************************************/ static int lib_skipspaces(FAR FILE *stream, FAR size_t *nread) @@ -115,6 +129,20 @@ static int lib_skipspaces(FAR FILE *stream, FAR size_t *nread) /**************************************************************************** * Name: lib_skipline + * + * Description: + * Read from the 'stream' until the end-of-line or end-of-file is + * encountered. + * + * Input Parameters: + * stream - The stream to read from + * nread - A count to the pointer of characters read. Will be + * incremented after each successful character read. + * + * Returned Value: + * The character that terminated the line. This may be either the newline + * character or EOF. + * ****************************************************************************/ static int lib_skipline(FAR FILE *stream, FAR size_t *nread) @@ -139,12 +167,26 @@ static int lib_skipline(FAR FILE *stream, FAR size_t *nread) /**************************************************************************** * Name: lib_copystring * + * Description: + * Read from the 'stream' And copy each byte to the buffer at 'ptr' until + * either a whitespace delimiter, the end-of-line, or the end-of-file is + * encountered. + * + * Input Parameters: + * stream - The stream to read from + * ptr - The pointer to the buffer to receive the string + * nread - A count to the pointer of characters read. Will be + * incremented after each successful character read. + * buflen - The size of the buffer in bytes + * terminator - The actual character the terminated the copy is returned + * to this location. + * * Returned Value: * Number of bytes written to the buffer on success. 0 if the end of * file is encountered (or a read error occurs). A negated errno value on * any failure: * - * -ERANGE - Insufficient buffer space + * -ERANGE - Insufficient buffer space to hold the string. * ****************************************************************************/