Repartitioning of DNS client logic in preparation for IPv6 support

- 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.
This commit is contained in:
Gregory Nutt 2015-07-12 09:19:40 -06:00
parent 14dedf3dea
commit 5ace3311d9
7 changed files with 266 additions and 391 deletions

View File

@ -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.

View File

@ -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 <gnutt@nuttx.org>
*
* 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 */

View File

@ -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 <gnutt@nuttx.org>
#
# 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

View File

@ -1,95 +0,0 @@
/****************************************************************************
* libc/netdb/dns_gethostip.c
*
* Copyright (C) 2007, 2009, 2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Based heavily on portions of uIP:
*
* Author: Adam Dunkels <adam@dunkels.com>
* 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 <nuttx/config.h>
#include <nuttx/net/dnsclient.h>
/****************************************************************************
* 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;
}

View File

@ -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 <gnutt@nuttx.org>
*
* Based heavily on portions of uIP:
@ -60,46 +58,24 @@
#include <arpa/inet.h>
#include <netinet/in.h>
#include <nuttx/net/dnsclient.h>
#include <apps/netutils/netlib.h>
#include <nuttx/net/dns.h>
#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;
}

View File

@ -47,9 +47,10 @@
#include <arpa/inet.h>
#include <nuttx/net/dnsclient.h>
#include <nuttx/net/dns.h>
#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? */

View File

@ -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.
*
****************************************************************************/