libs/libc/netdb: Support multiple IP addresses per hostname

This commit is contained in:
Juha Niskanen 2018-11-23 07:09:47 -06:00 committed by Gregory Nutt
parent d2a11cdea5
commit 3e7281e699
8 changed files with 213 additions and 168 deletions

View file

@ -90,10 +90,12 @@
#define DNS_RECTYPE_NSEC 47 /* RFC 4034 Next-Secure record */
#define DNS_RECTYPE_NSEC3 50 /* RFC 5155 NSEC record version 3 */
#define DNS_RECTYPE_NSEC3PARAM 51 /* RFC 5155 NSEC3 parameters */
#define DNS_RECTYPE_OPENPGPKEY 61 /* RFC 7929 OpenPGP public key record */
#define DNS_RECTYPE_PTR 12 /* RFC 1035 Pointer record */
#define DNS_RECTYPE_RRSIG 46 /* RFC 4034 DNSSEC signature */
#define DNS_RECTYPE_RP 17 /* RFC 1183 Responsible person */
#define DNS_RECTYPE_SIG 24 /* RFC 2535 Signature */
#define DNS_RECTYPE_SMIMEA 53 /* RFC 8162 S/MIME cert association */
#define DNS_RECTYPE_SOA 6 /* RFC 1035 and RFC 2308 Start of [a zone of] authority record */
#define DNS_RECTYPE_SRV 33 /* RFC 2782 Service locator */
#define DNS_RECTYPE_SSHFP 44 /* RFC 4255 SSH Public Key Fingerprint */
@ -101,7 +103,8 @@
#define DNS_RECTYPE_TKEY 249 /* RFC 2930 Secret key record */
#define DNS_RECTYPE_TLSA 52 /* RFC 6698 TLSA certificate association */
#define DNS_RECTYPE_TSIG 250 /* RFC 2845 Transaction Signature */
#define DNS_RECTYPE_TXT 16 /* RFC 1035[1] Text record */
#define DNS_RECTYPE_TXT 16 /* RFC 1035 Text record */
#define DNS_RECTYPE_URI 256 /* RFC 7553 Uniform Resource Identifier */
#define DNS_RECTYPE_ALL 255 /* RFC 1035 All cached records */
#define DNS_RECTYPE_AXFR 252 /* RFC 1035 Authoritative Zone Transfer */
@ -156,7 +159,7 @@ struct dns_question_s
/* The DNS answer message structure */
struct dns_answer_s
begin_packed_struct struct dns_answer_s
{
uint16_t type;
uint16_t class;
@ -172,7 +175,7 @@ struct dns_answer_s
struct in6_addr ipv6;
#endif
} u;
};
} end_packed_struct;
/* The type of the callback from dns_foreach_nameserver() */

View file

@ -102,6 +102,13 @@ config NETDB_DNSCLIENT_MAXRESPONSE
can be received by the DNS resolver. The default is 96 but may
need to be larger on enterprise networks (perhaps 176).
config NETDB_DNSCLIENT_MAXIP
int "Max number of IP addresses per host"
default 1
---help---
This setting determines the maximum number of IP addresses
stored to the name resolution cache for a given host.
config NETDB_DNSCLIENT_RECV_TIMEOUT
int "DNS receive timeout"
default 30

View file

@ -62,12 +62,14 @@
# define CONFIG_NETDB_DNSCLIENT_ENTRIES 4
#endif
#define RESOLV_ENTRIES CONFIG_NETDB_DNSCLIENT_ENTRIES
#ifndef CONFIG_NETDB_DNSCLIENT_MAXRESPONSE
# define CONFIG_NETDB_DNSCLIENT_MAXRESPONSE 96
#endif
#ifndef CONFIG_NETDB_DNSCLIENT_MAXIP
# define CONFIG_NETDB_DNSCLIENT_MAXIP 1
#endif
#ifndef CONFIG_NETDB_DNSCLIENT_NAMESIZE
# define CONFIG_NETDB_DNSCLIENT_NAMESIZE 32
#endif
@ -91,7 +93,7 @@
* alternative to sockaddr_storage.
*/
union dns_server_u
union dns_addr_u
{
struct sockaddr addr; /* Common address representation */
#ifdef CONFIG_NET_IPv4
@ -118,7 +120,7 @@ extern "C"
#ifndef CONFIG_NETDB_RESOLVCONF
/* The DNS server address */
EXTERN union dns_server_u g_dns_server;
EXTERN union dns_addr_u g_dns_server;
EXTERN bool g_dns_address; /* true: We have the address of the DNS server */
#endif
@ -184,19 +186,19 @@ int dns_bind(void);
* 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.
* addr - The location to return the IP addresses associated with the
* hostname.
* naddr - On entry, the count of addresses backing up the 'addr'
* pointer. On return, this location will hold the actual count of
* the returned addresses.
*
* Returned Value:
* Returns zero (OK) if the query was successful.
*
****************************************************************************/
int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
FAR socklen_t *addrlen);
int dns_query(int sd, FAR const char *hostname, FAR union dns_addr_u *addr,
FAR int *naddr);
/****************************************************************************
* Name: dns_save_answer
@ -206,8 +208,8 @@ int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
*
* 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.
* addr - The IP addresses associated with the hostname.
* naddr - The count of the IP addresses.
*
* Returned Value:
* None
@ -216,7 +218,7 @@ int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
void dns_save_answer(FAR const char *hostname,
FAR const struct sockaddr *addr, socklen_t addrlen);
FAR const union dns_addr_u *addr, int naddr);
#endif
/****************************************************************************
@ -227,11 +229,11 @@ void dns_save_answer(FAR const char *hostname,
*
* 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.
* addr - The location to return the IP addresses associated with the
* hostname.
* naddr - On entry, the count of addresses backing up the 'addr'
* pointer. On return, this location will hold the actual count of
* the returned addresses.
*
* Returned Value:
* If the host name was successfully found in the DNS name resolution
@ -242,8 +244,8 @@ void dns_save_answer(FAR const char *hostname,
****************************************************************************/
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
int dns_find_answer(FAR const char *hostname, FAR struct sockaddr *addr,
FAR socklen_t *addrlen);
int dns_find_answer(FAR const char *hostname, FAR union dns_addr_u *addr,
FAR int *naddr);
#endif
#undef EXTERN

View file

@ -60,7 +60,7 @@
#ifndef CONFIG_NETDB_RESOLVCONF
/* The DNS server address */
union dns_server_u g_dns_server;
union dns_addr_u g_dns_server;
bool g_dns_address; /* true: We have the address of the DNS server */
#endif

View file

@ -42,6 +42,7 @@
#include <sys/time.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
@ -65,15 +66,20 @@
* Private Types
****************************************************************************/
/* This described one entry in the cache of resolved hostnames */
/* This described one entry in the cache of resolved hostnames.
*
* REVISIT: this consumes extra space, especially when multiple
* addresses per name are stored.
*/
struct dns_cache_s
{
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
time_t ctime; /* Creation time */
time_t ctime; /* Creation time */
#endif
char name[CONFIG_NETDB_DNSCLIENT_NAMESIZE];
union dns_server_u addr; /* Resolved address */
char name[CONFIG_NETDB_DNSCLIENT_NAMESIZE];
uint8_t naddr; /* How many addresses per name */
union dns_addr_u addr[CONFIG_NETDB_DNSCLIENT_MAXIP]; /* Resolved address */
};
/****************************************************************************
@ -103,8 +109,8 @@ static struct dns_cache_s g_dns_cache[CONFIG_NETDB_DNSCLIENT_ENTRIES];
*
* 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.
* addr - The IP addresses associated with the hostname.
* naddr - The count of the IP addresses.
*
* Returned Value:
* None
@ -112,7 +118,7 @@ static struct dns_cache_s g_dns_cache[CONFIG_NETDB_DNSCLIENT_ENTRIES];
****************************************************************************/
void dns_save_answer(FAR const char *hostname,
FAR const struct sockaddr *addr, socklen_t addrlen)
FAR const union dns_addr_u *addr, int naddr)
{
FAR struct dns_cache_s *entry;
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
@ -121,6 +127,9 @@ void dns_save_answer(FAR const char *hostname,
int next;
int ndx;
naddr = MIN(naddr, CONFIG_NETDB_DNSCLIENT_MAXIP);
DEBUGASSERT(naddr >= 1 && naddr <= UCHAR_MAX);
/* Get exclusive access to the DNS cache */
dns_semtake();
@ -161,7 +170,8 @@ void dns_save_answer(FAR const char *hostname,
#endif
strncpy(entry->name, hostname, CONFIG_NETDB_DNSCLIENT_NAMESIZE);
memcpy(&entry->addr.addr, addr, addrlen);
memcpy(&entry->addr, addr, naddr * sizeof(*addr));
entry->naddr = naddr;
/* Save the updated head index */
@ -177,11 +187,11 @@ void dns_save_answer(FAR const char *hostname,
*
* 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.
* addr - The location to return the IP addresses associated with the
* hostname.
* naddr - On entry, the count of addresses backing up the 'addr'
* pointer. On return, this location will hold the actual count of
* the returned addresses.
*
* Returned Value:
* If the host name was successfully found in the DNS name resolution
@ -191,8 +201,8 @@ void dns_save_answer(FAR const char *hostname,
*
****************************************************************************/
int dns_find_answer(FAR const char *hostname, FAR struct sockaddr *addr,
FAR socklen_t *addrlen)
int dns_find_answer(FAR const char *hostname, FAR union dns_addr_u *addr,
FAR int *naddr)
{
FAR struct dns_cache_s *entry;
#if CONFIG_NETDB_DNSCLIENT_LIFESEC > 0
@ -221,8 +231,6 @@ int dns_find_answer(FAR const char *hostname, FAR struct sockaddr *addr,
ret = clock_gettime(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];
@ -263,41 +271,17 @@ int dns_find_answer(FAR const char *hostname, FAR struct sockaddr *addr,
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
#ifdef CONFIG_NET_IPv6
if (entry->addr.addr.sa_family == AF_INET)
#endif
{
inlen = sizeof(struct sockaddr_in);
}
#endif
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
else
#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;
}
*naddr = MIN(*naddr, entry->naddr);
/* Return the address information */
memcpy(addr, &entry->addr.addr, inlen);
*addrlen = inlen;
memcpy(addr, &entry->addr, *naddr * sizeof(*addr));
dns_semgive();
return OK;
@ -307,7 +291,6 @@ int dns_find_answer(FAR const char *hostname, FAR struct sockaddr *addr,
ret = -ENOENT;
errout_with_sem:
dns_semgive();
return ret;
}

View file

@ -90,7 +90,7 @@ static FAR char *find_spaces(FAR char *ptr)
int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
{
union dns_server_u u;
union dns_addr_u u;
FAR FILE *stream;
char line[DNS_MAX_LINE];
FAR char *addrstr;

View file

@ -88,8 +88,8 @@ struct dns_query_s
int sd; /* DNS server socket */
int result; /* Explanation of the failure */
FAR const char *hostname; /* Hostname to lookup */
FAR struct sockaddr *addr; /* Location to return host address */
FAR socklen_t *addrlen; /* Length of the address */
FAR union dns_addr_u *addr; /* Location to return host address */
FAR int *naddr; /* Number of returned addresses */
};
/* Query info to check response against. */
@ -205,7 +205,7 @@ static inline uint16_t dns_alloc_id(void)
****************************************************************************/
static int dns_send_query(int sd, FAR const char *name,
FAR union dns_server_u *uaddr, uint16_t rectype,
FAR union dns_addr_u *uaddr, uint16_t rectype,
FAR struct dns_query_info_s *qinfo)
{
FAR struct dns_header_s *hdr;
@ -337,10 +337,13 @@ static int dns_send_query(int sd, FAR const char *name,
* Description:
* Called when new UDP data arrives
*
* Returned Value:
* Returns number of valid IP address responses. Negated errno value is
* returned in all other cases.
*
****************************************************************************/
static int dns_recv_response(int sd, FAR struct sockaddr *addr,
FAR socklen_t *addrlen,
static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
FAR struct dns_query_info_s *qinfo)
{
FAR uint8_t *nameptr;
@ -352,8 +355,9 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
FAR struct dns_question_s *que;
uint16_t nquestions;
uint16_t nanswers;
union dns_server_u recvaddr;
union dns_addr_u recvaddr;
socklen_t raddrlen;
int naddr_read;
int errcode;
int ret;
@ -535,6 +539,9 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
nameptr += sizeof(struct dns_question_s);
ret = OK;
naddr_read = 0;
for (; nanswers > 0; nanswers--)
{
/* Each answer starts with a name */
@ -542,7 +549,8 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
nameptr = dns_parse_name(nameptr, endofbuffer);
if (nameptr == endofbuffer)
{
return -EILSEQ;
ret = -EILSEQ;
break;
}
ans = (FAR struct dns_answer_s *)nameptr;
@ -562,7 +570,7 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
ans->len == HTONS(4) &&
nameptr + 10 + 4 <= endofbuffer)
{
ans->u.ipv4.s_addr = *(FAR uint32_t *)(nameptr + 10);
nameptr += 10 + 4;
ninfo("IPv4 address: %d.%d.%d.%d\n",
(ans->u.ipv4.s_addr ) & 0xff,
@ -570,21 +578,25 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
(ans->u.ipv4.s_addr >> 16) & 0xff,
(ans->u.ipv4.s_addr >> 24) & 0xff);
if (*addrlen >= sizeof(struct sockaddr_in))
if (naddr_read < *naddr)
{
FAR struct sockaddr_in *inaddr;
inaddr = (FAR struct sockaddr_in *)addr;
inaddr->sin_family = AF_INET;
inaddr->sin_port = 0;
inaddr->sin_addr.s_addr = ans->u.ipv4.s_addr;
inaddr = (FAR struct sockaddr_in *)&addr[naddr_read].addr;
inaddr->sin_family = AF_INET;
inaddr->sin_port = 0;
inaddr->sin_addr.s_addr = ans->u.ipv4.s_addr;
*addrlen = sizeof(struct sockaddr_in);
return OK;
naddr_read++;
if (naddr_read >= *naddr)
{
break;
}
}
else
{
return -ERANGE;
ret = -ERANGE;
break;
}
}
else
@ -595,7 +607,7 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
ans->len == HTONS(16) &&
nameptr + 10 + 16 <= endofbuffer)
{
memcpy(&ans->u.ipv6.s6_addr, nameptr + 10, 16);
nameptr += 10 + 16;
ninfo("IPv6 address: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
htons(ans->u.ipv6.s6_addr[7]), htons(ans->u.ipv6.s6_addr[6]),
@ -603,21 +615,25 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
htons(ans->u.ipv6.s6_addr[3]), htons(ans->u.ipv6.s6_addr[2]),
htons(ans->u.ipv6.s6_addr[1]), htons(ans->u.ipv6.s6_addr[0]));
if (*addrlen >= sizeof(struct sockaddr_in6))
if (naddr_read < *naddr)
{
FAR struct sockaddr_in6 *inaddr;
inaddr = (FAR struct sockaddr_in6 *)addr;
inaddr->sin6_family = AF_INET;
inaddr = (FAR struct sockaddr_in6 *)&addr[naddr_read].addr;
inaddr->sin6_family = AF_INET6;
inaddr->sin6_port = 0;
memcpy(inaddr->sin6_addr.s6_addr, ans->u.ipv6.s6_addr, 16);
*addrlen = sizeof(struct sockaddr_in6);
return OK;
naddr_read++;
if (naddr_read >= *naddr)
{
break;
}
}
else
{
return -ERANGE;
ret = -ERANGE;
break;
}
}
else
@ -627,7 +643,17 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
}
}
return -EADDRNOTAVAIL;
if (naddr_read == 0 && ret == OK)
{
ret = -EADDRNOTAVAIL;
}
else if (naddr_read > 0 && ret != OK)
{
nwarn("Got an IP, but further parse returned %d\n", ret);
}
*naddr = naddr_read;
return (naddr_read > 0) ? naddr_read : ret;
}
/****************************************************************************
@ -684,7 +710,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
/* Send the IPv4 query */
ret = dns_send_query(query->sd, query->hostname,
(FAR union dns_server_u *)addr,
(FAR union dns_addr_u *)addr,
DNS_RECTYPE_A, &qinfo);
if (ret < 0)
{
@ -699,7 +725,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
/* Obtain the IPv4 response */
ret = dns_recv_response(query->sd, query->addr, query->addrlen,
ret = dns_recv_response(query->sd, query->addr, query->naddr,
&qinfo);
if (ret >= 0)
{
@ -709,7 +735,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
/* Save the answer in the DNS cache */
dns_save_answer(query->hostname, query->addr,
*query->addrlen);
*query->naddr);
#endif
/* Return 1 to indicate to (1) stop the traversal, and (2)
* indicate that the address was found.
@ -749,7 +775,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
#ifdef CONFIG_NET_IPv6
/* Is this an IPv6 address? */
if (query->addr->sa_family == AF_INET6)
if (addr->sa_family == AF_INET6)
{
/* Yes.. verify the address size */
@ -767,7 +793,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
/* Send the IPv6 query */
ret = dns_send_query(query->sd, query->hostname,
(FAR union dns_server_u *)addr,
(FAR union dns_addr_u *)addr,
DNS_RECTYPE_AAAA, &qinfo);
if (ret < 0)
{
@ -782,7 +808,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
/* Obtain the IPv6 response */
ret = dns_recv_response(query->sd, query->addr, query->addrlen,
ret = dns_recv_response(query->sd, query->addr, query->naddr,
&qinfo);
if (ret >= 0)
{
@ -791,7 +817,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
/* Save the answer in the DNS cache */
dns_save_answer(query->hostname, query->addr, *query->addrlen);
dns_save_answer(query->hostname, query->addr, *query->naddr);
#endif
/* Return 1 to indicate to (1) stop the traversal, and (2)
* indicate that the address was found.
@ -859,19 +885,19 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
* 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.
* addr - The location to return the IP addresses associated with the
* hostname.
* naddr - On entry, the count of addresses backing up the 'addr'
* pointer. On return, this location will hold the actual count of
* the returned addresses.
*
* Returned Value:
* Returns zero (OK) if the query was successful.
*
****************************************************************************/
int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
FAR socklen_t *addrlen)
int dns_query(int sd, FAR const char *hostname, FAR union dns_addr_u *addr,
FAR int *naddr)
{
FAR struct dns_query_s query;
int ret;
@ -882,7 +908,7 @@ int dns_query(int sd, FAR const char *hostname, FAR struct sockaddr *addr,
query.result = -EADDRNOTAVAIL;
query.hostname = hostname;
query.addr = addr;
query.addrlen = addrlen;
query.naddr = naddr;
/* Perform the query. dns_foreach_nameserver() will return:
*

View file

@ -66,7 +66,7 @@
struct hostent_info_s
{
FAR char *hi_addrlist[2];
FAR char *hi_addrlist[CONFIG_NETDB_DNSCLIENT_MAXIP + 1];
char hi_data[1];
};
@ -360,9 +360,11 @@ static int lib_find_answer(FAR const char *name, FAR struct hostent *host,
FAR char *ptr;
FAR void *addrdata;
socklen_t addrlen;
int naddr;
int addrtype;
int namelen;
int ret;
int i;
/* Verify that we have a buffer big enough to get started (it still may not
* be big enough).
@ -379,13 +381,20 @@ static int lib_find_answer(FAR const char *name, FAR struct hostent *host,
ptr = info->hi_data;
buflen -= (sizeof(struct hostent_info_s) - 1);
/* Verify again that there is space for at least one address. */
if (buflen < sizeof(union dns_addr_u))
{
return -ERANGE;
}
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);
naddr = buflen / sizeof(union dns_addr_u);
ret = dns_find_answer(name, (FAR union dns_addr_u *)ptr, &naddr);
if (ret < 0)
{
/* No, nothing found in the cache */
@ -393,41 +402,45 @@ static int lib_find_answer(FAR const char *name, FAR struct hostent *host,
return ret;
}
/* Get the address type; verify the address size. */
DEBUGASSERT(naddr <= CONFIG_NETDB_DNSCLIENT_MAXIP);
/* Get the address type. */
for (i = 0; i < naddr; i++)
{
#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
if (((FAR struct sockaddr_in *)ptr)->sin_family == AF_INET)
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;
addrdata = &((FAR struct sockaddr_in *)ptr)->sin_addr;
}
{
addrlen = sizeof(struct sockaddr_in);
addrtype = AF_INET;
addrdata = &((FAR struct sockaddr_in *)ptr)->sin_addr;
}
#endif
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
else
else
#endif
{
DEBUGASSERT(addrlen == sizeof(struct sockaddr_in6));
addrlen = sizeof(struct sockaddr_in6);
addrtype = AF_INET6;
addrdata = &((FAR struct sockaddr_in6 *)ptr)->sin6_addr;
{
addrlen = sizeof(struct sockaddr_in6);
addrtype = AF_INET6;
addrdata = &((FAR struct sockaddr_in6 *)ptr)->sin6_addr;
}
#endif
/* REVISIT: This assumes addresses are all either IPv4 or IPv6. */
info->hi_addrlist[i] = addrdata;
host->h_addrtype = addrtype;
host->h_length = addrlen;
ptr += sizeof(union dns_addr_u);
buflen -= sizeof(union dns_addr_u);
}
#endif
/* Yes.. Return the address that we obtained from the DNS cache. */
info->hi_addrlist[0] = addrdata;
host->h_addr_list = info->hi_addrlist;
host->h_addrtype = addrtype;
host->h_length = addrlen;
ptr += addrlen;
buflen -= addrlen;
host->h_addr_list = info->hi_addrlist;
/* And copy name */
@ -459,7 +472,7 @@ static int lib_find_answer(FAR const char *name, FAR struct hostent *host,
#ifdef CONFIG_NETDB_DNSCLIENT
static int lib_dns_query(FAR const char *hostname,
FAR struct sockaddr *addr, socklen_t *addrlen)
FAR union dns_addr_u *addr, int *naddr)
{
int sd;
int ret;
@ -474,7 +487,7 @@ static int lib_dns_query(FAR const char *hostname,
/* Perform the query to get the IP address */
ret = dns_query(sd, hostname, addr, addrlen);
ret = dns_query(sd, hostname, addr, naddr);
/* Release the socket */
@ -509,9 +522,11 @@ static int lib_dns_lookup(FAR const char *name, FAR struct hostent *host,
FAR char *ptr;
FAR void *addrdata;
socklen_t addrlen;
int naddr;
int addrtype;
int namelen;
int ret;
int i;
/* Verify that we have a buffer big enough to get started (it still may not
* be big enough).
@ -528,26 +543,36 @@ static int lib_dns_lookup(FAR const char *name, FAR struct hostent *host,
ptr = info->hi_data;
buflen -= (sizeof(struct hostent_info_s) - 1);
/* Verify again that there is space for at least one address. */
if (buflen < sizeof(union dns_addr_u))
{
return -ERANGE;
}
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 = lib_dns_query(name, (FAR struct sockaddr *)ptr, &addrlen);
/* Was the DNS lookup successful? */
if (ret >= 0)
naddr = buflen / sizeof(union dns_addr_u);
ret = lib_dns_query(name, (FAR union dns_addr_u *)ptr, &naddr);
if (ret < 0)
{
/* Get the address type; verify the address size. */
return ret;
}
/* We can read more than maximum, limit here. */
naddr = MIN(naddr, CONFIG_NETDB_DNSCLIENT_MAXIP);
for (i = 0; i < naddr; i++)
{
#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;
addrdata = &((FAR struct sockaddr_in *)ptr)->sin_addr;
@ -559,40 +584,39 @@ static int lib_dns_lookup(FAR const char *name, FAR struct hostent *host,
else
#endif
{
DEBUGASSERT(addrlen == sizeof(struct sockaddr_in6));
addrlen = sizeof(struct sockaddr_in6);
addrtype = AF_INET6;
addrdata = &((FAR struct sockaddr_in6 *)ptr)->sin6_addr;
}
#endif
/* Yes.. Return the address that we obtained from the DNS name server. */
/* REVISIT: This assumes addresses are all either IPv4 or IPv6. */
info->hi_addrlist[0] = addrdata;
host->h_addr_list = info->hi_addrlist;
info->hi_addrlist[i] = addrdata;
host->h_addrtype = addrtype;
host->h_length = addrlen;
ptr += addrlen;
buflen -= addrlen;
/* And copy name */
namelen = strlen(name);
if ((namelen + 1) > buflen)
{
return -ERANGE;
}
strncpy(ptr, name, buflen);
/* Set the address to h_name */
host->h_name = ptr;
return OK;
ptr += sizeof(union dns_addr_u);
buflen -= sizeof(union dns_addr_u);
}
return ret;
host->h_addr_list = info->hi_addrlist;
/* And copy name */
namelen = strlen(name);
if ((namelen + 1) > buflen)
{
return -ERANGE;
}
strncpy(ptr, name, buflen);
/* Set the address to h_name */
host->h_name = ptr;
return OK;
}
#endif /* CONFIG_NETDB_DNSCLIENT */