ares_process.c (45132B)
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 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 */ 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 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 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 */ 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 */ 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 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 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 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 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 */ 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 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 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 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 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 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 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. */ 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 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 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. */ 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 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 */ 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. */ 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 */ 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 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 */ 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 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 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 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 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 /* Keep track of queries bucketed by timeout, so we can process 1299 * timeout events quickly. 1300 */ 1301 ares_slist_node_destroy(query->node_queries_by_timeout); 1302 query->ts = *now; 1303 query->timeout = *now; 1304 timeadd(&query->timeout, timeplus); 1305 query->node_queries_by_timeout = 1306 ares_slist_insert(channel->queries_by_timeout, query); 1307 if (!query->node_queries_by_timeout) { 1308 /* LCOV_EXCL_START: OutOfMemory */ 1309 end_query(channel, server, query, ARES_ENOMEM, NULL); 1310 return ARES_ENOMEM; 1311 /* LCOV_EXCL_STOP */ 1312 } 1313 1314 /* Keep track of queries bucketed by connection, so we can process errors 1315 * quickly. */ 1316 ares_llist_node_destroy(query->node_queries_to_conn); 1317 query->node_queries_to_conn = 1318 ares_llist_insert_last(conn->queries_to_conn, query); 1319 1320 if (query->node_queries_to_conn == NULL) { 1321 /* LCOV_EXCL_START: OutOfMemory */ 1322 end_query(channel, server, query, ARES_ENOMEM, NULL); 1323 return ARES_ENOMEM; 1324 /* LCOV_EXCL_STOP */ 1325 } 1326 1327 query->conn = conn; 1328 conn->total_queries++; 1329 1330 /* We just successfully enqueud a query, see if we should probe downed 1331 * servers. */ 1332 if (probe_downed_server) { 1333 ares_probe_failed_server(channel, server, query); 1334 } 1335 1336 return ARES_SUCCESS; 1337 } 1338 1339 static ares_bool_t same_questions(const ares_query_t *query, 1340 const ares_dns_record_t *arec) 1341 { 1342 size_t i; 1343 ares_bool_t rv = ARES_FALSE; 1344 const ares_dns_record_t *qrec = query->query; 1345 const ares_channel_t *channel = query->channel; 1346 1347 1348 if (ares_dns_record_query_cnt(qrec) != ares_dns_record_query_cnt(arec)) { 1349 goto done; 1350 } 1351 1352 for (i = 0; i < ares_dns_record_query_cnt(qrec); i++) { 1353 const char *qname = NULL; 1354 const char *aname = NULL; 1355 ares_dns_rec_type_t qtype; 1356 ares_dns_rec_type_t atype; 1357 ares_dns_class_t qclass; 1358 ares_dns_class_t aclass; 1359 1360 if (ares_dns_record_query_get(qrec, i, &qname, &qtype, &qclass) != 1361 ARES_SUCCESS || 1362 qname == NULL) { 1363 goto done; 1364 } 1365 1366 if (ares_dns_record_query_get(arec, i, &aname, &atype, &aclass) != 1367 ARES_SUCCESS || 1368 aname == NULL) { 1369 goto done; 1370 } 1371 1372 if (qtype != atype || qclass != aclass) { 1373 goto done; 1374 } 1375 1376 if (channel->flags & ARES_FLAG_DNS0x20 && !query->using_tcp) { 1377 /* NOTE: for DNS 0x20, part of the protection is to use a case-sensitive 1378 * comparison of the DNS query name. This expects the upstream DNS 1379 * server to preserve the case of the name in the response packet. 1380 * https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00 1381 */ 1382 if (!ares_streq(qname, aname)) { 1383 goto done; 1384 } 1385 } else { 1386 /* without DNS0x20 use case-insensitive matching */ 1387 if (!ares_strcaseeq(qname, aname)) { 1388 goto done; 1389 } 1390 } 1391 } 1392 1393 rv = ARES_TRUE; 1394 1395 done: 1396 return rv; 1397 } 1398 1399 static void ares_detach_query(ares_query_t *query) 1400 { 1401 /* Remove the query from all the lists in which it is linked */ 1402 ares_query_remove_from_conn(query); 1403 ares_htable_szvp_remove(query->channel->queries_by_qid, query->qid); 1404 ares_llist_node_destroy(query->node_all_queries); 1405 query->node_all_queries = NULL; 1406 } 1407 1408 static void end_query(ares_channel_t *channel, ares_server_t *server, 1409 ares_query_t *query, ares_status_t status, 1410 const ares_dns_record_t *dnsrec) 1411 { 1412 /* If we were probing for the server to come back online, lets mark it as 1413 * no longer being probed */ 1414 if (server != NULL) { 1415 server->probe_pending = ARES_FALSE; 1416 } 1417 1418 ares_metrics_record(query, server, status, dnsrec); 1419 1420 /* Invoke the callback. */ 1421 query->callback(query->arg, status, query->timeouts, dnsrec); 1422 ares_free_query(query); 1423 1424 /* Check and notify if no other queries are enqueued on the channel. This 1425 * must come after the callback and freeing the query for 2 reasons. 1426 * 1) The callback itself may enqueue a new query 1427 * 2) Technically the current query isn't detached until it is free()'d. 1428 */ 1429 ares_queue_notify_empty(channel); 1430 } 1431 1432 void ares_free_query(ares_query_t *query) 1433 { 1434 ares_detach_query(query); 1435 /* Zero out some important stuff, to help catch bugs */ 1436 query->callback = NULL; 1437 query->arg = NULL; 1438 /* Deallocate the memory associated with the query */ 1439 ares_dns_record_destroy(query->query); 1440 1441 ares_free(query); 1442 }