• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MIT License
2  *
3  * Copyright (c) 1998, 2011, 2013 Massachusetts Institute of Technology
4  * Copyright (c) 2017 Christian Ammer
5  * Copyright (c) 2019 Andrew Selivanov
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  *
26  * SPDX-License-Identifier: MIT
27  */
28 
29 #include "ares_private.h"
30 
31 #ifdef HAVE_GETSERVBYNAME_R
32 #  if !defined(GETSERVBYNAME_R_ARGS) || (GETSERVBYNAME_R_ARGS < 4) || \
33     (GETSERVBYNAME_R_ARGS > 6)
34 #    error "you MUST specify a valid number of arguments for getservbyname_r"
35 #  endif
36 #endif
37 
38 #ifdef HAVE_NETINET_IN_H
39 #  include <netinet/in.h>
40 #endif
41 #ifdef HAVE_NETDB_H
42 #  include <netdb.h>
43 #endif
44 #ifdef HAVE_ARPA_INET_H
45 #  include <arpa/inet.h>
46 #endif
47 
48 #include "ares_nameser.h"
49 
50 #ifdef HAVE_STRINGS_H
51 #  include <strings.h>
52 #endif
53 #include <assert.h>
54 
55 #ifdef HAVE_LIMITS_H
56 #  include <limits.h>
57 #endif
58 
59 #include "ares_dns.h"
60 #include "ares_llist.h"
61 
62 struct host_query {
63   ares_channel_t            *channel;
64   char                      *name;
65   unsigned short             port; /* in host order */
66   ares_addrinfo_callback     callback;
67   void                      *arg;
68   struct ares_addrinfo_hints hints;
69   int    sent_family; /* this family is what was is being used */
70   size_t timeouts;    /* number of timeouts we saw for this request */
71   char  *lookups; /* Duplicate memory from channel because of ares_reinit() */
72   const char *remaining_lookups; /* types of lookup we need to perform ("fb" by
73                                     default, file and dns respectively) */
74 
75   /* Search order for names */
76   char      **names;
77   size_t      names_cnt;
78   size_t      next_name_idx;       /* next name index being attempted */
79 
80   struct ares_addrinfo *ai;        /* store results between lookups */
81   unsigned short        qid_a;     /* qid for A request */
82   unsigned short        qid_aaaa;  /* qid for AAAA request */
83 
84   size_t                remaining; /* number of DNS answers waiting for */
85 
86   /* Track nodata responses to possibly override final result */
87   size_t                nodata_cnt;
88 #if OHOS_DNS_PROXY_BY_NETSYS
89   char                  *src_addr;
90   struct ares_process_info process_info;
91 #endif
92 };
93 
94 static const struct ares_addrinfo_hints default_hints = {
95   0,         /* ai_flags */
96   AF_UNSPEC, /* ai_family */
97   0,         /* ai_socktype */
98   0,         /* ai_protocol */
99 };
100 
101 /* forward declarations */
102 static ares_bool_t next_dns_lookup(struct host_query *hquery);
103 
104 #if OHOS_DNS_PROXY_BY_NETSYS
105 #define MAX_RESULTS 32
106 #define MAX_CANON_NAME 256
107 #define SOURCE_FROM_CARES 2
108 
109 typedef union {
110     struct sockaddr sa;
111     struct sockaddr_in6 sin6;
112     struct sockaddr_in sin;
113 } ares_align_sock_addr;
114 
115 typedef struct {
116     uint32_t ai_flags;
117     uint32_t ai_family;
118     uint32_t ai_socktype;
119     uint32_t ai_protocol;
120     uint32_t ai_addrlen;
121     ares_align_sock_addr ai_addr;
122     char ai_canonName[MAX_CANON_NAME + 1];
123 } ares_cached_addrinfo;
124 
125 typedef struct {
126     char *host;
127     char *serv;
128     struct addrinfo *hint;
129 } ares_cache_key_param_wrapper;
130 
131 static const struct ares_family_query_info empty_family_query_info = {
132   -1, /* retCode */
133   NULL, /* serverAddr */
134   1,  /* isNoAnswer */
135   0,  /* cname */
136 };
137 
ares_addrinfo_hints_to_addrinfo(const struct ares_addrinfo_hints * hints,struct addrinfo * out_hints)138 void ares_addrinfo_hints_to_addrinfo(const struct ares_addrinfo_hints *hints, struct addrinfo *out_hints) {
139   if (hints == NULL || out_hints == NULL) {
140     return;
141   }
142   memset(out_hints, 0, sizeof(struct addrinfo));
143   out_hints->ai_flags = hints->ai_flags;
144   out_hints->ai_family = hints->ai_family;
145   out_hints->ai_socktype = hints->ai_socktype;
146   out_hints->ai_protocol = hints->ai_protocol;
147 }
148 
ares_get_now_time()149 long long ares_get_now_time()
150 {
151   struct timeval tv;
152   gettimeofday(&tv, NULL);
153   long long timestamp = (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000;
154   return timestamp;
155 }
156 
free_process_info(struct ares_process_info process_info)157 void free_process_info(struct ares_process_info process_info)
158 {
159     struct ares_family_query_info ipv4Info = process_info.ipv4QueryInfo;
160     struct ares_family_query_info ipv6Info = process_info.ipv6QueryInfo;
161     if (ipv4Info.serverAddr) {
162         ares_free(ipv4Info.serverAddr);
163     }
164     if (ipv6Info.serverAddr) {
165         ares_free(ipv6Info.serverAddr);
166     }
167 }
168 
ares_free_posix_addrinfo(struct addrinfo * head)169 void ares_free_posix_addrinfo(struct addrinfo *head) {
170   while (head != NULL) {
171     struct addrinfo *current = head;
172     head = head->ai_next;
173     if (current->ai_addr) {
174       ares_free(current->ai_addr);
175     }
176     ares_free(current);
177   }
178 }
179 
ares_addrinfo_to_addrinfo(const struct ares_addrinfo * res)180 struct addrinfo *ares_addrinfo_to_addrinfo(const struct ares_addrinfo *res) {
181   if (res == NULL) {
182     return NULL;
183   }
184 
185   struct addrinfo *head_res = ares_malloc(sizeof(struct addrinfo));
186   if (head_res == NULL) {
187     return NULL;
188   }
189   memset(head_res, 0, sizeof(struct addrinfo));
190 
191   struct addrinfo *now_node = head_res;
192   for (struct ares_addrinfo_node *tmp = res->nodes; tmp != NULL; tmp = tmp->ai_next) {
193     if (tmp->ai_addrlen > sizeof(ares_align_sock_addr)) {
194       continue;
195     }
196     struct addrinfo *next_node = ares_malloc(sizeof(struct addrinfo));
197     if (next_node == NULL) {
198       ares_free_posix_addrinfo(head_res);
199       return NULL;
200     }
201     memset(next_node, 0, sizeof(struct addrinfo));
202     now_node->ai_next = next_node;
203     now_node = next_node;
204 
205     next_node->ai_flags = tmp->ai_flags;
206     next_node->ai_family = tmp->ai_family;
207     next_node->ai_socktype = tmp->ai_socktype;
208     next_node->ai_protocol = tmp->ai_protocol;
209     next_node->ai_addrlen = tmp->ai_addrlen;
210     next_node->ai_addr = ares_malloc(sizeof(ares_align_sock_addr));
211     if (next_node->ai_addr == NULL) {
212       ares_free_posix_addrinfo(head_res);
213       return NULL;
214     }
215     memset(next_node->ai_addr, 0, sizeof(ares_align_sock_addr));
216     memcpy(next_node->ai_addr, tmp->ai_addr, tmp->ai_addrlen);
217   }
218   struct addrinfo *out_res = head_res->ai_next;
219   ares_free(head_res);
220   return out_res;
221 }
222 
ares_record_process(int status,const char * hostname,long long start_time,const struct ares_addrinfo * addr_info,struct host_query * hquery)223 void ares_record_process(int status, const char *hostname, long long start_time,
224     const struct ares_addrinfo *addr_info, struct host_query *hquery)
225 {
226   if (hostname == NULL) {
227     return;
228   }
229   int cost_time = ares_get_now_time() - start_time;
230   struct ares_process_info process_info;
231   process_info.ipv4QueryInfo = empty_family_query_info;
232   process_info.ipv6QueryInfo = empty_family_query_info;
233   process_info.sourceFrom = SOURCE_FROM_CARES;
234   process_info.hostname = ares_strdup(hostname);
235   if (addr_info) {
236     // read from cache
237     process_info.isFromCache = 1;
238     process_info.queryTime = start_time;
239     process_info.retCode = status;
240     process_info.firstQueryEndDuration = cost_time;
241     process_info.firstReturnType = 0;
242     struct addrinfo *addr = ares_addrinfo_to_addrinfo(addr_info);
243     ares_free_posix_addrinfo(addr);
244     ares_free(process_info.hostname);
245   } else if (!hquery) {
246     // no hquery mean error
247     process_info.isFromCache = 0;
248     process_info.queryTime = start_time;
249     process_info.retCode = status;
250     process_info.firstQueryEndDuration = cost_time;
251     process_info.firstReturnType = 0;
252     ares_free(process_info.hostname);
253   } else if (hquery) {
254     // query complete
255     ares_free(process_info.hostname);
256     process_info = hquery->process_info;
257     process_info.isFromCache = 0;
258     struct addrinfo *addr = ares_addrinfo_to_addrinfo(hquery->ai);
259     ares_free_posix_addrinfo(addr);
260   }
261 }
262 
ares_ans_all_cname(const ares_dns_record_t * dnsrec)263 int ares_ans_all_cname(const ares_dns_record_t *dnsrec)
264 {
265   size_t ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER);
266   if (ancount == 0) {
267     return 0;
268   }
269   for (size_t i = 0; i < ancount; i++) {
270     const ares_dns_rr_t *rr =
271       ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i);
272     ares_dns_rec_type_t rtype = ares_dns_rr_get_type(rr);
273     ares_dns_class_t rclass = ares_dns_rr_get_class(rr);
274     if (rclass != ARES_CLASS_IN || rtype != ARES_REC_TYPE_CNAME) {
275       return 0;
276     }
277   }
278   return 1;
279 }
280 
ares_get_addr(struct ares_addr * addr)281 char *ares_get_addr(struct ares_addr *addr)
282 {
283   if (addr == NULL) {
284     return NULL;
285   }
286   char *ip_str = NULL;
287   if (addr->family == AF_INET) {
288     ip_str = ares_malloc(INET_ADDRSTRLEN);
289     if (ip_str == NULL) {
290         return NULL;
291     }
292     if (ares_inet_ntop(AF_INET, &addr->addr.addr4, ip_str, INET_ADDRSTRLEN) == NULL) {
293         ares_free(ip_str);
294         return NULL;
295     }
296   } else if (addr->family == AF_INET6) {
297     ip_str = ares_malloc(INET6_ADDRSTRLEN);
298     if (ip_str == NULL) {
299         return NULL;
300     }
301     if (ares_inet_ntop(AF_INET6, &addr->addr.addr6, ip_str, INET6_ADDRSTRLEN) == NULL) {
302         ares_free(ip_str);
303         return NULL;
304     }
305   }
306   return ip_str;
307 }
308 
ares_get_addr_by_sockaddr(struct sockaddr * sa)309 char *ares_get_addr_by_sockaddr(struct sockaddr *sa)
310 {
311   if (sa == NULL) {
312     return NULL;
313   }
314   char *ip_str = NULL;
315   switch (sa->sa_family) {
316     case AF_INET: {
317       ip_str = ares_malloc(INET_ADDRSTRLEN);
318       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
319       if (ares_inet_ntop(AF_INET, &sin->sin_addr, ip_str, INET_ADDRSTRLEN) == NULL) {
320         ares_free(ip_str);
321       }
322       break;
323     }
324     case AF_INET6: {
325       ip_str = ares_malloc(INET6_ADDRSTRLEN);
326       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
327       if (ares_inet_ntop(AF_INET6, &sin6->sin6_addr, ip_str, INET6_ADDRSTRLEN) == NULL) {
328         ares_free(ip_str);
329       }
330       break;
331     }
332     default:
333       break;
334   }
335   return ip_str;
336 }
337 
ares_get_src_addr(ares_socket_t sock,struct ares_addr addr,struct sockaddr * src_addr)338 int ares_get_src_addr(ares_socket_t sock, struct ares_addr addr, struct sockaddr *src_addr)
339 {
340   if (sock <= 0) {
341     return -1;
342   }
343   ares_socklen_t len;
344   switch (addr.family)
345     {
346     case AF_INET:
347       len = sizeof(struct sockaddr_in);
348       break;
349     case AF_INET6:
350       len = sizeof(struct sockaddr_in6);
351       break;
352     default:
353       /* No known usable source address for non-INET families. */
354       return -1;
355     }
356   if (getsockname(sock, src_addr, &len) != 0) {
357     return -1;
358   }
359   return 0;
360 }
361 
ares_set_hquery_process(ares_dns_rec_type_t qtype,struct host_query * hquery,int status,struct ares_family_query_info info)362 void ares_set_hquery_process(ares_dns_rec_type_t qtype, struct host_query *hquery,
363   int status, struct ares_family_query_info info)
364 {
365   if (hquery->process_info.firstQueryEndDuration == 0) {
366     if (status == ARES_SUCCESS) {
367         hquery->process_info.firstQueryEndDuration =
368             ares_get_now_time() - hquery->process_info.queryTime;
369     }
370     hquery->process_info.firstReturnType = qtype;
371   }
372   if (qtype == ARES_REC_TYPE_A) {
373     hquery->process_info.ipv4QueryInfo = info;
374   }
375   if (qtype == ARES_REC_TYPE_AAAA) {
376     hquery->process_info.ipv6QueryInfo = info;
377   }
378 }
379 
ares_parse_query_info(int status,const ares_dns_record_t * dnsrec,struct host_query * hquery)380 void ares_parse_query_info(int status, const ares_dns_record_t *dnsrec, struct host_query *hquery)
381 {
382   if (hquery == NULL || dnsrec == NULL || hquery->channel == NULL) {
383     return;
384   }
385   ares_dns_rec_type_t qtype;
386   const ares_channel_t *channel = hquery->channel;
387   ares_query_t *query = ares_htable_szvp_get_direct(channel->queries_by_qid,
388     ares_dns_record_get_id(dnsrec));
389   if (query == NULL) {
390     return;
391   }
392   if (ares_dns_record_query_get(query->query, 0, NULL, &qtype, NULL) != ARES_SUCCESS) {
393     return;
394   }
395   if (qtype != ARES_REC_TYPE_A && qtype != ARES_REC_TYPE_AAAA)  {
396     return;
397   }
398   char *res_addr = NULL;
399   char *server_addr = NULL;
400   ares_conn_t *conn = query->conn;
401   if (conn == NULL) {
402     return;
403   }
404   ares_server_t *server = conn->server;
405   if (server == NULL) {
406     return;
407   }
408   server_addr = ares_get_addr(&server->addr);
409   struct sockaddr *src_addr = NULL;
410   src_addr = ares_malloc(sizeof(struct sockaddr_storage));
411   if (src_addr) {
412     if (ares_get_src_addr(conn->fd, server->addr, src_addr) == 0) {
413       res_addr = ares_get_addr_by_sockaddr(src_addr);
414     }
415   }
416   ares_free(src_addr);
417   hquery->src_addr = res_addr;
418   struct ares_family_query_info info;
419   info.retCode = status;
420   size_t ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER);
421   info.isNoAnswer = ancount > 0 ? 0 : 1;
422   info.serverAddr = server_addr;
423   info.cname = ares_ans_all_cname(dnsrec);
424   ares_set_hquery_process(qtype, hquery, status, info);
425 }
426 
427 struct ares_addrinfo *
ares_cached_addrinfo_to_ares_addrinfo(const ares_cached_addrinfo cached_addrinfo[static MAX_RESULTS],uint32_t num)428 ares_cached_addrinfo_to_ares_addrinfo(const ares_cached_addrinfo cached_addrinfo[static MAX_RESULTS], uint32_t num) {
429   uint32_t real_num = num > MAX_RESULTS ? MAX_RESULTS : num;
430   if (num == 0) {
431     return NULL;
432   }
433 
434   struct ares_addrinfo_node *head_res = ares_malloc(sizeof(struct ares_addrinfo_node));
435   if (head_res == NULL) {
436     return NULL;
437   }
438   memset(head_res, 0, sizeof(struct ares_addrinfo_node));
439 
440   struct ares_addrinfo_node *now_node = head_res;
441   for (uint32_t i = 0; i < real_num; ++i) {
442     if (cached_addrinfo[i].ai_addrlen > sizeof(ares_align_sock_addr)) {
443       continue;
444     }
445 
446     struct ares_addrinfo_node *next_node = ares_malloc(sizeof(struct ares_addrinfo_node));
447     if (next_node == NULL) {
448       ares_freeaddrinfo_nodes(head_res);
449       return NULL;
450     }
451     memset(next_node, 0, sizeof(struct ares_addrinfo_node));
452     now_node->ai_next = next_node;
453     now_node = next_node;
454 
455     next_node->ai_flags = (int) cached_addrinfo[i].ai_flags;
456     next_node->ai_family = (int) cached_addrinfo[i].ai_family;
457     next_node->ai_socktype = (int) cached_addrinfo[i].ai_socktype;
458     next_node->ai_protocol = (int) cached_addrinfo[i].ai_protocol;
459     next_node->ai_addrlen = (ares_socklen_t) cached_addrinfo[i].ai_addrlen;
460     next_node->ai_addr = ares_malloc(sizeof(ares_align_sock_addr));
461     if (next_node->ai_addr == NULL) {
462       ares_freeaddrinfo_nodes(head_res);
463       return NULL;
464     }
465     memset(next_node->ai_addr, 0, sizeof(ares_align_sock_addr));
466     memcpy(next_node->ai_addr, &cached_addrinfo[i].ai_addr, cached_addrinfo[i].ai_addrlen);
467   }
468   struct ares_addrinfo *info = ares_malloc(sizeof(struct ares_addrinfo));
469   if (info == NULL) {
470     ares_freeaddrinfo_nodes(head_res);
471     return NULL;
472   }
473   memset(info, 0, sizeof(struct ares_addrinfo));
474 
475   info->nodes = head_res->ai_next;
476   ares_free(head_res);
477   return info;
478 }
479 
480 struct ares_addrinfo *
ares_get_dns_cache(const char * host,const char * service,const struct ares_addrinfo_hints * hints)481 ares_get_dns_cache(const char *host, const char *service, const struct ares_addrinfo_hints *hints) {
482   ares_cache_key_param_wrapper param = {0};
483   param.host = (char *) host;
484   param.serv = (char *) service;
485   struct addrinfo hint = {0};
486   ares_addrinfo_hints_to_addrinfo(hints, &hint);
487   param.hint = &hint;
488 
489   ares_cached_addrinfo cached_addrinfo[MAX_RESULTS] = {0};
490   memset(cached_addrinfo, 0, sizeof(ares_cached_addrinfo) * MAX_RESULTS);
491   uint32_t num = 0;
492   if (num == 0) {
493     return NULL;
494   }
495   return ares_cached_addrinfo_to_ares_addrinfo(cached_addrinfo, num);
496 }
497 
ares_set_dns_cache(const char * host,const char * service,const struct ares_addrinfo_hints * hints,const struct ares_addrinfo * res)498 void ares_set_dns_cache(const char *host, const char *service, const struct ares_addrinfo_hints *hints,
499                         const struct ares_addrinfo *res) {
500   ares_cache_key_param_wrapper param = {0};
501   param.host = (char *) host;
502   param.serv = (char *) service;
503   struct addrinfo hint = {0};
504   ares_addrinfo_hints_to_addrinfo(hints, &hint);
505   param.hint = &hint;
506 
507   struct addrinfo *posix_res = ares_addrinfo_to_addrinfo(res);
508   if (!posix_res) {
509     return;
510   }
511   ares_free_posix_addrinfo(posix_res);
512 }
513 #endif
514 
515 struct ares_addrinfo_cname *
ares_append_addrinfo_cname(struct ares_addrinfo_cname ** head)516   ares_append_addrinfo_cname(struct ares_addrinfo_cname **head)
517 {
518   struct ares_addrinfo_cname *tail = ares_malloc_zero(sizeof(*tail));
519   struct ares_addrinfo_cname *last = *head;
520 
521   if (tail == NULL) {
522     return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
523   }
524 
525   if (!last) {
526     *head = tail;
527     return tail;
528   }
529 
530   while (last->next) {
531     last = last->next;
532   }
533 
534   last->next = tail;
535   return tail;
536 }
537 
ares_addrinfo_cat_cnames(struct ares_addrinfo_cname ** head,struct ares_addrinfo_cname * tail)538 void ares_addrinfo_cat_cnames(struct ares_addrinfo_cname **head,
539                               struct ares_addrinfo_cname  *tail)
540 {
541   struct ares_addrinfo_cname *last = *head;
542   if (!last) {
543     *head = tail;
544     return;
545   }
546 
547   while (last->next) {
548     last = last->next;
549   }
550 
551   last->next = tail;
552 }
553 
554 /* Allocate new addrinfo and append to the tail. */
555 struct ares_addrinfo_node *
ares_append_addrinfo_node(struct ares_addrinfo_node ** head)556   ares_append_addrinfo_node(struct ares_addrinfo_node **head)
557 {
558   struct ares_addrinfo_node *tail = ares_malloc_zero(sizeof(*tail));
559   struct ares_addrinfo_node *last = *head;
560 
561   if (tail == NULL) {
562     return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
563   }
564 
565   if (!last) {
566     *head = tail;
567     return tail;
568   }
569 
570   while (last->ai_next) {
571     last = last->ai_next;
572   }
573 
574   last->ai_next = tail;
575   return tail;
576 }
577 
ares_addrinfo_cat_nodes(struct ares_addrinfo_node ** head,struct ares_addrinfo_node * tail)578 void ares_addrinfo_cat_nodes(struct ares_addrinfo_node **head,
579                              struct ares_addrinfo_node  *tail)
580 {
581   struct ares_addrinfo_node *last = *head;
582   if (!last) {
583     *head = tail;
584     return;
585   }
586 
587   while (last->ai_next) {
588     last = last->ai_next;
589   }
590 
591   last->ai_next = tail;
592 }
593 
594 /* Resolve service name into port number given in host byte order.
595  * If not resolved, return 0.
596  */
lookup_service(const char * service,int flags)597 static unsigned short lookup_service(const char *service, int flags)
598 {
599   const char     *proto;
600   struct servent *sep;
601 #ifdef HAVE_GETSERVBYNAME_R
602   struct servent se;
603   char           tmpbuf[4096];
604 #endif
605 
606   if (service) {
607     if (flags & ARES_NI_UDP) {
608       proto = "udp";
609     } else if (flags & ARES_NI_SCTP) {
610       proto = "sctp";
611     } else if (flags & ARES_NI_DCCP) {
612       proto = "dccp";
613     } else {
614       proto = "tcp";
615     }
616 #ifdef HAVE_GETSERVBYNAME_R
617     memset(&se, 0, sizeof(se));
618     sep = &se;
619     memset(tmpbuf, 0, sizeof(tmpbuf));
620 #  if GETSERVBYNAME_R_ARGS == 6
621     if (getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf),
622                         &sep) != 0) {
623       sep = NULL; /* LCOV_EXCL_LINE: buffer large so this never fails */
624     }
625 #  elif GETSERVBYNAME_R_ARGS == 5
626     sep = getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf));
627 #  elif GETSERVBYNAME_R_ARGS == 4
628     if (getservbyname_r(service, proto, &se, (void *)tmpbuf) != 0) {
629       sep = NULL;
630     }
631 #  else
632     /* Lets just hope the OS uses TLS! */
633     sep = getservbyname(service, proto);
634 #  endif
635 #else
636     /* Lets just hope the OS uses TLS! */
637 #  if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
638     sep = getservbyname(service, (char *)proto);
639 #  else
640     sep = getservbyname(service, proto);
641 #  endif
642 #endif
643     return (sep ? ntohs((unsigned short)sep->s_port) : 0);
644   }
645   return 0;
646 }
647 
648 /* If the name looks like an IP address or an error occurred,
649  * fake up a host entry, end the query immediately, and return true.
650  * Otherwise return false.
651  */
fake_addrinfo(const char * name,unsigned short port,const struct ares_addrinfo_hints * hints,struct ares_addrinfo * ai,ares_addrinfo_callback callback,void * arg)652 static ares_bool_t fake_addrinfo(const char *name, unsigned short port,
653                                  const struct ares_addrinfo_hints *hints,
654                                  struct ares_addrinfo             *ai,
655                                  ares_addrinfo_callback callback, void *arg)
656 {
657   struct ares_addrinfo_cname *cname;
658   ares_status_t               status = ARES_SUCCESS;
659   ares_bool_t                 result = ARES_FALSE;
660   int                         family = hints->ai_family;
661   if (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC) {
662     /* It only looks like an IP address if it's all numbers and dots. */
663     size_t      numdots = 0;
664     ares_bool_t valid   = ARES_TRUE;
665     const char *p;
666     for (p = name; *p; p++) {
667       if (!ares_isdigit(*p) && *p != '.') {
668         valid = ARES_FALSE;
669         break;
670       } else if (*p == '.') {
671         numdots++;
672       }
673     }
674 
675     /* if we don't have 3 dots, it is illegal
676      * (although inet_pton doesn't think so).
677      */
678     if (numdots != 3 || !valid) {
679       result = ARES_FALSE;
680     } else {
681       struct in_addr addr4;
682       result =
683         ares_inet_pton(AF_INET, name, &addr4) < 1 ? ARES_FALSE : ARES_TRUE;
684       if (result) {
685         status = ares_append_ai_node(AF_INET, port, 0, &addr4, &ai->nodes);
686         if (status != ARES_SUCCESS) {
687           callback(arg, (int)status, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
688           return ARES_TRUE;                    /* LCOV_EXCL_LINE: OutOfMemory */
689         }
690       }
691     }
692   }
693 
694   if (!result && (family == AF_INET6 || family == AF_UNSPEC)) {
695     struct ares_in6_addr addr6;
696     result =
697       ares_inet_pton(AF_INET6, name, &addr6) < 1 ? ARES_FALSE : ARES_TRUE;
698     if (result) {
699       status = ares_append_ai_node(AF_INET6, port, 0, &addr6, &ai->nodes);
700       if (status != ARES_SUCCESS) {
701         callback(arg, (int)status, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
702         return ARES_TRUE;                    /* LCOV_EXCL_LINE: OutOfMemory */
703       }
704     }
705   }
706 
707   if (!result) {
708     return ARES_FALSE;
709   }
710 
711   if (hints->ai_flags & ARES_AI_CANONNAME) {
712     cname = ares_append_addrinfo_cname(&ai->cnames);
713     if (!cname) {
714       /* LCOV_EXCL_START: OutOfMemory */
715       ares_freeaddrinfo(ai);
716       callback(arg, ARES_ENOMEM, 0, NULL);
717       return ARES_TRUE;
718       /* LCOV_EXCL_STOP */
719     }
720 
721     /* Duplicate the name, to avoid a constness violation. */
722     cname->name = ares_strdup(name);
723     if (!cname->name) {
724       ares_freeaddrinfo(ai);
725       callback(arg, ARES_ENOMEM, 0, NULL);
726       return ARES_TRUE;
727     }
728   }
729 
730   ai->nodes->ai_socktype = hints->ai_socktype;
731   ai->nodes->ai_protocol = hints->ai_protocol;
732 
733   callback(arg, ARES_SUCCESS, 0, ai);
734   return ARES_TRUE;
735 }
736 
hquery_free(struct host_query * hquery,ares_bool_t cleanup_ai)737 static void hquery_free(struct host_query *hquery, ares_bool_t cleanup_ai)
738 {
739   if (cleanup_ai) {
740     ares_freeaddrinfo(hquery->ai);
741   }
742   ares_strsplit_free(hquery->names, hquery->names_cnt);
743   ares_free(hquery->name);
744   ares_free(hquery->lookups);
745 #if OHOS_DNS_PROXY_BY_NETSYS
746   ares_free(hquery->src_addr);
747   free_process_info(hquery->process_info);
748 #endif
749   ares_free(hquery);
750 }
751 
end_hquery(struct host_query * hquery,ares_status_t status)752 static void end_hquery(struct host_query *hquery, ares_status_t status)
753 {
754   struct ares_addrinfo_node  sentinel;
755   struct ares_addrinfo_node *next;
756 
757   if (status == ARES_SUCCESS) {
758     if (!(hquery->hints.ai_flags & ARES_AI_NOSORT) && hquery->ai->nodes) {
759       sentinel.ai_next = hquery->ai->nodes;
760       ares_sortaddrinfo(hquery->channel, &sentinel);
761       hquery->ai->nodes = sentinel.ai_next;
762     }
763     next = hquery->ai->nodes;
764 
765     while (next) {
766       next->ai_socktype = hquery->hints.ai_socktype;
767       next->ai_protocol = hquery->hints.ai_protocol;
768       next              = next->ai_next;
769     }
770   } else {
771     /* Clean up what we have collected by so far. */
772     ares_freeaddrinfo(hquery->ai);
773     hquery->ai = NULL;
774   }
775 #if OHOS_DNS_PROXY_BY_NETSYS
776   char serv[12] = {0};
777   sprintf(serv, "%d", hquery->port);
778   ares_set_dns_cache(hquery->name, serv, &hquery->hints, hquery->ai);
779   hquery->process_info.hostname = hquery->name;
780   hquery->process_info.retCode = status;
781   int allDuration = ares_get_now_time() - hquery->process_info.queryTime;
782   int firstQueryEnd2AppDuration = allDuration - hquery->process_info.firstQueryEndDuration;
783   hquery->process_info.firstQueryEnd2AppDuration = firstQueryEnd2AppDuration;
784   ares_record_process(status, hquery->name, hquery->process_info.queryTime, NULL, hquery);
785 #endif
786   hquery->callback(hquery->arg, (int)status, (int)hquery->timeouts, hquery->ai);
787   hquery_free(hquery, ARES_FALSE);
788 }
789 
ares_is_localhost(const char * name)790 ares_bool_t ares_is_localhost(const char *name)
791 {
792   /* RFC6761 6.3 says : The domain "localhost." and any names falling within
793    * ".localhost." */
794   size_t len;
795 
796   if (name == NULL) {
797     return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
798   }
799 
800   if (ares_strcaseeq(name, "localhost")) {
801     return ARES_TRUE;
802   }
803 
804   len = ares_strlen(name);
805   if (len < 10 /* strlen(".localhost") */) {
806     return ARES_FALSE;
807   }
808 
809   if (ares_strcaseeq(name + (len - 10 /* strlen(".localhost") */),
810                      ".localhost")) {
811     return ARES_TRUE;
812   }
813 
814   return ARES_FALSE;
815 }
816 
file_lookup(struct host_query * hquery)817 static ares_status_t file_lookup(struct host_query *hquery)
818 {
819   const ares_hosts_entry_t *entry;
820   ares_status_t             status;
821 
822   /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */
823   if (ares_is_onion_domain(hquery->name)) {
824     return ARES_ENOTFOUND;
825   }
826 
827   status = ares_hosts_search_host(
828     hquery->channel,
829     (hquery->hints.ai_flags & ARES_AI_ENVHOSTS) ? ARES_TRUE : ARES_FALSE,
830     hquery->name, &entry);
831 
832   if (status != ARES_SUCCESS) {
833     goto done;
834   }
835 
836   status = ares_hosts_entry_to_addrinfo(
837     entry, hquery->name, hquery->hints.ai_family, hquery->port,
838     (hquery->hints.ai_flags & ARES_AI_CANONNAME) ? ARES_TRUE : ARES_FALSE,
839     hquery->ai);
840 
841   if (status != ARES_SUCCESS) {
842     goto done; /* LCOV_EXCL_LINE: OutOfMemory */
843   }
844 
845 
846 done:
847   /* RFC6761 section 6.3 #3 states that "Name resolution APIs and libraries
848    * SHOULD recognize localhost names as special and SHOULD always return the
849    * IP loopback address for address queries".
850    * We will also ignore ALL errors when trying to resolve localhost, such
851    * as permissions errors reading /etc/hosts or a malformed /etc/hosts.
852    *
853    * Also, just because the query itself returned success from /etc/hosts
854    * lookup doesn't mean it returned everything it needed to for all requested
855    * address families. As long as we're not on a critical out of memory
856    * condition pass it through to fill in any other address classes. */
857   if (status != ARES_ENOMEM && ares_is_localhost(hquery->name)) {
858     return ares_addrinfo_localhost(hquery->name, hquery->port, &hquery->hints,
859                                    hquery->ai);
860   }
861 
862   return status;
863 }
864 
next_lookup(struct host_query * hquery,ares_status_t status)865 static void next_lookup(struct host_query *hquery, ares_status_t status)
866 {
867   switch (*hquery->remaining_lookups) {
868     case 'b':
869       /* RFC6761 section 6.3 #3 says "Name resolution APIs SHOULD NOT send
870        * queries for localhost names to their configured caching DNS
871        * server(s)."
872        * Otherwise, DNS lookup. */
873       if (!ares_is_localhost(hquery->name) && next_dns_lookup(hquery)) {
874         break;
875       }
876 
877       hquery->remaining_lookups++;
878       next_lookup(hquery, status);
879       break;
880 
881     case 'f':
882       /* Host file lookup */
883       if (file_lookup(hquery) == ARES_SUCCESS) {
884         end_hquery(hquery, ARES_SUCCESS);
885         break;
886       }
887       hquery->remaining_lookups++;
888       next_lookup(hquery, status);
889       break;
890     default:
891       /* No lookup left */
892       end_hquery(hquery, status);
893       break;
894   }
895 }
896 
terminate_retries(const struct host_query * hquery,unsigned short qid)897 static void terminate_retries(const struct host_query *hquery,
898                               unsigned short           qid)
899 {
900   unsigned short term_qid =
901     (qid == hquery->qid_a) ? hquery->qid_aaaa : hquery->qid_a;
902   const ares_channel_t *channel = hquery->channel;
903   ares_query_t         *query   = NULL;
904 
905   /* No other outstanding queries, nothing to do */
906   if (!hquery->remaining) {
907     return;
908   }
909 
910   query = ares_htable_szvp_get_direct(channel->queries_by_qid, term_qid);
911   if (query == NULL) {
912     return;
913   }
914 
915   query->no_retries = ARES_TRUE;
916 }
917 
ai_has_ipv4(struct ares_addrinfo * ai)918 static ares_bool_t ai_has_ipv4(struct ares_addrinfo *ai)
919 {
920   struct ares_addrinfo_node *node;
921 
922   for (node = ai->nodes; node != NULL; node = node->ai_next) {
923     if (node->ai_family == AF_INET) {
924       return ARES_TRUE;
925     }
926   }
927   return ARES_FALSE;
928 }
929 
host_callback(void * arg,ares_status_t status,size_t timeouts,const ares_dns_record_t * dnsrec)930 static void host_callback(void *arg, ares_status_t status, size_t timeouts,
931                           const ares_dns_record_t *dnsrec)
932 {
933   struct host_query *hquery         = (struct host_query *)arg;
934   ares_status_t      addinfostatus  = ARES_SUCCESS;
935   hquery->timeouts                 += timeouts;
936   hquery->remaining--;
937 
938   if (status == ARES_SUCCESS) {
939     if (dnsrec == NULL) {
940       addinfostatus = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
941     } else {
942       addinfostatus =
943         ares_parse_into_addrinfo(dnsrec, ARES_TRUE, hquery->port, hquery->ai);
944     }
945 
946     /* We sent out ipv4 and ipv6 requests simultaneously.  If we got a
947      * successful ipv4 response, we want to go ahead and tell the ipv6 request
948      * that if it fails or times out to not try again since we have the data
949      * we need.
950      *
951      * Our initial implementation of this would terminate retries if we got any
952      * successful response (ipv4 _or_ ipv6).  But we did get some user-reported
953      * issues with this that had bad system configs and odd behavior:
954      *  https://github.com/alpinelinux/docker-alpine/issues/366
955      *
956      * Essentially the ipv6 query succeeded but the ipv4 query failed or timed
957      * out, and so we only returned the ipv6 address, but the host couldn't
958      * use ipv6.  If we continued to allow ipv4 retries it would have found a
959      * server that worked and returned both address classes (this is clearly
960      * unexpected behavior).
961      *
962      * At some point down the road if ipv6 actually becomes required and
963      * reliable we can drop this ipv4 check.
964      */
965     if (addinfostatus == ARES_SUCCESS && ai_has_ipv4(hquery->ai)) {
966       terminate_retries(hquery, ares_dns_record_get_id(dnsrec));
967     }
968   }
969 #if OHOS_DNS_PROXY_BY_NETSYS
970   ares_parse_query_info(status, dnsrec, hquery);
971 #endif
972   if (!hquery->remaining) {
973     if (status == ARES_EDESTRUCTION || status == ARES_ECANCELLED) {
974       /* must make sure we don't do next_lookup() on destroy or cancel,
975        * and return the appropriate status.  We won't return a partial
976        * result in this case. */
977       end_hquery(hquery, status);
978     } else if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA) {
979       /* error in parsing result e.g. no memory */
980       if (addinfostatus == ARES_EBADRESP && hquery->ai->nodes) {
981         /* We got a bad response from server, but at least one query
982          * ended with ARES_SUCCESS */
983         end_hquery(hquery, ARES_SUCCESS);
984       } else {
985         end_hquery(hquery, addinfostatus);
986       }
987     } else if (hquery->ai->nodes) {
988       /* at least one query ended with ARES_SUCCESS */
989       end_hquery(hquery, ARES_SUCCESS);
990     } else if (status == ARES_ENOTFOUND || status == ARES_ENODATA ||
991                addinfostatus == ARES_ENODATA) {
992       if (status == ARES_ENODATA || addinfostatus == ARES_ENODATA) {
993         hquery->nodata_cnt++;
994       }
995 #if OHOS_DNS_PROXY_BY_NETSYS
996       if (hquery->nodata_cnt < ares_slist_len(hquery->channel->servers) && hquery->nodata_cnt > 0) {
997         hquery->next_name_idx--;
998         ares_slist_node_t *node;
999         ares_server_t *server;
1000         server = ares_slist_node_val(ares_slist_node_first(hquery->channel->servers));
1001         server->consec_failures++;
1002         node = ares_slist_node_find(hquery->channel->servers, server);
1003         ares_slist_node_reinsert(node);
1004         ares_qcache_flush(hquery->channel->qcache);
1005       }
1006 #endif
1007       next_lookup(hquery, hquery->nodata_cnt ? ARES_ENODATA : status);
1008     } else if ((status == ARES_ESERVFAIL || status == ARES_EREFUSED) &&
1009                ares_name_label_cnt(hquery->names[hquery->next_name_idx - 1]) ==
1010                  1) {
1011       /* Issue #852, systemd-resolved may return SERVFAIL or REFUSED on a
1012        * single label domain name. */
1013       next_lookup(hquery, hquery->nodata_cnt ? ARES_ENODATA : status);
1014     } else {
1015       end_hquery(hquery, status);
1016     }
1017   }
1018 
1019   /* at this point we keep on waiting for the next query to finish */
1020 }
1021 
ares_getaddrinfo_int(ares_channel_t * channel,const char * name,const char * service,const struct ares_addrinfo_hints * hints,ares_addrinfo_callback callback,void * arg)1022 static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name,
1023                                  const char                       *service,
1024                                  const struct ares_addrinfo_hints *hints,
1025                                  ares_addrinfo_callback callback, void *arg)
1026 {
1027 #if OHOS_DNS_PROXY_BY_NETSYS
1028   long long time_now = ares_get_now_time();
1029   struct ares_addrinfo *cache_res = ares_get_dns_cache(name, service, hints);
1030   if (cache_res && cache_res->nodes) {
1031     ares_record_process(ARES_SUCCESS, name, time_now, cache_res, NULL);
1032     callback(arg, ARES_SUCCESS, 0, cache_res);
1033     return;
1034   }
1035 #endif
1036   struct host_query    *hquery;
1037   unsigned short        port = 0;
1038   int                   family;
1039   struct ares_addrinfo *ai;
1040   ares_status_t         status;
1041 
1042   if (!hints) {
1043     hints = &default_hints;
1044   }
1045 
1046   family = hints->ai_family;
1047 
1048   /* Right now we only know how to look up Internet addresses
1049      and unspec means try both basically. */
1050   if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) {
1051     callback(arg, ARES_ENOTIMP, 0, NULL);
1052     return;
1053   }
1054 
1055   if (ares_is_onion_domain(name)) {
1056     callback(arg, ARES_ENOTFOUND, 0, NULL);
1057     return;
1058   }
1059 
1060   if (service) {
1061     if (hints->ai_flags & ARES_AI_NUMERICSERV) {
1062       unsigned long val;
1063       errno = 0;
1064       val   = strtoul(service, NULL, 0);
1065       if ((val == 0 && errno != 0) || val > 65535) {
1066         callback(arg, ARES_ESERVICE, 0, NULL);
1067         return;
1068       }
1069       port = (unsigned short)val;
1070     } else {
1071       port = lookup_service(service, 0);
1072       if (!port) {
1073         unsigned long val;
1074         errno = 0;
1075         val   = strtoul(service, NULL, 0);
1076         if ((val == 0 && errno != 0) || val > 65535) {
1077           callback(arg, ARES_ESERVICE, 0, NULL);
1078           return;
1079         }
1080         port = (unsigned short)val;
1081       }
1082     }
1083   }
1084 
1085   ai = ares_malloc_zero(sizeof(*ai));
1086   if (!ai) {
1087     callback(arg, ARES_ENOMEM, 0, NULL);
1088     return;
1089   }
1090 
1091   if (fake_addrinfo(name, port, hints, ai, callback, arg)) {
1092     return;
1093   }
1094 
1095   /* Allocate and fill in the host query structure. */
1096   hquery = ares_malloc_zero(sizeof(*hquery));
1097   if (!hquery) {
1098     ares_freeaddrinfo(ai);
1099     callback(arg, ARES_ENOMEM, 0, NULL);
1100     return;
1101   }
1102 
1103   hquery->port        = port;
1104   hquery->channel     = channel;
1105   hquery->hints       = *hints;
1106   hquery->sent_family = -1; /* nothing is sent yet */
1107   hquery->callback    = callback;
1108   hquery->arg         = arg;
1109   hquery->ai          = ai;
1110   hquery->name        = ares_strdup(name);
1111 #if OHOS_DNS_PROXY_BY_NETSYS
1112   hquery->src_addr    = NULL;
1113   hquery->process_info.queryTime = time_now;
1114   hquery->process_info.retCode = ARES_ENODATA;
1115   hquery->process_info.firstQueryEndDuration = 0;
1116   hquery->process_info.firstQueryEnd2AppDuration = 0;
1117   hquery->process_info.firstReturnType = 0;
1118   hquery->process_info.sourceFrom = SOURCE_FROM_CARES;
1119   hquery->process_info.ipv4QueryInfo = empty_family_query_info;
1120   hquery->process_info.ipv6QueryInfo = empty_family_query_info;
1121 #endif
1122   if (hquery->name == NULL) {
1123 #if OHOS_DNS_PROXY_BY_NETSYS
1124     ares_record_process(ARES_ENOMEM, name, time_now, NULL, NULL);
1125 #endif
1126     hquery_free(hquery, ARES_TRUE);
1127     callback(arg, ARES_ENOMEM, 0, NULL);
1128     return;
1129   }
1130 
1131   status =
1132     ares_search_name_list(channel, name, &hquery->names, &hquery->names_cnt);
1133   if (status != ARES_SUCCESS) {
1134 #if OHOS_DNS_PROXY_BY_NETSYS
1135     ares_record_process(status, name, time_now, NULL, NULL);
1136 #endif
1137     hquery_free(hquery, ARES_TRUE);
1138     callback(arg, (int)status, 0, NULL);
1139     return;
1140   }
1141   hquery->next_name_idx = 0;
1142 
1143 
1144   hquery->lookups = ares_strdup(channel->lookups);
1145   if (hquery->lookups == NULL) {
1146 #if OHOS_DNS_PROXY_BY_NETSYS
1147     ares_record_process(status, name, time_now, NULL, NULL);
1148 #endif
1149     hquery_free(hquery, ARES_TRUE);
1150     callback(arg, ARES_ENOMEM, 0, NULL);
1151     return;
1152   }
1153   hquery->remaining_lookups = hquery->lookups;
1154 
1155   /* Start performing lookups according to channel->lookups. */
1156   next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */);
1157 }
1158 
ares_getaddrinfo(ares_channel_t * channel,const char * name,const char * service,const struct ares_addrinfo_hints * hints,ares_addrinfo_callback callback,void * arg)1159 void ares_getaddrinfo(ares_channel_t *channel, const char *name,
1160                       const char                       *service,
1161                       const struct ares_addrinfo_hints *hints,
1162                       ares_addrinfo_callback callback, void *arg)
1163 {
1164   if (channel == NULL) {
1165     return;
1166   }
1167   ares_channel_lock(channel);
1168   ares_getaddrinfo_int(channel, name, service, hints, callback, arg);
1169   ares_channel_unlock(channel);
1170 }
1171 
next_dns_lookup(struct host_query * hquery)1172 static ares_bool_t next_dns_lookup(struct host_query *hquery)
1173 {
1174   const char *name = NULL;
1175 
1176   if (hquery->next_name_idx >= hquery->names_cnt) {
1177     return ARES_FALSE;
1178   }
1179 
1180   name = hquery->names[hquery->next_name_idx++];
1181 
1182   /* NOTE: hquery may be invalidated during the call to ares_query_qid(),
1183    *       so should not be referenced after this point */
1184   switch (hquery->hints.ai_family) {
1185     case AF_INET:
1186       hquery->remaining += 1;
1187       ares_query_nolock(hquery->channel, name, ARES_CLASS_IN, ARES_REC_TYPE_A,
1188                         host_callback, hquery, &hquery->qid_a);
1189       break;
1190     case AF_INET6:
1191       hquery->remaining += 1;
1192       ares_query_nolock(hquery->channel, name, ARES_CLASS_IN,
1193                         ARES_REC_TYPE_AAAA, host_callback, hquery,
1194                         &hquery->qid_aaaa);
1195       break;
1196     case AF_UNSPEC:
1197       hquery->remaining += 2;
1198       ares_query_nolock(hquery->channel, name, ARES_CLASS_IN, ARES_REC_TYPE_A,
1199                         host_callback, hquery, &hquery->qid_a);
1200       ares_query_nolock(hquery->channel, name, ARES_CLASS_IN,
1201                         ARES_REC_TYPE_AAAA, host_callback, hquery,
1202                         &hquery->qid_aaaa);
1203       break;
1204     default:
1205       break;
1206   }
1207 
1208   return ARES_TRUE;
1209 }
1210