libc/netdb: Move dns query info and buffer out of the stack

The length of these buffers come from Kconfig, it isn't safe to allocate
them on the stack.

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2023-07-25 12:48:56 +08:00 committed by Xiang Xiao
parent 4aa54e8405
commit 9dc5a59d50

View File

@ -57,6 +57,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <nuttx/lib/lib.h>
#include <nuttx/net/net.h> #include <nuttx/net/net.h>
#include <nuttx/net/dns.h> #include <nuttx/net/dns.h>
@ -79,6 +80,7 @@
#define SEND_BUFFER_SIZE (16 + CONFIG_NETDB_DNSCLIENT_NAMESIZE + 2) #define SEND_BUFFER_SIZE (16 + CONFIG_NETDB_DNSCLIENT_NAMESIZE + 2)
#define RECV_BUFFER_SIZE CONFIG_NETDB_DNSCLIENT_MAXRESPONSE #define RECV_BUFFER_SIZE CONFIG_NETDB_DNSCLIENT_MAXRESPONSE
#define QUERY_BUFFER_SIZE MAX(SEND_BUFFER_SIZE, RECV_BUFFER_SIZE)
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
@ -104,6 +106,13 @@ struct dns_query_info_s
* encoded format + NUL */ * encoded format + NUL */
}; };
struct dns_query_data_s
{
struct dns_query_s query;
struct dns_query_info_s qinfo;
uint8_t buffer[QUERY_BUFFER_SIZE]; /* Buffer to hold request & response */
};
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -197,7 +206,8 @@ static inline uint16_t dns_alloc_id(void)
static int dns_send_query(int sd, FAR const char *name, static int dns_send_query(int sd, FAR const char *name,
FAR union dns_addr_u *uaddr, uint16_t rectype, FAR union dns_addr_u *uaddr, uint16_t rectype,
FAR struct dns_query_info_s *qinfo) FAR struct dns_query_info_s *qinfo,
FAR uint8_t *buffer)
{ {
FAR struct dns_header_s *hdr; FAR struct dns_header_s *hdr;
FAR uint8_t *dest; FAR uint8_t *dest;
@ -205,7 +215,6 @@ static int dns_send_query(int sd, FAR const char *name,
FAR char *qname; FAR char *qname;
FAR char *qptr; FAR char *qptr;
FAR const char *src; FAR const char *src;
uint8_t buffer[SEND_BUFFER_SIZE];
uint16_t id; uint16_t id;
socklen_t addrlen; socklen_t addrlen;
int ret; int ret;
@ -327,12 +336,11 @@ 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,
uint32_t *ttl) FAR uint32_t *ttl, FAR uint8_t *buffer)
{ {
FAR uint8_t *nameptr; FAR uint8_t *nameptr;
FAR uint8_t *namestart; FAR uint8_t *namestart;
FAR uint8_t *endofbuffer; FAR uint8_t *endofbuffer;
char buffer[RECV_BUFFER_SIZE];
FAR struct dns_answer_s *ans; FAR struct dns_answer_s *ans;
FAR struct dns_header_s *hdr; FAR struct dns_header_s *hdr;
FAR struct dns_question_s *que; FAR struct dns_question_s *que;
@ -366,7 +374,7 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int naddr,
} }
hdr = (FAR struct dns_header_s *)buffer; hdr = (FAR struct dns_header_s *)buffer;
endofbuffer = (FAR uint8_t *)buffer + ret; endofbuffer = buffer + ret;
ninfo("ID %d\n", NTOHS(hdr->id)); ninfo("ID %d\n", NTOHS(hdr->id));
ninfo("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE); ninfo("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE);
@ -411,7 +419,7 @@ static int dns_recv_response(int sd, FAR union dns_addr_u *addr, int naddr,
* matches against the name in the question. * matches against the name in the question.
*/ */
namestart = (uint8_t *)buffer + sizeof(*hdr); namestart = buffer + sizeof(*hdr);
nameptr = dns_parse_name(namestart, endofbuffer); nameptr = dns_parse_name(namestart, endofbuffer);
if (nameptr == endofbuffer) if (nameptr == endofbuffer)
{ {
@ -620,8 +628,8 @@ static void dns_query_error(FAR const char *prompt, int ret,
static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr, static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
FAR socklen_t addrlen) FAR socklen_t addrlen)
{ {
FAR struct dns_query_s *query = (FAR struct dns_query_s *)arg; FAR struct dns_query_data_s *qdata = arg;
FAR struct dns_query_info_s qinfo; FAR struct dns_query_s *query = &qdata->query;
int next = 0; int next = 0;
int retries; int retries;
int ret; int ret;
@ -645,7 +653,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
ret = dns_send_query(sd, query->hostname, ret = dns_send_query(sd, query->hostname,
(FAR union dns_addr_u *)addr, (FAR union dns_addr_u *)addr,
DNS_RECTYPE_AAAA, &qinfo); DNS_RECTYPE_AAAA, &qdata->qinfo, qdata->buffer);
if (ret < 0) if (ret < 0)
{ {
dns_query_error("ERROR: IPv6 dns_send_query failed", dns_query_error("ERROR: IPv6 dns_send_query failed",
@ -657,7 +665,8 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
/* Obtain the IPv6 response */ /* Obtain the IPv6 response */
ret = dns_recv_response(sd, &query->addr[next], ret = dns_recv_response(sd, &query->addr[next],
*query->naddr - next, &qinfo, &query->ttl); *query->naddr - next, &qdata->qinfo,
&query->ttl, qdata->buffer);
if (ret >= 0) if (ret >= 0)
{ {
next += ret; next += ret;
@ -685,7 +694,7 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
ret = dns_send_query(sd, query->hostname, ret = dns_send_query(sd, query->hostname,
(FAR union dns_addr_u *)addr, (FAR union dns_addr_u *)addr,
DNS_RECTYPE_A, &qinfo); DNS_RECTYPE_A, &qdata->qinfo, qdata->buffer);
if (ret < 0) if (ret < 0)
{ {
dns_query_error("ERROR: IPv4 dns_send_query failed", dns_query_error("ERROR: IPv4 dns_send_query failed",
@ -697,7 +706,8 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
/* Obtain the IPv4 response */ /* Obtain the IPv4 response */
ret = dns_recv_response(sd, &query->addr[next], ret = dns_recv_response(sd, &query->addr[next],
*query->naddr - next, &qinfo, &query->ttl); *query->naddr - next, &qdata->qinfo,
&query->ttl, qdata->buffer);
if (ret >= 0) if (ret >= 0)
{ {
next += ret; next += ret;
@ -763,15 +773,20 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
int dns_query(FAR const char *hostname, FAR union dns_addr_u *addr, int dns_query(FAR const char *hostname, FAR union dns_addr_u *addr,
FAR int *naddr) FAR int *naddr)
{ {
FAR struct dns_query_s query; FAR struct dns_query_data_s *qdata = lib_malloc(sizeof(*qdata));
int ret; int ret;
if (qdata == NULL)
{
return -ENOMEM;
}
/* Set up the query info structure */ /* Set up the query info structure */
query.result = -EADDRNOTAVAIL; qdata->query.result = -EADDRNOTAVAIL;
query.hostname = hostname; qdata->query.hostname = hostname;
query.addr = addr; qdata->query.addr = addr;
query.naddr = naddr; qdata->query.naddr = naddr;
/* Perform the query. dns_foreach_nameserver() will return: /* Perform the query. dns_foreach_nameserver() will return:
* *
@ -780,7 +795,7 @@ int dns_query(FAR const char *hostname, FAR union dns_addr_u *addr,
* <0 - Some other failure (?, shouldn't happen) * <0 - Some other failure (?, shouldn't happen)
*/ */
ret = dns_foreach_nameserver(dns_query_callback, &query); ret = dns_foreach_nameserver(dns_query_callback, qdata);
if (ret > 0) if (ret > 0)
{ {
/* The lookup was successful */ /* The lookup was successful */
@ -789,8 +804,12 @@ int dns_query(FAR const char *hostname, FAR union dns_addr_u *addr,
} }
else if (ret == 0) else if (ret == 0)
{ {
ret = query.result; ret = qdata->query.result;
} }
/* Free the query data */
lib_free(qdata);
return ret; return ret;
} }