libs/libc/netdb: Support multiple IP addresses per hostname
This commit is contained in:
parent
d2a11cdea5
commit
3e7281e699
8 changed files with 213 additions and 168 deletions
|
|
@ -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() */
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue