libc/netdb: Should query both IPv4 and IPv6 address regardless the server address type
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com> Change-Id: I1ba17b3078837cd5b857a13f104550613050d3e0
This commit is contained in:
parent
2e57583219
commit
7f2810f73a
@ -324,7 +324,7 @@ static int dns_send_query(int sd, FAR const char *name,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int naddr,
|
||||||
FAR struct dns_query_info_s *qinfo)
|
FAR struct dns_query_info_s *qinfo)
|
||||||
{
|
{
|
||||||
FAR uint8_t *nameptr;
|
FAR uint8_t *nameptr;
|
||||||
@ -339,6 +339,11 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
|||||||
int naddr_read;
|
int naddr_read;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (naddr <= 0)
|
||||||
|
{
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Receive the response */
|
/* Receive the response */
|
||||||
|
|
||||||
ret = _NX_RECV(sd, buffer, RECV_BUFFER_SIZE, 0);
|
ret = _NX_RECV(sd, buffer, RECV_BUFFER_SIZE, 0);
|
||||||
@ -456,6 +461,7 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
|||||||
if (nameptr == endofbuffer)
|
if (nameptr == endofbuffer)
|
||||||
{
|
{
|
||||||
ret = -EILSEQ;
|
ret = -EILSEQ;
|
||||||
|
nwarn("Further parse returned %d\n", ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,6 +482,8 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
|||||||
ans->len == HTONS(4) &&
|
ans->len == HTONS(4) &&
|
||||||
nameptr + 10 + 4 <= endofbuffer)
|
nameptr + 10 + 4 <= endofbuffer)
|
||||||
{
|
{
|
||||||
|
FAR struct sockaddr_in *inaddr;
|
||||||
|
|
||||||
nameptr += 10 + 4;
|
nameptr += 10 + 4;
|
||||||
|
|
||||||
ninfo("IPv4 address: %d.%d.%d.%d\n",
|
ninfo("IPv4 address: %d.%d.%d.%d\n",
|
||||||
@ -484,22 +492,12 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
|||||||
(ans->u.ipv4.s_addr >> 16) & 0xff,
|
(ans->u.ipv4.s_addr >> 16) & 0xff,
|
||||||
(ans->u.ipv4.s_addr >> 24) & 0xff);
|
(ans->u.ipv4.s_addr >> 24) & 0xff);
|
||||||
|
|
||||||
if (naddr_read < *naddr)
|
|
||||||
{
|
|
||||||
FAR struct sockaddr_in *inaddr;
|
|
||||||
|
|
||||||
inaddr = &addr[naddr_read].ipv4;
|
inaddr = &addr[naddr_read].ipv4;
|
||||||
inaddr->sin_family = AF_INET;
|
inaddr->sin_family = AF_INET;
|
||||||
inaddr->sin_port = 0;
|
inaddr->sin_port = 0;
|
||||||
inaddr->sin_addr.s_addr = ans->u.ipv4.s_addr;
|
inaddr->sin_addr.s_addr = ans->u.ipv4.s_addr;
|
||||||
|
|
||||||
naddr_read++;
|
if (++naddr_read >= naddr)
|
||||||
if (naddr_read >= *naddr)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ret = -ERANGE;
|
ret = -ERANGE;
|
||||||
break;
|
break;
|
||||||
@ -513,6 +511,8 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
|||||||
ans->len == HTONS(16) &&
|
ans->len == HTONS(16) &&
|
||||||
nameptr + 10 + 16 <= endofbuffer)
|
nameptr + 10 + 16 <= endofbuffer)
|
||||||
{
|
{
|
||||||
|
FAR struct sockaddr_in6 *inaddr;
|
||||||
|
|
||||||
nameptr += 10 + 16;
|
nameptr += 10 + 16;
|
||||||
|
|
||||||
ninfo("IPv6 address: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
ninfo("IPv6 address: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||||
@ -521,22 +521,12 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
|||||||
ntohs(ans->u.ipv6.s6_addr[3]), ntohs(ans->u.ipv6.s6_addr[2]),
|
ntohs(ans->u.ipv6.s6_addr[3]), ntohs(ans->u.ipv6.s6_addr[2]),
|
||||||
ntohs(ans->u.ipv6.s6_addr[1]), ntohs(*ans->u.ipv6.s6_addr));
|
ntohs(ans->u.ipv6.s6_addr[1]), ntohs(*ans->u.ipv6.s6_addr));
|
||||||
|
|
||||||
if (naddr_read < *naddr)
|
|
||||||
{
|
|
||||||
FAR struct sockaddr_in6 *inaddr;
|
|
||||||
|
|
||||||
inaddr = &addr[naddr_read].ipv6;
|
inaddr = &addr[naddr_read].ipv6;
|
||||||
inaddr->sin6_family = AF_INET6;
|
inaddr->sin6_family = AF_INET6;
|
||||||
inaddr->sin6_port = 0;
|
inaddr->sin6_port = 0;
|
||||||
memcpy(inaddr->sin6_addr.s6_addr, ans->u.ipv6.s6_addr, 16);
|
memcpy(inaddr->sin6_addr.s6_addr, ans->u.ipv6.s6_addr, 16);
|
||||||
|
|
||||||
naddr_read++;
|
if (++naddr_read >= naddr)
|
||||||
if (naddr_read >= *naddr)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ret = -ERANGE;
|
ret = -ERANGE;
|
||||||
break;
|
break;
|
||||||
@ -553,13 +543,8 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int *naddr,
|
|||||||
{
|
{
|
||||||
ret = -EADDRNOTAVAIL;
|
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;
|
||||||
return (naddr_read > 0) ? naddr_read : ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -586,6 +571,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
|
|||||||
{
|
{
|
||||||
FAR struct dns_query_s *query = (FAR struct dns_query_s *)arg;
|
FAR struct dns_query_s *query = (FAR struct dns_query_s *)arg;
|
||||||
FAR struct dns_query_info_s qinfo;
|
FAR struct dns_query_info_s qinfo;
|
||||||
|
int next = 0;
|
||||||
int retries;
|
int retries;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -596,23 +582,6 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
|
|||||||
for (retries = 0; retries < CONFIG_NETDB_DNSCLIENT_RETRIES; retries++)
|
for (retries = 0; retries < CONFIG_NETDB_DNSCLIENT_RETRIES; retries++)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_NET_IPv4
|
#ifdef CONFIG_NET_IPv4
|
||||||
/* Is this an IPv4 address? */
|
|
||||||
|
|
||||||
if (addr->sa_family == AF_INET)
|
|
||||||
{
|
|
||||||
/* Yes.. verify the address size */
|
|
||||||
|
|
||||||
if (addrlen < sizeof(struct sockaddr_in))
|
|
||||||
{
|
|
||||||
/* Return zero to skip this address and try the next
|
|
||||||
* nameserver address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nerr("ERROR: Invalid IPv4 address size: %d\n", addrlen);
|
|
||||||
query->result = -EINVAL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send the IPv4 query */
|
/* Send the IPv4 query */
|
||||||
|
|
||||||
ret = dns_send_query(query->sd, query->hostname,
|
ret = dns_send_query(query->sd, query->hostname,
|
||||||
@ -620,82 +589,28 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
|
|||||||
DNS_RECTYPE_A, &qinfo);
|
DNS_RECTYPE_A, &qinfo);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
/* Return zero to skip this address and try the next
|
|
||||||
* nameserver address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nerr("ERROR: IPv4 dns_send_query failed: %d\n", ret);
|
nerr("ERROR: IPv4 dns_send_query failed: %d\n", ret);
|
||||||
query->result = ret;
|
query->result = ret;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Obtain the IPv4 response */
|
|
||||||
|
|
||||||
ret = dns_recv_response(query->sd, query->addr, query->naddr,
|
|
||||||
&qinfo);
|
|
||||||
if (ret >= 0)
|
|
||||||
{
|
|
||||||
/* IPv4 response received successfully */
|
|
||||||
|
|
||||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
|
||||||
/* Save the answer in the DNS cache */
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle errors */
|
|
||||||
|
|
||||||
nerr("ERROR: IPv4 dns_recv_response failed: %d\n", ret);
|
|
||||||
|
|
||||||
if (ret == -EADDRNOTAVAIL)
|
|
||||||
{
|
|
||||||
/* The IPv4 address is not available. Return zero to
|
|
||||||
* continue the tranversal with the next nameserver
|
|
||||||
* address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
query->result = -EADDRNOTAVAIL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (ret != -EAGAIN)
|
|
||||||
{
|
|
||||||
/* Some failure other than receive timeout occurred. Return
|
|
||||||
* zero to skip this address and try the next nameserver
|
|
||||||
* address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
query->result = ret;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* Obtain the IPv4 response */
|
||||||
|
|
||||||
|
ret = dns_recv_response(query->sd, &query->addr[next],
|
||||||
|
*query->naddr - next, &qinfo);
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
next += ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nerr("ERROR: IPv4 dns_recv_response failed: %d\n", ret);
|
||||||
|
query->result = ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif /* CONFIG_NET_IPv4 */
|
#endif /* CONFIG_NET_IPv4 */
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
#ifdef CONFIG_NET_IPv6
|
||||||
/* Is this an IPv6 address? */
|
|
||||||
|
|
||||||
if (addr->sa_family == AF_INET6)
|
|
||||||
{
|
|
||||||
/* Yes.. verify the address size */
|
|
||||||
|
|
||||||
if (addrlen < sizeof(struct sockaddr_in6))
|
|
||||||
{
|
|
||||||
/* Return zero to skip this address and try the next
|
|
||||||
* nameserver address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nerr("ERROR: Invalid IPv6 address size: %d\n", addrlen);
|
|
||||||
query->result = -EINVAL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send the IPv6 query */
|
/* Send the IPv6 query */
|
||||||
|
|
||||||
ret = dns_send_query(query->sd, query->hostname,
|
ret = dns_send_query(query->sd, query->hostname,
|
||||||
@ -703,77 +618,47 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
|
|||||||
DNS_RECTYPE_AAAA, &qinfo);
|
DNS_RECTYPE_AAAA, &qinfo);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
/* Return zero to skip this address and try the next
|
|
||||||
* nameserver address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nerr("ERROR: IPv6 dns_send_query failed: %d\n", ret);
|
nerr("ERROR: IPv6 dns_send_query failed: %d\n", ret);
|
||||||
query->result = ret;
|
query->result = ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Obtain the IPv6 response */
|
/* Obtain the IPv6 response */
|
||||||
|
|
||||||
ret = dns_recv_response(query->sd, query->addr, query->naddr,
|
ret = dns_recv_response(query->sd, &query->addr[next],
|
||||||
&qinfo);
|
*query->naddr - next, &qinfo);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
/* IPv6 response received successfully */
|
next += ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nerr("ERROR: IPv6 dns_recv_response failed: %d\n", ret);
|
||||||
|
query->result = ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (next > 0)
|
||||||
|
{
|
||||||
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
#if CONFIG_NETDB_DNSCLIENT_ENTRIES > 0
|
||||||
/* Save the answer in the DNS cache */
|
/* Save the answer in the DNS cache */
|
||||||
|
|
||||||
dns_save_answer(query->hostname, query->addr, *query->naddr);
|
dns_save_answer(query->hostname, query->addr, next);
|
||||||
#endif
|
#endif
|
||||||
/* Return 1 to indicate to (1) stop the traversal, and (2)
|
/* Return 1 to indicate to (1) stop the traversal, and (2)
|
||||||
* indicate that the address was found.
|
* indicate that the address was found.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
*query->naddr = next;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else if (query->result != -EAGAIN)
|
||||||
/* Handle errors */
|
|
||||||
|
|
||||||
nerr("ERROR: IPv6 dns_recv_response failed: %d\n", ret);
|
|
||||||
|
|
||||||
if (ret == -EADDRNOTAVAIL)
|
|
||||||
{
|
{
|
||||||
/* The IPv6 address is not available. Return zero to
|
break;
|
||||||
* continue the tranversal with the next nameserver
|
|
||||||
* address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
query->result = -EADDRNOTAVAIL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (ret != -EAGAIN)
|
|
||||||
{
|
|
||||||
/* Some failure other than receive timeout occurred. Return
|
|
||||||
* zero to skip this address and try the next nameserver
|
|
||||||
* address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
query->result = ret;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* Unsupported address family. Return zero to continue the
|
|
||||||
* tranversal with the next nameserver address in resolv.conf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We tried and could not communicate with this nameserver. Perhaps it
|
|
||||||
* is down? Return zero to continue with the next address in the
|
|
||||||
* resolv.conf file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
query->result = -ETIMEDOUT;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user