NETDB: Add support for caching DNS name resultion mappings
This commit is contained in:
parent
fcaac468b1
commit
95424d9ef3
@ -10714,4 +10714,10 @@
|
||||
* include/nuttx/net/ and libc/netdb: Implement the low-level network DNS
|
||||
packet protocol to request and receive IPv6 address mappings
|
||||
(2015-07-12).
|
||||
|
||||
* libc/netdb: Add a default value for DNS server IP address. Make
|
||||
sure that the IP address has been initialized before permitting DNS
|
||||
queries (2015-07-13).
|
||||
* libc/netdb: Add support for a DNS host name resulution cache. This
|
||||
can save a lot of DNS name server lookups (but might also have the
|
||||
negative consequence of using stale IP address mappings (2015-07-13).
|
||||
|
||||
|
32
libc/Kconfig
32
libc/Kconfig
@ -548,10 +548,42 @@ config NETDB_DNSCLIENT_ENTRIES
|
||||
int "Number of DNS resolver entries"
|
||||
default 0 if DEFAULT_SMALL
|
||||
default 8 if !DEFAULT_SMALL
|
||||
range 0 255
|
||||
---help---
|
||||
Number of cached DNS resolver entries. Default: 8. Zero disables
|
||||
all cached name resolutions.
|
||||
|
||||
Disabling the DNS cache means that each access call to
|
||||
gethostbyname() will result in a new DNS network query. If
|
||||
CONFIG_NETDB_DNSCLIENT_ENTRIES is non-zero, then entries will be
|
||||
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
|
||||
might have undesirable side-effects (see help for
|
||||
CONFIG_NETDB_DNSCLIENT_LIFESEC).
|
||||
|
||||
config NETDB_DNSCLIENT_NAMESIZE
|
||||
int "Max size of a cached hostname"
|
||||
default 32
|
||||
---help---
|
||||
The size of a hostname string in the DNS resolver cache is fixed.
|
||||
This setting provides the maximum size of a hostname. Names longer
|
||||
than this will be aliased! Default: 32
|
||||
|
||||
config NETDB_DNSCLIENT_LIFESEC
|
||||
int "Life of a DNS cache entry (seconds)"
|
||||
default 3600
|
||||
---help---
|
||||
Cached entries in the name resolution cache older than this will not
|
||||
be used. Default: 1 hour. Zero means that entries will not expire.
|
||||
|
||||
Small values of CONFIG_NETDB_DNSCLIENT_LIFESEC may result in more
|
||||
network DNS queries; larger values can make a host unreachable for
|
||||
the entire duration of the timeout value. This might happen, for
|
||||
example, if the remote host was assigned a different IP address by
|
||||
a DHCP server.
|
||||
|
||||
config NETDB_DNSCLIENT_MAXRESPONSE
|
||||
int "Max response size"
|
||||
default 96
|
||||
|
@ -66,6 +66,14 @@
|
||||
# define CONFIG_NETDB_DNSCLIENT_MAXRESPONSE 96
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NETDB_DNSCLIENT_NAMESIZE
|
||||
# define CONFIG_NETDB_DNSCLIENT_NAMESIZE 32
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NETDB_DNSCLIENT_LIFESEC
|
||||
# define CONFIG_NETDB_DNSCLIENT_LIFESEC 3600
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -104,6 +112,15 @@ int dns_bind(void);
|
||||
* Using the DNS resolver socket (sd), look up the the 'hostname', and
|
||||
* return its IP address in 'ipaddr'
|
||||
*
|
||||
* Input Parameters:
|
||||
* sd - The socket descriptor previously initialized by dsn_bind().
|
||||
* hostname - The hostname string to be resolved.
|
||||
* addr - The location to return the IP address associated with the
|
||||
* hostname
|
||||
* addrlen - On entry, the size of the buffer backing up the 'addr'
|
||||
* pointer. On return, this location will hold the actual size of
|
||||
* the returned address.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) if the query was successful.
|
||||
*
|
||||
@ -112,6 +129,33 @@ int dns_bind(void);
|
||||
int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
|
||||
FAR socklen_t *addrlen);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_find_answer
|
||||
*
|
||||
* Description:
|
||||
* Check if we already have the resolved hostname address in the cache.
|
||||
*
|
||||
* Input Parameters:
|
||||
* hostname - The hostname string to be resolved.
|
||||
* addr - The location to return the IP address associated with the
|
||||
* hostname
|
||||
* addrlen - On entry, the size of the buffer backing up the 'addr'
|
||||
* pointer. On return, this location will hold the actual size of
|
||||
* the returned address.
|
||||
*
|
||||
* Returned Value:
|
||||
* If the host name was successfully found in the DNS name resolution
|
||||
* cache, zero (OK) will be returned. Otherwise, some negated errno
|
||||
* value will be returned, typically -ENOENT meaning that the hostname
|
||||
* was not found in the cache.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
int dns_find_answer(FAR const char *hostname, FAR struct sockaddr *addr,
|
||||
FAR socklen_t *addrlen);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
@ -52,6 +52,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
@ -76,26 +78,56 @@
|
||||
#define SEND_BUFFER_SIZE 64
|
||||
#define RECV_BUFFER_SIZE CONFIG_NETDB_DNSCLIENT_MAXRESPONSE
|
||||
|
||||
/* Use clock monotonic, if possible */
|
||||
|
||||
#ifdef CONFIG_CLOCK_MONOTONIC
|
||||
# define DNS_CLOCK CLOCK_MONOTONIC
|
||||
#else
|
||||
# define DNS_CLOCK CLOCK_REALTIME
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
/* This describes either an IPv4 or IPv6 address. It is essentially a named
|
||||
* alternative to sockaddr_storage.
|
||||
*/
|
||||
|
||||
union dns_server_u
|
||||
{
|
||||
struct sockaddr addr;
|
||||
struct sockaddr addr; /* Common address representation */
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct sockaddr_in ipv4;
|
||||
struct sockaddr_in ipv4; /* IPv4 address */
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct sockaddr_in6 ipv6;
|
||||
struct sockaddr_in6 ipv6; /* IPv6 address */
|
||||
#endif
|
||||
};
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
/* This described one entry in the cache of resolved hostnames */
|
||||
|
||||
struct dns_cache_s
|
||||
{
|
||||
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
|
||||
time_t ctime; /* Creation time */
|
||||
#endif
|
||||
char name[CONFIG_NETDB_DNSCLIENT_NAMESIZE];
|
||||
union dns_server_u addr; /* Resolved address */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static sem_t g_dns_sem; /* Protects g_seqno and DNS cache */
|
||||
static bool g_dns_initialized; /* DNS data structures initialized */
|
||||
static bool g_dns_address; /* We have the address of the DNS server */
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
static uint8_t g_dns_head; /* Head of the circular, DNS resolver cache */
|
||||
static uint8_t g_dns_tail; /* Tail of the circular, DNS resolver cache */
|
||||
#endif
|
||||
static uint8_t g_seqno; /* Sequence number of the next request */
|
||||
|
||||
/* The DNS server address */
|
||||
@ -118,10 +150,51 @@ static const uint16_t g_ipv6_hostaddr[8] =
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
/* This is the DNS resolver cache */
|
||||
|
||||
static struct dns_cache_s g_dns_cache[CONFIG_NETDB_DNSCLIENT_ENTRIES];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_semtake
|
||||
*
|
||||
* Description:
|
||||
* Take the DNS semaphore, ignoring errors do to the receipt of signals.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void dns_semtake(void)
|
||||
{
|
||||
int errcode = 0;
|
||||
int ret;
|
||||
|
||||
do
|
||||
{
|
||||
ret = sem_wait(&g_dns_sem);
|
||||
if (ret < 0)
|
||||
{
|
||||
errcode = get_errno();
|
||||
DEBUGASSERT(errcode == EINTR);
|
||||
}
|
||||
}
|
||||
while (ret < 0 && errcode == EINTR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_semgive
|
||||
*
|
||||
* Description:
|
||||
* Release the DNS semaphore
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define dns_semgive() sem_post(&g_dns_sem)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_initialize
|
||||
*
|
||||
@ -132,6 +205,14 @@ static const uint16_t g_ipv6_hostaddr[8] =
|
||||
|
||||
static bool dns_initialize(void)
|
||||
{
|
||||
/* Have DNS data structures been initialized? */
|
||||
|
||||
if (!g_dns_initialized)
|
||||
{
|
||||
sem_init(&g_dns_sem, 0, 1);
|
||||
g_dns_initialized = true;
|
||||
}
|
||||
|
||||
/* Has the DNS server IP address been assigned? */
|
||||
|
||||
if (!g_dns_address)
|
||||
@ -180,6 +261,83 @@ static bool dns_initialize(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_save_answer
|
||||
*
|
||||
* Description:
|
||||
* Same the last resolved hostname in the DNS cache
|
||||
*
|
||||
* Input Parameters:
|
||||
* hostname - The hostname string to be cached.
|
||||
* addr - The IP address associated with the hostname
|
||||
* addrlen - The size of the of the IP address.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
static void dns_save_answer(FAR const char *hostname,
|
||||
FAR const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
FAR struct dns_cache_s *entry;
|
||||
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
|
||||
struct timespec now;
|
||||
#endif
|
||||
int next;
|
||||
int ndx;
|
||||
|
||||
/* Get exclusive access to the DNS cache */
|
||||
|
||||
dns_semtake();
|
||||
|
||||
/* Get the index to the new head of the list */
|
||||
|
||||
ndx = g_dns_head;
|
||||
next = ndx + 1;
|
||||
if (next >= CONFIG_NETDB_DNSCLIENT_ENTRIES)
|
||||
{
|
||||
next = 0;
|
||||
}
|
||||
|
||||
/* If the next head pointer would match the tail index, then increment
|
||||
* the tail index, discarding the oldest mapping in the cache.
|
||||
*/
|
||||
|
||||
if (next == g_dns_tail)
|
||||
{
|
||||
int tmp = g_dns_tail + 1;
|
||||
if (tmp >= CONFIG_NETDB_DNSCLIENT_ENTRIES)
|
||||
{
|
||||
tmp = 0;
|
||||
}
|
||||
|
||||
g_dns_tail = tmp;
|
||||
}
|
||||
|
||||
/* Save the answer in the cache */
|
||||
|
||||
entry = &g_dns_cache[ndx];
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
|
||||
/* Get the current time, using CLOCK_MONOTONIC if possible */
|
||||
|
||||
(void)clock_settime(DNS_CLOCK, &now);
|
||||
entry->ctime = (time_t)now.tv_sec;
|
||||
#endif
|
||||
|
||||
strncpy(entry->name, hostname, CONFIG_NETDB_DNSCLIENT_NAMESIZE);
|
||||
memcpy(&entry->addr.addr, addr, addrlen);
|
||||
|
||||
/* Save the updated head index */
|
||||
|
||||
g_dns_head = next;
|
||||
dns_semgive();
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_parse_name
|
||||
*
|
||||
@ -223,13 +381,21 @@ static int dns_send_query(int sd, FAR const char *name,
|
||||
FAR uint8_t *dest;
|
||||
FAR uint8_t *nptr;
|
||||
FAR const char *src;
|
||||
uint8_t seqno = g_seqno++; /* REVISIT: Not thread safe */
|
||||
uint8_t buffer[SEND_BUFFER_SIZE];
|
||||
uint8_t seqno;
|
||||
socklen_t addrlen;
|
||||
int errcode;
|
||||
int ret;
|
||||
int n;
|
||||
|
||||
/* Increment the sequence number */
|
||||
|
||||
dns_semtake();
|
||||
seqno = g_seqno++;
|
||||
dns_semgive();
|
||||
|
||||
/* Initialize the request header */
|
||||
|
||||
hdr = (FAR struct dns_header_s *)buffer;
|
||||
memset(hdr, 0, sizeof(struct dns_header_s));
|
||||
hdr->id = htons(seqno);
|
||||
@ -556,6 +722,15 @@ int dns_bind(void)
|
||||
* Using the DNS resolver socket (sd), look up the the 'hostname', and
|
||||
* return its IP address in 'ipaddr'
|
||||
*
|
||||
* Input Parameters:
|
||||
* sd - The socket descriptor previously initialized by dsn_bind().
|
||||
* hostname - The hostname string to be resolved.
|
||||
* addr - The location to return the IP address associated with the
|
||||
* hostname
|
||||
* addrlen - On entry, the size of the buffer backing up the 'addr'
|
||||
* pointer. On return, this location will hold the actual size of
|
||||
* the returned address.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) if the query was successful.
|
||||
*
|
||||
@ -600,6 +775,11 @@ int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
|
||||
{
|
||||
/* IPv4 response received successfully */
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
/* Save the answer in the DNS cache */
|
||||
|
||||
dns_save_answer(hostname, addr, *addrlen);
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -657,6 +837,11 @@ int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
|
||||
{
|
||||
/* IPv6 response received successfully */
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
/* Save the answer in the DNS cache */
|
||||
|
||||
dns_save_answer(hostname, addr, *addrlen);
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -808,3 +993,140 @@ int dns_getserver(FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
||||
*addrlen = copylen;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_find_answer
|
||||
*
|
||||
* Description:
|
||||
* Check if we already have the resolved hostname address in the cache.
|
||||
*
|
||||
* Input Parameters:
|
||||
* hostname - The hostname string to be resolved.
|
||||
* addr - The location to return the IP address associated with the
|
||||
* hostname
|
||||
* addrlen - On entry, the size of the buffer backing up the 'addr'
|
||||
* pointer. On return, this location will hold the actual size of
|
||||
* the returned address.
|
||||
*
|
||||
* Returned Value:
|
||||
* If the host name was successfully found in the DNS name resolution
|
||||
* cache, zero (OK) will be returned. Otherwise, some negated errno
|
||||
* value will be returned, typically -ENOENT meaning that the hostname
|
||||
* was not found in the cache.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
int dns_find_answer(FAR const char *hostname, FAR struct sockaddr *addr,
|
||||
FAR socklen_t *addrlen)
|
||||
{
|
||||
FAR struct dns_cache_s *entry;
|
||||
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
|
||||
struct timespec now;
|
||||
uint32_t elapsed;
|
||||
int ret;
|
||||
#endif
|
||||
int next;
|
||||
int ndx;
|
||||
|
||||
/* Get exclusive access to the DNS cache */
|
||||
|
||||
dns_semtake();
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
|
||||
/* Get the current time, using CLOCK_MONOTONIC if possible */
|
||||
|
||||
ret = clock_settime(DNS_CLOCK, &now);
|
||||
#endif
|
||||
|
||||
/* REVISIT: This is not thread safe */
|
||||
|
||||
for (ndx = g_dns_tail; ndx != g_dns_head; ndx = next)
|
||||
{
|
||||
entry = &g_dns_cache[ndx];
|
||||
|
||||
/* Advance the index for the next time through the loop, handling
|
||||
* wrapping to the beginning of the circular buffer.
|
||||
*/
|
||||
|
||||
next = ndx + 1;
|
||||
if (next >= CONFIG_NETDB_DNSCLIENT_ENTRIES)
|
||||
{
|
||||
next = 0;
|
||||
}
|
||||
|
||||
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
|
||||
/* Check if this entry has expired
|
||||
* REVISIT: Does not this calculation assume that the sizeof(time_t)
|
||||
* is equal to the sizeof(uint32_t)?
|
||||
*/
|
||||
|
||||
elapsed = (uint32_t)now.tv_sec - (uint32_t)entry->ctime;
|
||||
if (ret >= 0 && elapsed > CONFIG_NETDB_DNSCLIENT_LIFESEC)
|
||||
{
|
||||
/* This entry has expired. Increment the tail index to exclude
|
||||
* this entry on future traversals.
|
||||
*/
|
||||
|
||||
g_dns_tail = next;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The entry has not expired, check for a name match. Notice that
|
||||
* because the names are truncated to CONFIG_NETDB_DNSCLIENT_NAMESIZE,
|
||||
* this has the possibility of aliasing two names and returning
|
||||
* the wrong entry from the cache.
|
||||
*/
|
||||
|
||||
if (strncmp(hostname, entry->name, CONFIG_NETDB_DNSCLIENT_NAMESIZE) == 0)
|
||||
{
|
||||
socklen_t inlen;
|
||||
|
||||
/* We have a match. Return the resolved host address */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (entry->addr.addr.sa_family == AF_INET)
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#endif
|
||||
{
|
||||
inlen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
else
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#endif
|
||||
{
|
||||
inlen = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
#endif
|
||||
/* Make sure that the address will fit in the caller-provided
|
||||
* buffer.
|
||||
*/
|
||||
|
||||
if (*addrlen < inlen)
|
||||
{
|
||||
ret = -ERANGE;
|
||||
goto errout_with_sem;
|
||||
}
|
||||
|
||||
/* Return the address information */
|
||||
|
||||
memcpy(addr, &entry->addr.addr, inlen);
|
||||
*addrlen = inlen;
|
||||
|
||||
dns_semgive();
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = -ENOENT;
|
||||
|
||||
errout_with_sem:
|
||||
dns_semgive();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
@ -194,6 +194,112 @@ static int lib_numeric_address(FAR const char *name, FAR struct hostent *host,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_find_answer
|
||||
*
|
||||
* Description:
|
||||
* Check if we previously resolved this hostname and if that resolved
|
||||
* address is already available in the DNS cache.
|
||||
*
|
||||
* Input Parameters:
|
||||
* name - The name of the host to find.
|
||||
* host - Caller provided location to return the host data.
|
||||
* buf - Caller provided buffer to hold string data associated with the
|
||||
* host data.
|
||||
* buflen - The size of the caller-provided buffer
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (0) is returned if the DNS lookup was successful.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETDB_DNSCLIENT
|
||||
static int lib_find_answer(FAR const char *name, FAR struct hostent *host,
|
||||
FAR char *buf, size_t buflen)
|
||||
{
|
||||
FAR struct hostent_info_s *info;
|
||||
FAR char *ptr;
|
||||
socklen_t addrlen;
|
||||
int addrtype;
|
||||
int namelen;
|
||||
int ret;
|
||||
|
||||
/* Verify that we have a buffer big enough to get started (it still may not
|
||||
* be big enough).
|
||||
*/
|
||||
|
||||
if (buflen <= sizeof(struct hostent_info_s))
|
||||
{
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/* Initialize buffers */
|
||||
|
||||
info = (FAR struct hostent_info_s *)buf;
|
||||
ptr = info->hi_data;
|
||||
buflen -= (sizeof(struct hostent_info_s) - 1);
|
||||
|
||||
memset(host, 0, sizeof(struct hostent));
|
||||
memset(info, 0, sizeof(struct hostent_info_s));
|
||||
|
||||
/* Try to get the host address using the DNS name server */
|
||||
|
||||
addrlen = buflen;
|
||||
ret = dns_find_answer(name, (FAR struct sockaddr *)ptr, &addrlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* No, nothing found in the cache */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the address type; verify the address size. */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (((FAR struct sockaddr_in *)ptr)->sin_family == AF_INET)
|
||||
#endif
|
||||
{
|
||||
DEBUGASSERT(addrlen == sizeof(struct sockaddr_in));
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
addrtype = AF_INET;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
DEBUGASSERT(addrlen == sizeof(struct sockaddr_in6));
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
addrtype = AF_INET6;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Yes.. Return the address that we obtained from the DNS cache. */
|
||||
|
||||
info->hi_addrlist[0] = ptr;
|
||||
host->h_addr_list = info->hi_addrlist;
|
||||
host->h_addrtype = addrtype;
|
||||
host->h_length = addrlen;
|
||||
|
||||
ptr += addrlen;
|
||||
buflen -= addrlen;
|
||||
|
||||
/* And copy the host name */
|
||||
|
||||
namelen = strlen(name);
|
||||
if (addrlen + namelen + 1 > buflen)
|
||||
{
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
strncpy(ptr, name, buflen);
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_NETDB_DNSCLIENT */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_dns_query
|
||||
*
|
||||
@ -524,6 +630,18 @@ int gethostbyname_r(FAR const char *name, FAR struct hostent *host,
|
||||
/* REVISIT: Not implemented */
|
||||
|
||||
#ifdef CONFIG_NETDB_DNSCLIENT
|
||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||
/* Check if we already have this hostname mapping cached */
|
||||
|
||||
ret = lib_find_answer(name, host, buf, buflen);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Found the address mapping in the cache */
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Try to get the host address using the DNS name server */
|
||||
|
||||
ret = lib_dns_lookup(name, host, buf, buflen);
|
||||
|
Loading…
x
Reference in New Issue
Block a user