1 /* MIT License
2 *
3 * Copyright (c) 1998 Massachusetts Institute of Technology
4 * Copyright (c) 2010 Daniel Stenberg
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * SPDX-License-Identifier: MIT
26 */
27
28 #include "ares_private.h"
29
30 #ifdef HAVE_STRINGS_H
31 # include <strings.h>
32 #endif
33 #ifdef HAVE_SYS_IOCTL_H
34 # include <sys/ioctl.h>
35 #endif
36 #ifdef NETWARE
37 # include <sys/filio.h>
38 #endif
39 #ifdef HAVE_STDINT_H
40 # include <stdint.h>
41 #endif
42
43 #include <assert.h>
44 #include <fcntl.h>
45 #include <limits.h>
46
47
48 static void timeadd(ares_timeval_t *now, size_t millisecs);
49 static ares_status_t process_write(ares_channel_t *channel,
50 ares_socket_t write_fd);
51 static ares_status_t process_read(ares_channel_t *channel,
52 ares_socket_t read_fd,
53 const ares_timeval_t *now);
54 static ares_status_t process_timeouts(ares_channel_t *channel,
55 const ares_timeval_t *now);
56 static ares_status_t process_answer(ares_channel_t *channel,
57 const unsigned char *abuf, size_t alen,
58 ares_conn_t *conn,
59 const ares_timeval_t *now,
60 ares_array_t **requeue);
61 static void handle_conn_error(ares_conn_t *conn, ares_bool_t critical_failure,
62 ares_status_t failure_status);
63 static ares_bool_t same_questions(const ares_query_t *query,
64 const ares_dns_record_t *arec);
65 static void end_query(ares_channel_t *channel, ares_server_t *server,
66 ares_query_t *query, ares_status_t status,
67 const ares_dns_record_t *dnsrec);
68
ares_query_remove_from_conn(ares_query_t * query)69 static void ares_query_remove_from_conn(ares_query_t *query)
70 {
71 /* If its not part of a connection, it can't be tracked for timeouts either */
72 ares_slist_node_destroy(query->node_queries_by_timeout);
73 ares_llist_node_destroy(query->node_queries_to_conn);
74 query->node_queries_by_timeout = NULL;
75 query->node_queries_to_conn = NULL;
76 query->conn = NULL;
77 }
78
79 /* Invoke the server state callback after a success or failure */
invoke_server_state_cb(const ares_server_t * server,ares_bool_t success,int flags)80 static void invoke_server_state_cb(const ares_server_t *server,
81 ares_bool_t success, int flags)
82 {
83 const ares_channel_t *channel = server->channel;
84 ares_buf_t *buf;
85 ares_status_t status;
86 char *server_string;
87
88 if (channel->server_state_cb == NULL) {
89 return;
90 }
91
92 buf = ares_buf_create();
93 if (buf == NULL) {
94 return; /* LCOV_EXCL_LINE: OutOfMemory */
95 }
96
97 status = ares_get_server_addr(server, buf);
98 if (status != ARES_SUCCESS) {
99 ares_buf_destroy(buf); /* LCOV_EXCL_LINE: OutOfMemory */
100 return; /* LCOV_EXCL_LINE: OutOfMemory */
101 }
102
103 server_string = ares_buf_finish_str(buf, NULL);
104 buf = NULL;
105 if (server_string == NULL) {
106 return; /* LCOV_EXCL_LINE: OutOfMemory */
107 }
108
109 channel->server_state_cb(server_string, success, flags,
110 channel->server_state_cb_data);
111 ares_free(server_string);
112 }
113
server_increment_failures(ares_server_t * server,ares_bool_t used_tcp)114 static void server_increment_failures(ares_server_t *server,
115 ares_bool_t used_tcp)
116 {
117 ares_slist_node_t *node;
118 const ares_channel_t *channel = server->channel;
119 ares_timeval_t next_retry_time;
120
121 node = ares_slist_node_find(channel->servers, server);
122 if (node == NULL) {
123 return; /* LCOV_EXCL_LINE: DefensiveCoding */
124 }
125
126 server->consec_failures++;
127 ares_slist_node_reinsert(node);
128
129 ares_tvnow(&next_retry_time);
130 timeadd(&next_retry_time, channel->server_retry_delay);
131 server->next_retry_time = next_retry_time;
132
133 invoke_server_state_cb(server, ARES_FALSE,
134 used_tcp == ARES_TRUE ? ARES_SERV_STATE_TCP
135 : ARES_SERV_STATE_UDP);
136 }
137
server_set_good(ares_server_t * server,ares_bool_t used_tcp)138 static void server_set_good(ares_server_t *server, ares_bool_t used_tcp)
139 {
140 ares_slist_node_t *node;
141 const ares_channel_t *channel = server->channel;
142
143 node = ares_slist_node_find(channel->servers, server);
144 if (node == NULL) {
145 return; /* LCOV_EXCL_LINE: DefensiveCoding */
146 }
147
148 if (server->consec_failures > 0) {
149 server->consec_failures = 0;
150 ares_slist_node_reinsert(node);
151 }
152
153 server->next_retry_time.sec = 0;
154 server->next_retry_time.usec = 0;
155
156 invoke_server_state_cb(server, ARES_TRUE,
157 used_tcp == ARES_TRUE ? ARES_SERV_STATE_TCP
158 : ARES_SERV_STATE_UDP);
159 }
160
161 /* return true if now is exactly check time or later */
ares_timedout(const ares_timeval_t * now,const ares_timeval_t * check)162 ares_bool_t ares_timedout(const ares_timeval_t *now,
163 const ares_timeval_t *check)
164 {
165 ares_int64_t secs = (now->sec - check->sec);
166
167 if (secs > 0) {
168 return ARES_TRUE; /* yes, timed out */
169 }
170 if (secs < 0) {
171 return ARES_FALSE; /* nope, not timed out */
172 }
173
174 /* if the full seconds were identical, check the sub second parts */
175 return ((ares_int64_t)now->usec - (ares_int64_t)check->usec) >= 0
176 ? ARES_TRUE
177 : ARES_FALSE;
178 }
179
180 /* add the specific number of milliseconds to the time in the first argument */
timeadd(ares_timeval_t * now,size_t millisecs)181 static void timeadd(ares_timeval_t *now, size_t millisecs)
182 {
183 now->sec += (ares_int64_t)millisecs / 1000;
184 now->usec += (unsigned int)((millisecs % 1000) * 1000);
185
186 if (now->usec >= 1000000) {
187 now->sec += now->usec / 1000000;
188 now->usec %= 1000000;
189 }
190 }
191
ares_process_fds_nolock(ares_channel_t * channel,const ares_fd_events_t * events,size_t nevents,unsigned int flags)192 static ares_status_t ares_process_fds_nolock(ares_channel_t *channel,
193 const ares_fd_events_t *events,
194 size_t nevents, unsigned int flags)
195 {
196 ares_timeval_t now;
197 size_t i;
198 ares_status_t status = ARES_SUCCESS;
199
200 if (channel == NULL || (events == NULL && nevents != 0)) {
201 return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
202 }
203
204 ares_tvnow(&now);
205
206 /* Process write events */
207 for (i = 0; i < nevents; i++) {
208 if (events[i].fd == ARES_SOCKET_BAD ||
209 !(events[i].events & ARES_FD_EVENT_WRITE)) {
210 continue;
211 }
212 status = process_write(channel, events[i].fd);
213 /* We only care about ENOMEM, anything else is handled via connection
214 * retries, etc */
215 if (status == ARES_ENOMEM) {
216 goto done;
217 }
218 }
219
220 /* Process read events */
221 for (i = 0; i < nevents; i++) {
222 if (events[i].fd == ARES_SOCKET_BAD ||
223 !(events[i].events & ARES_FD_EVENT_READ)) {
224 continue;
225 }
226 status = process_read(channel, events[i].fd, &now);
227 if (status == ARES_ENOMEM) {
228 goto done;
229 }
230 }
231
232 if (!(flags & ARES_PROCESS_FLAG_SKIP_NON_FD)) {
233 ares_check_cleanup_conns(channel);
234 status = process_timeouts(channel, &now);
235 if (status == ARES_ENOMEM) {
236 goto done;
237 }
238 }
239
240 done:
241 if (status == ARES_ENOMEM) {
242 return ARES_ENOMEM;
243 }
244 return ARES_SUCCESS;
245 }
246
ares_process_fds(ares_channel_t * channel,const ares_fd_events_t * events,size_t nevents,unsigned int flags)247 ares_status_t ares_process_fds(ares_channel_t *channel,
248 const ares_fd_events_t *events, size_t nevents,
249 unsigned int flags)
250 {
251 ares_status_t status;
252
253 if (channel == NULL) {
254 return ARES_EFORMERR;
255 }
256
257 ares_channel_lock(channel);
258 status = ares_process_fds_nolock(channel, events, nevents, flags);
259 ares_channel_unlock(channel);
260 return status;
261 }
262
ares_process_fd(ares_channel_t * channel,ares_socket_t read_fd,ares_socket_t write_fd)263 void ares_process_fd(ares_channel_t *channel, ares_socket_t read_fd,
264 ares_socket_t write_fd)
265 {
266 ares_fd_events_t events[2];
267 size_t nevents = 0;
268
269 memset(events, 0, sizeof(events));
270
271 if (read_fd != ARES_SOCKET_BAD) {
272 nevents++;
273 events[nevents - 1].fd = read_fd;
274 events[nevents - 1].events |= ARES_FD_EVENT_READ;
275 }
276
277 if (write_fd != ARES_SOCKET_BAD) {
278 if (write_fd != read_fd) {
279 nevents++;
280 }
281 events[nevents - 1].fd = write_fd;
282 events[nevents - 1].events |= ARES_FD_EVENT_WRITE;
283 }
284
285 ares_process_fds(channel, events, nevents, ARES_PROCESS_FLAG_NONE);
286 }
287
channel_socket_list(const ares_channel_t * channel,size_t * num)288 static ares_socket_t *channel_socket_list(const ares_channel_t *channel,
289 size_t *num)
290 {
291 ares_slist_node_t *snode;
292 ares_array_t *arr = ares_array_create(sizeof(ares_socket_t), NULL);
293
294 *num = 0;
295
296 if (arr == NULL) {
297 return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
298 }
299
300 for (snode = ares_slist_node_first(channel->servers); snode != NULL;
301 snode = ares_slist_node_next(snode)) {
302 ares_server_t *server = ares_slist_node_val(snode);
303 ares_llist_node_t *node;
304
305 for (node = ares_llist_node_first(server->connections); node != NULL;
306 node = ares_llist_node_next(node)) {
307 const ares_conn_t *conn = ares_llist_node_val(node);
308 ares_socket_t *sptr;
309 ares_status_t status;
310
311 if (conn->fd == ARES_SOCKET_BAD) {
312 continue;
313 }
314
315 status = ares_array_insert_last((void **)&sptr, arr);
316 if (status != ARES_SUCCESS) {
317 ares_array_destroy(arr); /* LCOV_EXCL_LINE: OutOfMemory */
318 return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
319 }
320 *sptr = conn->fd;
321 }
322 }
323
324 return ares_array_finish(arr, num);
325 }
326
327 /* Something interesting happened on the wire, or there was a timeout.
328 * See what's up and respond accordingly.
329 */
ares_process(ares_channel_t * channel,fd_set * read_fds,fd_set * write_fds)330 void ares_process(ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds)
331 {
332 size_t i;
333 size_t num_sockets;
334 ares_socket_t *socketlist;
335 ares_fd_events_t *events = NULL;
336 size_t nevents = 0;
337
338 if (channel == NULL) {
339 return;
340 }
341
342 ares_channel_lock(channel);
343
344 /* There is no good way to iterate across an fd_set, instead we must pull a
345 * list of all known fds, and iterate across that checking against the fd_set.
346 */
347 socketlist = channel_socket_list(channel, &num_sockets);
348
349 /* Lets create an events array, maximum number is the number of sockets in
350 * the list, so we'll use that and just track entries with nevents */
351 if (num_sockets) {
352 events = ares_malloc_zero(sizeof(*events) * num_sockets);
353 if (events == NULL) {
354 goto done;
355 }
356 }
357
358 for (i = 0; i < num_sockets; i++) {
359 ares_bool_t had_read = ARES_FALSE;
360 if (read_fds && FD_ISSET(socketlist[i], read_fds)) {
361 nevents++;
362 events[nevents - 1].fd = socketlist[i];
363 events[nevents - 1].events |= ARES_FD_EVENT_READ;
364 had_read = ARES_TRUE;
365 }
366 if (write_fds && FD_ISSET(socketlist[i], write_fds)) {
367 if (!had_read) {
368 nevents++;
369 }
370 events[nevents - 1].fd = socketlist[i];
371 events[nevents - 1].events |= ARES_FD_EVENT_WRITE;
372 }
373 }
374
375 done:
376 ares_process_fds_nolock(channel, events, nevents, ARES_PROCESS_FLAG_NONE);
377 ares_free(events);
378 ares_free(socketlist);
379 ares_channel_unlock(channel);
380 }
381
process_write(ares_channel_t * channel,ares_socket_t write_fd)382 static ares_status_t process_write(ares_channel_t *channel,
383 ares_socket_t write_fd)
384 {
385 ares_conn_t *conn = ares_conn_from_fd(channel, write_fd);
386 ares_status_t status;
387
388 if (conn == NULL) {
389 return ARES_SUCCESS;
390 }
391
392 /* Mark as connected if we got here and TFO Initial not set */
393 if (!(conn->flags & ARES_CONN_FLAG_TFO_INITIAL)) {
394 conn->state_flags |= ARES_CONN_STATE_CONNECTED;
395 }
396
397 status = ares_conn_flush(conn);
398 if (status != ARES_SUCCESS) {
399 handle_conn_error(conn, ARES_TRUE, status);
400 }
401 return status;
402 }
403
ares_process_pending_write(ares_channel_t * channel)404 void ares_process_pending_write(ares_channel_t *channel)
405 {
406 ares_slist_node_t *node;
407
408 if (channel == NULL) {
409 return;
410 }
411
412 ares_channel_lock(channel);
413 if (!channel->notify_pending_write) {
414 ares_channel_unlock(channel);
415 return;
416 }
417
418 /* Set as untriggerd before calling into ares_conn_flush(), this is
419 * because its possible ares_conn_flush() might cause additional data to
420 * be enqueued if there is some form of exception so it will need to recurse.
421 */
422 channel->notify_pending_write = ARES_FALSE;
423
424 for (node = ares_slist_node_first(channel->servers); node != NULL;
425 node = ares_slist_node_next(node)) {
426 ares_server_t *server = ares_slist_node_val(node);
427 ares_conn_t *conn = server->tcp_conn;
428 ares_status_t status;
429
430 if (conn == NULL) {
431 continue;
432 }
433
434 /* Enqueue any pending data if there is any */
435 status = ares_conn_flush(conn);
436 if (status != ARES_SUCCESS) {
437 handle_conn_error(conn, ARES_TRUE, status);
438 }
439 }
440
441 ares_channel_unlock(channel);
442 }
443
read_conn_packets(ares_conn_t * conn)444 static ares_status_t read_conn_packets(ares_conn_t *conn)
445 {
446 ares_bool_t read_again;
447 ares_conn_err_t err;
448 const ares_channel_t *channel = conn->server->channel;
449
450 do {
451 size_t count;
452 size_t len = 65535;
453 unsigned char *ptr;
454 size_t start_len = ares_buf_len(conn->in_buf);
455
456 /* If UDP, lets write out a placeholder for the length indicator */
457 if (!(conn->flags & ARES_CONN_FLAG_TCP) &&
458 ares_buf_append_be16(conn->in_buf, 0) != ARES_SUCCESS) {
459 handle_conn_error(conn, ARES_FALSE /* not critical to connection */,
460 ARES_SUCCESS);
461 return ARES_ENOMEM;
462 }
463
464 /* Get a buffer of sufficient size */
465 ptr = ares_buf_append_start(conn->in_buf, &len);
466
467 if (ptr == NULL) {
468 handle_conn_error(conn, ARES_FALSE /* not critical to connection */,
469 ARES_SUCCESS);
470 return ARES_ENOMEM;
471 }
472
473 /* Read from socket */
474 err = ares_conn_read(conn, ptr, len, &count);
475
476 if (err != ARES_CONN_ERR_SUCCESS) {
477 ares_buf_append_finish(conn->in_buf, 0);
478 if (!(conn->flags & ARES_CONN_FLAG_TCP)) {
479 ares_buf_set_length(conn->in_buf, start_len);
480 }
481 break;
482 }
483
484 /* Record amount of data read */
485 ares_buf_append_finish(conn->in_buf, count);
486
487 /* Only loop if sockets support non-blocking operation, and are using UDP
488 * or are using TCP and read the maximum buffer size */
489 read_again = ARES_FALSE;
490 if (channel->sock_funcs.flags & ARES_SOCKFUNC_FLAG_NONBLOCKING &&
491 (!(conn->flags & ARES_CONN_FLAG_TCP) || count == len)) {
492 read_again = ARES_TRUE;
493 }
494
495 /* If UDP, overwrite length */
496 if (!(conn->flags & ARES_CONN_FLAG_TCP)) {
497 len = ares_buf_len(conn->in_buf);
498 ares_buf_set_length(conn->in_buf, start_len);
499 ares_buf_append_be16(conn->in_buf, (unsigned short)count);
500 ares_buf_set_length(conn->in_buf, len);
501 }
502 /* Try to read again only if *we* set up the socket, otherwise it may be
503 * a blocking socket and would cause recvfrom to hang. */
504 } while (read_again);
505
506 if (err != ARES_CONN_ERR_SUCCESS && err != ARES_CONN_ERR_WOULDBLOCK) {
507 handle_conn_error(conn, ARES_TRUE, ARES_ECONNREFUSED);
508 return ARES_ECONNREFUSED;
509 }
510
511 return ARES_SUCCESS;
512 }
513
514 /* Simple data structure to store a query that needs to be requeued with
515 * optional server */
516 typedef struct {
517 unsigned short qid;
518 ares_server_t *server; /* optional */
519 } ares_requeue_t;
520
ares_append_requeue(ares_array_t ** requeue,ares_query_t * query,ares_server_t * server)521 static ares_status_t ares_append_requeue(ares_array_t **requeue,
522 ares_query_t *query,
523 ares_server_t *server)
524 {
525 ares_requeue_t entry;
526
527 if (*requeue == NULL) {
528 *requeue = ares_array_create(sizeof(ares_requeue_t), NULL);
529 if (*requeue == NULL) {
530 return ARES_ENOMEM;
531 }
532 }
533
534 ares_query_remove_from_conn(query);
535
536 entry.qid = query->qid;
537 entry.server = server;
538 return ares_array_insertdata_last(*requeue, &entry);
539 }
540
read_answers(ares_conn_t * conn,const ares_timeval_t * now)541 static ares_status_t read_answers(ares_conn_t *conn, const ares_timeval_t *now)
542 {
543 ares_status_t status;
544 ares_channel_t *channel = conn->server->channel;
545 ares_array_t *requeue = NULL;
546
547 /* Process all queued answers */
548 while (1) {
549 unsigned short dns_len = 0;
550 const unsigned char *data = NULL;
551 size_t data_len = 0;
552
553 /* Tag so we can roll back */
554 ares_buf_tag(conn->in_buf);
555
556 /* Read length indicator */
557 status = ares_buf_fetch_be16(conn->in_buf, &dns_len);
558 if (status != ARES_SUCCESS) {
559 ares_buf_tag_rollback(conn->in_buf);
560 break;
561 }
562
563 /* Not enough data for a full response yet */
564 status = ares_buf_consume(conn->in_buf, dns_len);
565 if (status != ARES_SUCCESS) {
566 ares_buf_tag_rollback(conn->in_buf);
567 break;
568 }
569
570 /* Can't fail except for misuse */
571 data = ares_buf_tag_fetch(conn->in_buf, &data_len);
572 if (data == NULL || data_len < 2) {
573 ares_buf_tag_clear(conn->in_buf);
574 break;
575 }
576
577 /* Strip off 2 bytes length */
578 data += 2;
579 data_len -= 2;
580
581 /* We finished reading this answer; process it */
582 status = process_answer(channel, data, data_len, conn, now, &requeue);
583 if (status != ARES_SUCCESS) {
584 handle_conn_error(conn, ARES_TRUE, status);
585 goto cleanup;
586 }
587
588 /* Since we processed the answer, clear the tag so space can be reclaimed */
589 ares_buf_tag_clear(conn->in_buf);
590 }
591
592 cleanup:
593
594 /* Flush requeue */
595 while (ares_array_len(requeue) > 0) {
596 ares_query_t *query;
597 ares_requeue_t entry;
598 ares_status_t internal_status;
599
600 internal_status = ares_array_claim_at(&entry, sizeof(entry), requeue, 0);
601 if (internal_status != ARES_SUCCESS) {
602 break;
603 }
604
605 /* Query disappeared */
606 query = ares_htable_szvp_get_direct(channel->queries_by_qid, entry.qid);
607 if (query == NULL) {
608 continue;
609 }
610
611 internal_status = ares_send_query(entry.server, query, now);
612 /* We only care about ARES_ENOMEM */
613 if (internal_status == ARES_ENOMEM) {
614 status = ARES_ENOMEM;
615 }
616 }
617 ares_array_destroy(requeue);
618
619 return status;
620 }
621
process_read(ares_channel_t * channel,ares_socket_t read_fd,const ares_timeval_t * now)622 static ares_status_t process_read(ares_channel_t *channel,
623 ares_socket_t read_fd,
624 const ares_timeval_t *now)
625 {
626 ares_conn_t *conn = ares_conn_from_fd(channel, read_fd);
627 ares_status_t status;
628
629 if (conn == NULL) {
630 return ARES_SUCCESS;
631 }
632
633 /* TODO: There might be a potential issue here where there was a read that
634 * read some data, then looped and read again and got a disconnect.
635 * Right now, that would cause a resend instead of processing the data
636 * we have. This is fairly unlikely to occur due to only looping if
637 * a full buffer of 65535 bytes was read. */
638 status = read_conn_packets(conn);
639
640 if (status != ARES_SUCCESS) {
641 return status;
642 }
643
644 return read_answers(conn, now);
645 }
646
647 /* If any queries have timed out, note the timeout and move them on. */
process_timeouts(ares_channel_t * channel,const ares_timeval_t * now)648 static ares_status_t process_timeouts(ares_channel_t *channel,
649 const ares_timeval_t *now)
650 {
651 ares_slist_node_t *node;
652 ares_status_t status = ARES_SUCCESS;
653
654 /* Just keep popping off the first as this list will re-sort as things come
655 * and go. We don't want to try to rely on 'next' as some operation might
656 * cause a cleanup of that pointer and would become invalid */
657 while ((node = ares_slist_node_first(channel->queries_by_timeout)) != NULL) {
658 ares_query_t *query = ares_slist_node_val(node);
659 ares_conn_t *conn;
660
661 /* Since this is sorted, as soon as we hit a query that isn't timed out,
662 * break */
663 if (!ares_timedout(now, &query->timeout)) {
664 break;
665 }
666
667 query->timeouts++;
668
669 conn = query->conn;
670 server_increment_failures(conn->server, query->using_tcp);
671 status = ares_requeue_query(query, now, ARES_ETIMEOUT, ARES_TRUE, NULL,
672 NULL);
673 if (status == ARES_ENOMEM) {
674 goto done;
675 }
676 }
677 done:
678 if (status == ARES_ENOMEM) {
679 return ARES_ENOMEM;
680 }
681 return ARES_SUCCESS;
682 }
683
rewrite_without_edns(ares_query_t * query)684 static ares_status_t rewrite_without_edns(ares_query_t *query)
685 {
686 ares_status_t status = ARES_SUCCESS;
687 size_t i;
688 ares_bool_t found_opt_rr = ARES_FALSE;
689
690 /* Find and remove the OPT RR record */
691 for (i = 0; i < ares_dns_record_rr_cnt(query->query, ARES_SECTION_ADDITIONAL);
692 i++) {
693 const ares_dns_rr_t *rr;
694 rr = ares_dns_record_rr_get(query->query, ARES_SECTION_ADDITIONAL, i);
695 if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) {
696 ares_dns_record_rr_del(query->query, ARES_SECTION_ADDITIONAL, i);
697 found_opt_rr = ARES_TRUE;
698 break;
699 }
700 }
701
702 if (!found_opt_rr) {
703 status = ARES_EFORMERR;
704 goto done;
705 }
706
707 done:
708 return status;
709 }
710
issue_might_be_edns(const ares_dns_record_t * req,const ares_dns_record_t * rsp)711 static ares_bool_t issue_might_be_edns(const ares_dns_record_t *req,
712 const ares_dns_record_t *rsp)
713 {
714 const ares_dns_rr_t *rr;
715
716 /* If we use EDNS and server answers with FORMERR without an OPT RR, the
717 * protocol extension is not understood by the responder. We must retry the
718 * query without EDNS enabled. */
719 if (ares_dns_record_get_rcode(rsp) != ARES_RCODE_FORMERR) {
720 return ARES_FALSE;
721 }
722
723 rr = ares_dns_get_opt_rr_const(req);
724 if (rr == NULL) {
725 /* We didn't send EDNS */
726 return ARES_FALSE;
727 }
728
729 if (ares_dns_get_opt_rr_const(rsp) == NULL) {
730 /* Spec says EDNS won't be echo'd back on non-supporting servers, so
731 * retry without EDNS */
732 return ARES_TRUE;
733 }
734
735 /* As per issue #911 some non-compliant servers that do indeed support EDNS
736 * but don't support unrecognized option codes exist. At this point we
737 * expect them to have also returned an EDNS opt record, but we may remove
738 * that check in the future. Lets detect this situation if we're sending
739 * option codes */
740 if (ares_dns_rr_get_opt_cnt(rr, ARES_RR_OPT_OPTIONS) == 0) {
741 /* We didn't send any option codes */
742 return ARES_FALSE;
743 }
744
745 if (ares_dns_get_opt_rr_const(rsp) != NULL) {
746 /* At this time we're requiring the server to respond with EDNS opt
747 * records since that's what has been observed in the field. We might
748 * find in the future we have to remove this, who knows. Lets go
749 * ahead and force a retry without EDNS*/
750 return ARES_TRUE;
751 }
752
753 return ARES_FALSE;
754 }
755
756 /* Handle an answer from a server. This must NEVER cleanup the
757 * server connection! Return something other than ARES_SUCCESS to cause
758 * the connection to be terminated after this call. */
process_answer(ares_channel_t * channel,const unsigned char * abuf,size_t alen,ares_conn_t * conn,const ares_timeval_t * now,ares_array_t ** requeue)759 static ares_status_t process_answer(ares_channel_t *channel,
760 const unsigned char *abuf, size_t alen,
761 ares_conn_t *conn,
762 const ares_timeval_t *now,
763 ares_array_t **requeue)
764 {
765 ares_query_t *query;
766 /* Cache these as once ares_send_query() gets called, it may end up
767 * invalidating the connection all-together */
768 ares_server_t *server = conn->server;
769 ares_dns_record_t *rdnsrec = NULL;
770 ares_status_t status;
771 ares_bool_t is_cached = ARES_FALSE;
772
773 /* UDP can have 0-byte messages, drop them to the ground */
774 if (alen == 0) {
775 return ARES_SUCCESS;
776 }
777
778 /* Parse the response */
779 status = ares_dns_parse(abuf, alen, 0, &rdnsrec);
780 if (status != ARES_SUCCESS) {
781 /* Malformations are never accepted */
782 status = ARES_EBADRESP;
783 goto cleanup;
784 }
785
786 /* Find the query corresponding to this packet. The queries are
787 * hashed/bucketed by query id, so this lookup should be quick.
788 */
789 query = ares_htable_szvp_get_direct(channel->queries_by_qid,
790 ares_dns_record_get_id(rdnsrec));
791 if (!query) {
792 /* We may have stopped listening for this query, that's ok */
793 status = ARES_SUCCESS;
794 goto cleanup;
795 }
796
797 /* Both the query id and the questions must be the same. We will drop any
798 * replies that aren't for the same query as this is considered invalid. */
799 if (!same_questions(query, rdnsrec)) {
800 /* Possible qid conflict due to delayed response, that's ok */
801 status = ARES_SUCCESS;
802 goto cleanup;
803 }
804
805 /* Validate DNS cookie in response. This function may need to requeue the
806 * query. */
807 if (ares_cookie_validate(query, rdnsrec, conn, now, requeue)
808 != ARES_SUCCESS) {
809 /* Drop response and return */
810 status = ARES_SUCCESS;
811 goto cleanup;
812 }
813
814 /* At this point we know we've received an answer for this query, so we should
815 * remove it from the connection's queue so we can possibly invalidate the
816 * connection. Delay cleaning up the connection though as we may enqueue
817 * something new. */
818 ares_llist_node_destroy(query->node_queries_to_conn);
819 query->node_queries_to_conn = NULL;
820
821 /* There are old servers that don't understand EDNS at all, then some servers
822 * that have non-compliant implementations. Lets try to detect this sort
823 * of thing. */
824 if (issue_might_be_edns(query->query, rdnsrec)) {
825 status = rewrite_without_edns(query);
826 if (status != ARES_SUCCESS) {
827 end_query(channel, server, query, status, NULL);
828 goto cleanup;
829 }
830
831 /* Requeue to same server */
832 status = ares_append_requeue(requeue, query, server);
833 goto cleanup;
834 }
835
836 /* If we got a truncated UDP packet and are not ignoring truncation,
837 * don't accept the packet, and switch the query to TCP if we hadn't
838 * done so already.
839 */
840 if (ares_dns_record_get_flags(rdnsrec) & ARES_FLAG_TC &&
841 !(conn->flags & ARES_CONN_FLAG_TCP) &&
842 !(channel->flags & ARES_FLAG_IGNTC)) {
843 query->using_tcp = ARES_TRUE;
844 status = ares_append_requeue(requeue, query, NULL);
845 /* Status will reflect success except on memory error, which is good since
846 * requeuing to TCP is ok */
847 goto cleanup;
848 }
849
850 /* If we aren't passing through all error packets, discard packets
851 * with SERVFAIL, NOTIMP, or REFUSED response codes.
852 */
853 if (!(channel->flags & ARES_FLAG_NOCHECKRESP)) {
854 ares_dns_rcode_t rcode = ares_dns_record_get_rcode(rdnsrec);
855 if (rcode == ARES_RCODE_SERVFAIL || rcode == ARES_RCODE_NOTIMP ||
856 rcode == ARES_RCODE_REFUSED) {
857 switch (rcode) {
858 case ARES_RCODE_SERVFAIL:
859 status = ARES_ESERVFAIL;
860 break;
861 case ARES_RCODE_NOTIMP:
862 status = ARES_ENOTIMP;
863 break;
864 case ARES_RCODE_REFUSED:
865 status = ARES_EREFUSED;
866 break;
867 default:
868 break;
869 }
870
871 server_increment_failures(server, query->using_tcp);
872 status = ares_requeue_query(query, now, status, ARES_TRUE, rdnsrec, requeue);
873
874 if (status != ARES_ENOMEM) {
875 /* Should any of these cause a connection termination?
876 * Maybe SERVER_FAILURE? */
877 status = ARES_SUCCESS;
878 }
879 goto cleanup;
880 }
881 }
882
883 /* If cache insertion was successful, it took ownership. We ignore
884 * other cache insertion failures. */
885 if (ares_qcache_insert(channel, now, query, rdnsrec) == ARES_SUCCESS) {
886 is_cached = ARES_TRUE;
887 }
888
889 server_set_good(server, query->using_tcp);
890 end_query(channel, server, query, ARES_SUCCESS, rdnsrec);
891
892 status = ARES_SUCCESS;
893
894 cleanup:
895 /* Don't cleanup the cached pointer to the dns response */
896 if (!is_cached) {
897 ares_dns_record_destroy(rdnsrec);
898 }
899
900 return status;
901 }
902
handle_conn_error(ares_conn_t * conn,ares_bool_t critical_failure,ares_status_t failure_status)903 static void handle_conn_error(ares_conn_t *conn, ares_bool_t critical_failure,
904 ares_status_t failure_status)
905 {
906 ares_server_t *server = conn->server;
907
908 /* Increment failures first before requeue so it is unlikely to requeue
909 * to the same server */
910 if (critical_failure) {
911 server_increment_failures(
912 server, (conn->flags & ARES_CONN_FLAG_TCP) ? ARES_TRUE : ARES_FALSE);
913 }
914
915 /* This will requeue any connections automatically */
916 ares_close_connection(conn, failure_status);
917 }
918
919 /* Requeue query will normally call ares_send_query() but in some circumstances
920 * this needs to be delayed, so if requeue is not NULL, it will add the query
921 * to the queue instead */
ares_requeue_query(ares_query_t * query,const ares_timeval_t * now,ares_status_t status,ares_bool_t inc_try_count,const ares_dns_record_t * dnsrec,ares_array_t ** requeue)922 ares_status_t ares_requeue_query(ares_query_t *query, const ares_timeval_t *now,
923 ares_status_t status,
924 ares_bool_t inc_try_count,
925 const ares_dns_record_t *dnsrec,
926 ares_array_t **requeue)
927 {
928 ares_channel_t *channel = query->channel;
929 size_t max_tries = ares_slist_len(channel->servers) * channel->tries;
930
931 ares_query_remove_from_conn(query);
932
933 if (status != ARES_SUCCESS) {
934 query->error_status = status;
935 }
936
937 if (inc_try_count) {
938 query->try_count++;
939 }
940
941 if (query->try_count < max_tries && !query->no_retries) {
942 if (requeue != NULL) {
943 return ares_append_requeue(requeue, query, NULL);
944 }
945 return ares_send_query(NULL, query, now);
946 }
947
948 /* If we are here, all attempts to perform query failed. */
949 if (query->error_status == ARES_SUCCESS) {
950 query->error_status = ARES_ETIMEOUT;
951 }
952
953 end_query(channel, NULL, query, query->error_status, dnsrec);
954 return ARES_ETIMEOUT;
955 }
956
957 /*! Count the number of servers that share the same highest priority (lowest
958 * consecutive failures). Since they are sorted in priority order, we just
959 * stop when the consecutive failure count changes. Used for random selection
960 * of good servers. */
count_highest_prio_servers(const ares_channel_t * channel)961 static size_t count_highest_prio_servers(const ares_channel_t *channel)
962 {
963 ares_slist_node_t *node;
964 size_t cnt = 0;
965 size_t last_consec_failures = SIZE_MAX;
966
967 for (node = ares_slist_node_first(channel->servers); node != NULL;
968 node = ares_slist_node_next(node)) {
969 const ares_server_t *server = ares_slist_node_val(node);
970
971 if (last_consec_failures != SIZE_MAX &&
972 last_consec_failures < server->consec_failures) {
973 break;
974 }
975
976 last_consec_failures = server->consec_failures;
977 cnt++;
978 }
979
980 return cnt;
981 }
982
983 /* Pick a random *best* server from the list, we first get a random number in
984 * the range of the number of *best* servers, then scan until we find that
985 * server in the list */
ares_random_server(ares_channel_t * channel)986 static ares_server_t *ares_random_server(ares_channel_t *channel)
987 {
988 unsigned char c;
989 size_t cnt;
990 size_t idx;
991 ares_slist_node_t *node;
992 size_t num_servers = count_highest_prio_servers(channel);
993
994 /* Silence coverity, not possible */
995 if (num_servers == 0) {
996 return NULL;
997 }
998
999 ares_rand_bytes(channel->rand_state, &c, 1);
1000
1001 cnt = c;
1002 idx = cnt % num_servers;
1003
1004 cnt = 0;
1005 for (node = ares_slist_node_first(channel->servers); node != NULL;
1006 node = ares_slist_node_next(node)) {
1007 if (cnt == idx) {
1008 return ares_slist_node_val(node);
1009 }
1010
1011 cnt++;
1012 }
1013
1014 return NULL;
1015 }
1016
server_probe_cb(void * arg,ares_status_t status,size_t timeouts,const ares_dns_record_t * dnsrec)1017 static void server_probe_cb(void *arg, ares_status_t status, size_t timeouts,
1018 const ares_dns_record_t *dnsrec)
1019 {
1020 (void)arg;
1021 (void)status;
1022 (void)timeouts;
1023 (void)dnsrec;
1024 /* Nothing to do, the logic internally will handle success/fail of this */
1025 }
1026
1027 /* Determine if we should probe a downed server */
ares_probe_failed_server(ares_channel_t * channel,const ares_server_t * server,const ares_query_t * query)1028 static void ares_probe_failed_server(ares_channel_t *channel,
1029 const ares_server_t *server,
1030 const ares_query_t *query)
1031 {
1032 const ares_server_t *last_server = ares_slist_last_val(channel->servers);
1033 unsigned short r;
1034 ares_timeval_t now;
1035 ares_slist_node_t *node;
1036 ares_server_t *probe_server = NULL;
1037
1038 /* If no servers have failures, or we're not configured with a server retry
1039 * chance, then nothing to probe */
1040 if ((last_server != NULL && last_server->consec_failures == 0) ||
1041 channel->server_retry_chance == 0) {
1042 return;
1043 }
1044
1045 /* Generate a random value to decide whether to retry a failed server. The
1046 * probability to use is 1/channel->server_retry_chance, rounded up to a
1047 * precision of 1/2^B where B is the number of bits in the random value.
1048 * We use an unsigned short for the random value for increased precision.
1049 */
1050 ares_rand_bytes(channel->rand_state, (unsigned char *)&r, sizeof(r));
1051 if (r % channel->server_retry_chance != 0) {
1052 return;
1053 }
1054
1055 /* Select the first server with failures to retry that has passed the retry
1056 * timeout and doesn't already have a pending probe */
1057 ares_tvnow(&now);
1058 for (node = ares_slist_node_first(channel->servers); node != NULL;
1059 node = ares_slist_node_next(node)) {
1060 ares_server_t *node_val = ares_slist_node_val(node);
1061 if (node_val != NULL && node_val->consec_failures > 0 &&
1062 !node_val->probe_pending &&
1063 ares_timedout(&now, &node_val->next_retry_time)) {
1064 probe_server = node_val;
1065 break;
1066 }
1067 }
1068
1069 /* Either nothing to probe or the query was enqueud to the same server
1070 * we were going to probe. Do nothing. */
1071 if (probe_server == NULL || server == probe_server) {
1072 return;
1073 }
1074
1075 /* Enqueue an identical query onto the specified server without honoring
1076 * the cache or allowing retries. We want to make sure it only attempts to
1077 * use the server in question */
1078 probe_server->probe_pending = ARES_TRUE;
1079 ares_send_nolock(channel, probe_server,
1080 ARES_SEND_FLAG_NOCACHE | ARES_SEND_FLAG_NORETRY,
1081 query->query, server_probe_cb, NULL, NULL);
1082 }
1083
ares_calc_query_timeout(const ares_query_t * query,const ares_server_t * server,const ares_timeval_t * now)1084 static size_t ares_calc_query_timeout(const ares_query_t *query,
1085 const ares_server_t *server,
1086 const ares_timeval_t *now)
1087 {
1088 const ares_channel_t *channel = query->channel;
1089 size_t timeout = ares_metrics_server_timeout(server, now);
1090 size_t timeplus = timeout;
1091 size_t rounds;
1092 size_t num_servers = ares_slist_len(channel->servers);
1093
1094 if (num_servers == 0) {
1095 return 0; /* LCOV_EXCL_LINE: DefensiveCoding */
1096 }
1097
1098 /* For each trip through the entire server list, we want to double the
1099 * retry from the last retry */
1100 rounds = (query->try_count / num_servers);
1101 if (rounds > 0) {
1102 timeplus <<= rounds;
1103 }
1104
1105 if (channel->maxtimeout && timeplus > channel->maxtimeout) {
1106 timeplus = channel->maxtimeout;
1107 }
1108
1109 /* Add some jitter to the retry timeout.
1110 *
1111 * Jitter is needed in situation when resolve requests are performed
1112 * simultaneously from multiple hosts and DNS server throttle these requests.
1113 * Adding randomness allows to avoid synchronisation of retries.
1114 *
1115 * Value of timeplus adjusted randomly to the range [0.5 * timeplus,
1116 * timeplus].
1117 */
1118 if (rounds > 0) {
1119 unsigned short r;
1120 float delta_multiplier;
1121
1122 ares_rand_bytes(channel->rand_state, (unsigned char *)&r, sizeof(r));
1123 delta_multiplier = ((float)r / USHRT_MAX) * 0.5f;
1124 timeplus -= (size_t)((float)timeplus * delta_multiplier);
1125 }
1126
1127 /* We want explicitly guarantee that timeplus is greater or equal to timeout
1128 * specified in channel options. */
1129 if (timeplus < timeout) {
1130 timeplus = timeout;
1131 }
1132
1133 return timeplus;
1134 }
1135
ares_fetch_connection(const ares_channel_t * channel,ares_server_t * server,const ares_query_t * query)1136 static ares_conn_t *ares_fetch_connection(const ares_channel_t *channel,
1137 ares_server_t *server,
1138 const ares_query_t *query)
1139 {
1140 ares_llist_node_t *node;
1141 ares_conn_t *conn;
1142
1143 if (query->using_tcp) {
1144 return server->tcp_conn;
1145 }
1146
1147 /* Fetch existing UDP connection */
1148 node = ares_llist_node_first(server->connections);
1149 if (node == NULL) {
1150 return NULL;
1151 }
1152
1153 conn = ares_llist_node_val(node);
1154 /* Not UDP, skip */
1155 if (conn->flags & ARES_CONN_FLAG_TCP) {
1156 return NULL;
1157 }
1158
1159 /* Used too many times */
1160 if (channel->udp_max_queries > 0 &&
1161 conn->total_queries >= channel->udp_max_queries) {
1162 return NULL;
1163 }
1164
1165 return conn;
1166 }
1167
ares_conn_query_write(ares_conn_t * conn,ares_query_t * query,const ares_timeval_t * now)1168 static ares_status_t ares_conn_query_write(ares_conn_t *conn,
1169 ares_query_t *query,
1170 const ares_timeval_t *now)
1171 {
1172 ares_server_t *server = conn->server;
1173 ares_channel_t *channel = server->channel;
1174 ares_status_t status;
1175
1176 status = ares_cookie_apply(query->query, conn, now);
1177 if (status != ARES_SUCCESS) {
1178 return status;
1179 }
1180
1181 /* We write using the TCP format even for UDP, we just strip the length
1182 * before putting on the wire */
1183 status = ares_dns_write_buf_tcp(query->query, conn->out_buf);
1184 if (status != ARES_SUCCESS) {
1185 return status;
1186 }
1187
1188 /* Not pending a TFO write and not connected, so we can't even try to
1189 * write until we get a signal */
1190 if (conn->flags & ARES_CONN_FLAG_TCP &&
1191 !(conn->state_flags & ARES_CONN_STATE_CONNECTED) &&
1192 !(conn->flags & ARES_CONN_FLAG_TFO_INITIAL)) {
1193 return ARES_SUCCESS;
1194 }
1195
1196 /* Delay actual write if possible (TCP only, and only if callback
1197 * configured) */
1198 if (channel->notify_pending_write_cb && !channel->notify_pending_write &&
1199 conn->flags & ARES_CONN_FLAG_TCP) {
1200 channel->notify_pending_write = ARES_TRUE;
1201 channel->notify_pending_write_cb(channel->notify_pending_write_cb_data);
1202 return ARES_SUCCESS;
1203 }
1204
1205 /* Unfortunately we need to write right away and can't aggregate multiple
1206 * queries into a single write. */
1207 return ares_conn_flush(conn);
1208 }
1209
ares_send_query(ares_server_t * requested_server,ares_query_t * query,const ares_timeval_t * now)1210 ares_status_t ares_send_query(ares_server_t *requested_server,
1211 ares_query_t *query, const ares_timeval_t *now)
1212 {
1213 ares_channel_t *channel = query->channel;
1214 ares_server_t *server;
1215 ares_conn_t *conn;
1216 size_t timeplus;
1217 ares_status_t status;
1218 ares_bool_t probe_downed_server = ARES_TRUE;
1219
1220
1221 /* Choose the server to send the query to */
1222 if (requested_server != NULL) {
1223 server = requested_server;
1224 } else {
1225 /* If rotate is turned on, do a random selection */
1226 if (channel->rotate) {
1227 server = ares_random_server(channel);
1228 } else {
1229 /* First server in list */
1230 server = ares_slist_first_val(channel->servers);
1231 }
1232 }
1233
1234 if (server == NULL) {
1235 end_query(channel, server, query, ARES_ENOSERVER /* ? */, NULL);
1236 return ARES_ENOSERVER;
1237 }
1238
1239 /* If a query is directed to a specific query, or the server chosen has
1240 * failures, or the query is being retried, don't probe for downed servers */
1241 if (requested_server != NULL || server->consec_failures > 0 ||
1242 query->try_count != 0) {
1243 probe_downed_server = ARES_FALSE;
1244 }
1245
1246 conn = ares_fetch_connection(channel, server, query);
1247 if (conn == NULL) {
1248 status = ares_open_connection(&conn, channel, server, query->using_tcp);
1249 switch (status) {
1250 /* Good result, continue on */
1251 case ARES_SUCCESS:
1252 break;
1253
1254 /* These conditions are retryable as they are server-specific
1255 * error codes */
1256 case ARES_ECONNREFUSED:
1257 case ARES_EBADFAMILY:
1258 server_increment_failures(server, query->using_tcp);
1259 return ares_requeue_query(query, now, status, ARES_TRUE, NULL, NULL);
1260
1261 /* Anything else is not retryable, likely ENOMEM */
1262 default:
1263 end_query(channel, server, query, status, NULL);
1264 return status;
1265 }
1266 }
1267
1268 /* Write the query */
1269 status = ares_conn_query_write(conn, query, now);
1270 switch (status) {
1271 /* Good result, continue on */
1272 case ARES_SUCCESS:
1273 break;
1274
1275 case ARES_ENOMEM:
1276 /* Not retryable */
1277 end_query(channel, server, query, status, NULL);
1278 return status;
1279
1280 /* These conditions are retryable as they are server-specific
1281 * error codes */
1282 case ARES_ECONNREFUSED:
1283 case ARES_EBADFAMILY:
1284 handle_conn_error(conn, ARES_TRUE, status);
1285 status = ares_requeue_query(query, now, status, ARES_TRUE, NULL, NULL);
1286 if (status == ARES_ETIMEOUT) {
1287 status = ARES_ECONNREFUSED;
1288 }
1289 return status;
1290
1291 default:
1292 server_increment_failures(server, query->using_tcp);
1293 status = ares_requeue_query(query, now, status, ARES_TRUE, NULL, NULL);
1294 return status;
1295 }
1296
1297 timeplus = ares_calc_query_timeout(query, server, now);
1298 #if OHOS_DNS_PROXY_BY_NETSYS
1299 timeplus = channel->timeout;
1300 #endif
1301 /* Keep track of queries bucketed by timeout, so we can process
1302 * timeout events quickly.
1303 */
1304 ares_slist_node_destroy(query->node_queries_by_timeout);
1305 query->ts = *now;
1306 query->timeout = *now;
1307 timeadd(&query->timeout, timeplus);
1308 query->node_queries_by_timeout =
1309 ares_slist_insert(channel->queries_by_timeout, query);
1310 if (!query->node_queries_by_timeout) {
1311 /* LCOV_EXCL_START: OutOfMemory */
1312 end_query(channel, server, query, ARES_ENOMEM, NULL);
1313 return ARES_ENOMEM;
1314 /* LCOV_EXCL_STOP */
1315 }
1316
1317 /* Keep track of queries bucketed by connection, so we can process errors
1318 * quickly. */
1319 ares_llist_node_destroy(query->node_queries_to_conn);
1320 query->node_queries_to_conn =
1321 ares_llist_insert_last(conn->queries_to_conn, query);
1322
1323 if (query->node_queries_to_conn == NULL) {
1324 /* LCOV_EXCL_START: OutOfMemory */
1325 end_query(channel, server, query, ARES_ENOMEM, NULL);
1326 return ARES_ENOMEM;
1327 /* LCOV_EXCL_STOP */
1328 }
1329
1330 query->conn = conn;
1331 conn->total_queries++;
1332
1333 /* We just successfully enqueud a query, see if we should probe downed
1334 * servers. */
1335 if (probe_downed_server) {
1336 ares_probe_failed_server(channel, server, query);
1337 }
1338
1339 return ARES_SUCCESS;
1340 }
1341
same_questions(const ares_query_t * query,const ares_dns_record_t * arec)1342 static ares_bool_t same_questions(const ares_query_t *query,
1343 const ares_dns_record_t *arec)
1344 {
1345 size_t i;
1346 ares_bool_t rv = ARES_FALSE;
1347 const ares_dns_record_t *qrec = query->query;
1348 const ares_channel_t *channel = query->channel;
1349
1350
1351 if (ares_dns_record_query_cnt(qrec) != ares_dns_record_query_cnt(arec)) {
1352 goto done;
1353 }
1354
1355 for (i = 0; i < ares_dns_record_query_cnt(qrec); i++) {
1356 const char *qname = NULL;
1357 const char *aname = NULL;
1358 ares_dns_rec_type_t qtype;
1359 ares_dns_rec_type_t atype;
1360 ares_dns_class_t qclass;
1361 ares_dns_class_t aclass;
1362
1363 if (ares_dns_record_query_get(qrec, i, &qname, &qtype, &qclass) !=
1364 ARES_SUCCESS ||
1365 qname == NULL) {
1366 goto done;
1367 }
1368
1369 if (ares_dns_record_query_get(arec, i, &aname, &atype, &aclass) !=
1370 ARES_SUCCESS ||
1371 aname == NULL) {
1372 goto done;
1373 }
1374
1375 if (qtype != atype || qclass != aclass) {
1376 goto done;
1377 }
1378
1379 if (channel->flags & ARES_FLAG_DNS0x20 && !query->using_tcp) {
1380 /* NOTE: for DNS 0x20, part of the protection is to use a case-sensitive
1381 * comparison of the DNS query name. This expects the upstream DNS
1382 * server to preserve the case of the name in the response packet.
1383 * https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00
1384 */
1385 if (!ares_streq(qname, aname)) {
1386 goto done;
1387 }
1388 } else {
1389 /* without DNS0x20 use case-insensitive matching */
1390 if (!ares_strcaseeq(qname, aname)) {
1391 goto done;
1392 }
1393 }
1394 }
1395
1396 rv = ARES_TRUE;
1397
1398 done:
1399 return rv;
1400 }
1401
ares_detach_query(ares_query_t * query)1402 static void ares_detach_query(ares_query_t *query)
1403 {
1404 /* Remove the query from all the lists in which it is linked */
1405 ares_query_remove_from_conn(query);
1406 ares_htable_szvp_remove(query->channel->queries_by_qid, query->qid);
1407 ares_llist_node_destroy(query->node_all_queries);
1408 query->node_all_queries = NULL;
1409 }
1410
end_query(ares_channel_t * channel,ares_server_t * server,ares_query_t * query,ares_status_t status,const ares_dns_record_t * dnsrec)1411 static void end_query(ares_channel_t *channel, ares_server_t *server,
1412 ares_query_t *query, ares_status_t status,
1413 const ares_dns_record_t *dnsrec)
1414 {
1415 /* If we were probing for the server to come back online, lets mark it as
1416 * no longer being probed */
1417 if (server != NULL) {
1418 server->probe_pending = ARES_FALSE;
1419 }
1420
1421 ares_metrics_record(query, server, status, dnsrec);
1422
1423 /* Invoke the callback. */
1424 query->callback(query->arg, status, query->timeouts, dnsrec);
1425 ares_free_query(query);
1426
1427 /* Check and notify if no other queries are enqueued on the channel. This
1428 * must come after the callback and freeing the query for 2 reasons.
1429 * 1) The callback itself may enqueue a new query
1430 * 2) Technically the current query isn't detached until it is free()'d.
1431 */
1432 ares_queue_notify_empty(channel);
1433 }
1434
ares_free_query(ares_query_t * query)1435 void ares_free_query(ares_query_t *query)
1436 {
1437 ares_detach_query(query);
1438 /* Zero out some important stuff, to help catch bugs */
1439 query->callback = NULL;
1440 query->arg = NULL;
1441 /* Deallocate the memory associated with the query */
1442 ares_dns_record_destroy(query->query);
1443
1444 ares_free(query);
1445 }
1446