ares_update_servers.c (37906B)
1 /* MIT License 2 * 3 * Copyright (c) 1998 Massachusetts Institute of Technology 4 * Copyright (c) 2008 Daniel Stenberg 5 * Copyright (c) 2023 Brad House 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 #include "ares_private.h" 29 30 #ifdef HAVE_ARPA_INET_H 31 # include <arpa/inet.h> 32 #endif 33 #ifdef HAVE_SYS_TYPES_H 34 # include <sys/types.h> 35 #endif 36 #ifdef HAVE_SYS_SOCKET_H 37 # include <sys/socket.h> 38 #endif 39 #ifdef HAVE_NET_IF_H 40 # include <net/if.h> 41 #endif 42 #ifdef HAVE_STDINT_H 43 # include <stdint.h> 44 #endif 45 46 #if defined(USE_WINSOCK) 47 # if defined(HAVE_IPHLPAPI_H) 48 # include <iphlpapi.h> 49 # endif 50 # if defined(HAVE_NETIOAPI_H) 51 # include <netioapi.h> 52 # endif 53 #endif 54 55 #include "ares_data.h" 56 #include "ares_inet_net_pton.h" 57 58 typedef struct { 59 struct ares_addr addr; 60 unsigned short tcp_port; 61 unsigned short udp_port; 62 63 char ll_iface[IF_NAMESIZE]; 64 unsigned int ll_scope; 65 } ares_sconfig_t; 66 67 static ares_bool_t ares_addr_match(const struct ares_addr *addr1, 68 const struct ares_addr *addr2) 69 { 70 if (addr1 == NULL && addr2 == NULL) { 71 return ARES_TRUE; /* LCOV_EXCL_LINE: DefensiveCoding */ 72 } 73 74 if (addr1 == NULL || addr2 == NULL) { 75 return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */ 76 } 77 78 if (addr1->family != addr2->family) { 79 return ARES_FALSE; 80 } 81 82 if (addr1->family == AF_INET && memcmp(&addr1->addr.addr4, &addr2->addr.addr4, 83 sizeof(addr1->addr.addr4)) == 0) { 84 return ARES_TRUE; 85 } 86 87 if (addr1->family == AF_INET6 && 88 memcmp(&addr1->addr.addr6._S6_un._S6_u8, &addr2->addr.addr6._S6_un._S6_u8, 89 sizeof(addr1->addr.addr6._S6_un._S6_u8)) == 0) { 90 return ARES_TRUE; 91 } 92 93 return ARES_FALSE; 94 } 95 96 ares_bool_t ares_subnet_match(const struct ares_addr *addr, 97 const struct ares_addr *subnet, 98 unsigned char netmask) 99 { 100 const unsigned char *addr_ptr; 101 const unsigned char *subnet_ptr; 102 size_t len; 103 size_t i; 104 105 if (addr == NULL || subnet == NULL) { 106 return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */ 107 } 108 109 if (addr->family != subnet->family) { 110 return ARES_FALSE; 111 } 112 113 if (addr->family == AF_INET) { 114 addr_ptr = (const unsigned char *)&addr->addr.addr4; 115 subnet_ptr = (const unsigned char *)&subnet->addr.addr4; 116 len = 4; 117 118 if (netmask > 32) { 119 return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */ 120 } 121 } else if (addr->family == AF_INET6) { 122 addr_ptr = (const unsigned char *)&addr->addr.addr6; 123 subnet_ptr = (const unsigned char *)&subnet->addr.addr6; 124 len = 16; 125 126 if (netmask > 128) { 127 return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */ 128 } 129 } else { 130 return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */ 131 } 132 133 for (i = 0; i < len && netmask > 0; i++) { 134 unsigned char mask = 0xff; 135 if (netmask < 8) { 136 mask <<= (8 - netmask); 137 netmask = 0; 138 } else { 139 netmask -= 8; 140 } 141 142 if ((addr_ptr[i] & mask) != (subnet_ptr[i] & mask)) { 143 return ARES_FALSE; 144 } 145 } 146 147 return ARES_TRUE; 148 } 149 150 ares_bool_t ares_addr_is_linklocal(const struct ares_addr *addr) 151 { 152 struct ares_addr subnet; 153 const unsigned char subnetaddr[16] = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 155 0x00, 0x00, 0x00, 0x00 }; 156 157 /* fe80::/10 */ 158 subnet.family = AF_INET6; 159 memcpy(&subnet.addr.addr6, subnetaddr, 16); 160 161 return ares_subnet_match(addr, &subnet, 10); 162 } 163 164 static ares_bool_t ares_server_blacklisted(const struct ares_addr *addr) 165 { 166 /* A list of blacklisted IPv6 subnets. */ 167 const struct { 168 const unsigned char netbase[16]; 169 unsigned char netmask; 170 } blacklist_v6[] = { 171 /* fec0::/10 was deprecated by [RFC3879] in September 2004. Formerly a 172 * Site-Local scoped address prefix. These are never valid DNS servers, 173 * but are known to be returned at least sometimes on Windows and Android. 174 */ 175 { { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 176 0x00, 0x00, 0x00, 0x00 }, 177 10 } 178 }; 179 180 size_t i; 181 182 if (addr->family != AF_INET6) { 183 return ARES_FALSE; 184 } 185 186 /* See if ipaddr matches any of the entries in the blacklist. */ 187 for (i = 0; i < sizeof(blacklist_v6) / sizeof(*blacklist_v6); i++) { 188 struct ares_addr subnet; 189 subnet.family = AF_INET6; 190 memcpy(&subnet.addr.addr6, blacklist_v6[i].netbase, 16); 191 if (ares_subnet_match(addr, &subnet, blacklist_v6[i].netmask)) { 192 return ARES_TRUE; 193 } 194 } 195 return ARES_FALSE; 196 } 197 198 static ares_status_t parse_nameserver_uri(ares_buf_t *buf, 199 ares_sconfig_t *sconfig) 200 { 201 ares_uri_t *uri = NULL; 202 ares_status_t status = ARES_SUCCESS; 203 const char *port; 204 char *ll_scope; 205 char hoststr[256]; 206 size_t addrlen; 207 208 status = ares_uri_parse_buf(&uri, buf); 209 if (status != ARES_SUCCESS) { 210 return status; 211 } 212 213 if (!ares_streq("dns", ares_uri_get_scheme(uri))) { 214 status = ARES_EBADSTR; 215 goto done; 216 } 217 218 ares_strcpy(hoststr, ares_uri_get_host(uri), sizeof(hoststr)); 219 ll_scope = strchr(hoststr, '%'); 220 if (ll_scope != NULL) { 221 *ll_scope = 0; 222 ll_scope++; 223 ares_strcpy(sconfig->ll_iface, ll_scope, sizeof(sconfig->ll_iface)); 224 } 225 226 /* Convert ip address from string to network byte order */ 227 sconfig->addr.family = AF_UNSPEC; 228 if (ares_dns_pton(hoststr, &sconfig->addr, &addrlen) == NULL) { 229 status = ARES_EBADSTR; 230 goto done; 231 } 232 233 sconfig->udp_port = ares_uri_get_port(uri); 234 sconfig->tcp_port = sconfig->udp_port; 235 port = ares_uri_get_query_key(uri, "tcpport"); 236 if (port != NULL) { 237 sconfig->tcp_port = (unsigned short)atoi(port); 238 } 239 240 done: 241 ares_uri_destroy(uri); 242 return status; 243 } 244 245 /* Parse address and port in these formats, either ipv4 or ipv6 addresses 246 * are allowed: 247 * ipaddr 248 * ipv4addr:port 249 * [ipaddr] 250 * [ipaddr]:port 251 * 252 * Modifiers: %iface 253 * 254 * TODO: #domain modifier 255 * 256 * If a port is not specified, will set port to 0. 257 * 258 * Will fail if an IPv6 nameserver as detected by 259 * ares_ipv6_server_blacklisted() 260 * 261 * Returns an error code on failure, else ARES_SUCCESS 262 */ 263 264 static ares_status_t parse_nameserver(ares_buf_t *buf, ares_sconfig_t *sconfig) 265 { 266 ares_status_t status; 267 char ipaddr[INET6_ADDRSTRLEN] = ""; 268 size_t addrlen; 269 270 memset(sconfig, 0, sizeof(*sconfig)); 271 272 /* Consume any leading whitespace */ 273 ares_buf_consume_whitespace(buf, ARES_TRUE); 274 275 /* pop off IP address. If it is in [ ] then it can be ipv4 or ipv6. If 276 * not, ipv4 only */ 277 if (ares_buf_begins_with(buf, (const unsigned char *)"[", 1)) { 278 /* Consume [ */ 279 ares_buf_consume(buf, 1); 280 281 ares_buf_tag(buf); 282 283 /* Consume until ] */ 284 if (ares_buf_consume_until_charset(buf, (const unsigned char *)"]", 1, 285 ARES_TRUE) == SIZE_MAX) { 286 return ARES_EBADSTR; 287 } 288 289 status = ares_buf_tag_fetch_string(buf, ipaddr, sizeof(ipaddr)); 290 if (status != ARES_SUCCESS) { 291 return status; 292 } 293 294 /* Skip over ] */ 295 ares_buf_consume(buf, 1); 296 } else { 297 size_t offset; 298 299 /* Not in [ ], see if '.' is in first 4 characters, if it is, then its ipv4, 300 * otherwise treat as ipv6 */ 301 ares_buf_tag(buf); 302 303 offset = ares_buf_consume_until_charset(buf, (const unsigned char *)".", 1, 304 ARES_TRUE); 305 ares_buf_tag_rollback(buf); 306 ares_buf_tag(buf); 307 308 if (offset > 0 && offset < 4) { 309 /* IPv4 */ 310 if (ares_buf_consume_charset(buf, (const unsigned char *)"0123456789.", 311 11) == 0) { 312 return ARES_EBADSTR; 313 } 314 } else { 315 /* IPv6 */ 316 const unsigned char ipv6_charset[] = "ABCDEFabcdef0123456789.:"; 317 if (ares_buf_consume_charset(buf, ipv6_charset, 318 sizeof(ipv6_charset) - 1) == 0) { 319 return ARES_EBADSTR; 320 } 321 } 322 323 status = ares_buf_tag_fetch_string(buf, ipaddr, sizeof(ipaddr)); 324 if (status != ARES_SUCCESS) { 325 return status; 326 } 327 } 328 329 /* Convert ip address from string to network byte order */ 330 sconfig->addr.family = AF_UNSPEC; 331 if (ares_dns_pton(ipaddr, &sconfig->addr, &addrlen) == NULL) { 332 return ARES_EBADSTR; 333 } 334 335 /* Pull off port */ 336 if (ares_buf_begins_with(buf, (const unsigned char *)":", 1)) { 337 char portstr[6]; 338 339 /* Consume : */ 340 ares_buf_consume(buf, 1); 341 342 ares_buf_tag(buf); 343 344 /* Read numbers */ 345 if (ares_buf_consume_charset(buf, (const unsigned char *)"0123456789", 346 10) == 0) { 347 return ARES_EBADSTR; 348 } 349 350 status = ares_buf_tag_fetch_string(buf, portstr, sizeof(portstr)); 351 if (status != ARES_SUCCESS) { 352 return status; 353 } 354 355 sconfig->udp_port = (unsigned short)atoi(portstr); 356 sconfig->tcp_port = sconfig->udp_port; 357 } 358 359 /* Pull off interface modifier */ 360 if (ares_buf_begins_with(buf, (const unsigned char *)"%", 1)) { 361 const unsigned char iface_charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 362 "abcdefghijklmnopqrstuvwxyz" 363 "0123456789.-_\\:{}"; 364 /* Consume % */ 365 ares_buf_consume(buf, 1); 366 367 ares_buf_tag(buf); 368 369 if (ares_buf_consume_charset(buf, iface_charset, 370 sizeof(iface_charset) - 1) == 0) { 371 return ARES_EBADSTR; 372 } 373 374 status = ares_buf_tag_fetch_string(buf, sconfig->ll_iface, 375 sizeof(sconfig->ll_iface)); 376 if (status != ARES_SUCCESS) { 377 return status; 378 } 379 } 380 381 /* Consume any trailing whitespace so we can bail out if there is something 382 * after we didn't read */ 383 ares_buf_consume_whitespace(buf, ARES_TRUE); 384 385 if (ares_buf_len(buf) != 0) { 386 return ARES_EBADSTR; 387 } 388 389 return ARES_SUCCESS; 390 } 391 392 static ares_status_t ares_sconfig_linklocal(const ares_channel_t *channel, 393 ares_sconfig_t *s, 394 const char *ll_iface) 395 { 396 unsigned int ll_scope = 0; 397 398 399 if (ares_str_isnum(ll_iface)) { 400 char ifname[IF_NAMESIZE] = ""; 401 ll_scope = (unsigned int)atoi(ll_iface); 402 if (channel->sock_funcs.aif_indextoname == NULL || 403 channel->sock_funcs.aif_indextoname(ll_scope, ifname, sizeof(ifname), 404 channel->sock_func_cb_data) == 405 NULL) { 406 DEBUGF(fprintf(stderr, "Interface %s for ipv6 Link Local not found\n", 407 ll_iface)); 408 return ARES_ENOTFOUND; 409 } 410 ares_strcpy(s->ll_iface, ifname, sizeof(s->ll_iface)); 411 s->ll_scope = ll_scope; 412 return ARES_SUCCESS; 413 } 414 415 if (channel->sock_funcs.aif_nametoindex != NULL) { 416 ll_scope = 417 channel->sock_funcs.aif_nametoindex(ll_iface, channel->sock_func_cb_data); 418 } 419 if (ll_scope == 0) { 420 DEBUGF(fprintf(stderr, "Interface %s for ipv6 Link Local not found\n", 421 ll_iface)); 422 return ARES_ENOTFOUND; 423 } 424 ares_strcpy(s->ll_iface, ll_iface, sizeof(s->ll_iface)); 425 s->ll_scope = ll_scope; 426 return ARES_SUCCESS; 427 } 428 429 ares_status_t ares_sconfig_append(const ares_channel_t *channel, 430 ares_llist_t **sconfig, 431 const struct ares_addr *addr, 432 unsigned short udp_port, 433 unsigned short tcp_port, const char *ll_iface) 434 { 435 ares_sconfig_t *s; 436 ares_status_t status; 437 438 if (sconfig == NULL || addr == NULL) { 439 return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */ 440 } 441 442 /* Silently skip blacklisted IPv6 servers. */ 443 if (ares_server_blacklisted(addr)) { 444 return ARES_SUCCESS; 445 } 446 447 s = ares_malloc_zero(sizeof(*s)); 448 if (s == NULL) { 449 return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ 450 } 451 452 if (*sconfig == NULL) { 453 *sconfig = ares_llist_create(ares_free); 454 if (*sconfig == NULL) { 455 status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ 456 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 457 } 458 } 459 460 memcpy(&s->addr, addr, sizeof(s->addr)); 461 s->udp_port = udp_port; 462 s->tcp_port = tcp_port; 463 464 /* Handle link-local enumeration. If an interface is specified on a 465 * non-link-local address, we'll simply end up ignoring that */ 466 if (ares_addr_is_linklocal(&s->addr)) { 467 if (ares_strlen(ll_iface) == 0) { 468 /* Silently ignore this entry, we require an interface */ 469 status = ARES_SUCCESS; 470 goto fail; 471 } 472 status = ares_sconfig_linklocal(channel, s, ll_iface); 473 /* Silently ignore this entry, we can't validate the interface */ 474 if (status != ARES_SUCCESS) { 475 status = ARES_SUCCESS; 476 goto fail; 477 } 478 } 479 480 if (ares_llist_insert_last(*sconfig, s) == NULL) { 481 status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ 482 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 483 } 484 485 return ARES_SUCCESS; 486 487 fail: 488 ares_free(s); 489 490 return status; 491 } 492 493 /* Add the IPv4 or IPv6 nameservers in str (separated by commas or spaces) to 494 * the servers list, updating servers and nservers as required. 495 * 496 * If a nameserver is encapsulated in [ ] it may optionally include a port 497 * suffix, e.g.: 498 * [127.0.0.1]:59591 499 * 500 * The extended format is required to support OpenBSD's resolv.conf format: 501 * https://man.openbsd.org/OpenBSD-5.1/resolv.conf.5 502 * As well as MacOS libresolv that may include a non-default port number. 503 * 504 * This will silently ignore blacklisted IPv6 nameservers as detected by 505 * ares_ipv6_server_blacklisted(). 506 * 507 * Returns an error code on failure, else ARES_SUCCESS. 508 */ 509 ares_status_t ares_sconfig_append_fromstr(const ares_channel_t *channel, 510 ares_llist_t **sconfig, 511 const char *str, 512 ares_bool_t ignore_invalid) 513 { 514 ares_status_t status = ARES_SUCCESS; 515 ares_buf_t *buf = NULL; 516 ares_array_t *list = NULL; 517 size_t num; 518 size_t i; 519 520 /* On Windows, there may be more than one nameserver specified in the same 521 * registry key, so we parse input as a space or comma separated list. 522 */ 523 buf = ares_buf_create_const((const unsigned char *)str, ares_strlen(str)); 524 if (buf == NULL) { 525 status = ARES_ENOMEM; 526 goto done; 527 } 528 529 status = ares_buf_split(buf, (const unsigned char *)" ,", 2, 530 ARES_BUF_SPLIT_NONE, 0, &list); 531 if (status != ARES_SUCCESS) { 532 goto done; 533 } 534 535 num = ares_array_len(list); 536 for (i = 0; i < num; i++) { 537 ares_buf_t **bufptr = ares_array_at(list, i); 538 ares_buf_t *entry = *bufptr; 539 ares_sconfig_t s; 540 541 status = parse_nameserver_uri(entry, &s); 542 if (status != ARES_SUCCESS) { 543 status = parse_nameserver(entry, &s); 544 } 545 546 if (status != ARES_SUCCESS) { 547 if (ignore_invalid) { 548 continue; 549 } else { 550 goto done; 551 } 552 } 553 554 status = ares_sconfig_append(channel, sconfig, &s.addr, s.udp_port, 555 s.tcp_port, s.ll_iface); 556 if (status != ARES_SUCCESS) { 557 goto done; /* LCOV_EXCL_LINE: OutOfMemory */ 558 } 559 } 560 561 status = ARES_SUCCESS; 562 563 done: 564 ares_array_destroy(list); 565 ares_buf_destroy(buf); 566 return status; 567 } 568 569 static unsigned short ares_sconfig_get_port(const ares_channel_t *channel, 570 const ares_sconfig_t *s, 571 ares_bool_t is_tcp) 572 { 573 unsigned short port = is_tcp ? s->tcp_port : s->udp_port; 574 575 if (port == 0) { 576 port = is_tcp ? channel->tcp_port : channel->udp_port; 577 } 578 579 if (port == 0) { 580 port = 53; 581 } 582 583 return port; 584 } 585 586 static ares_slist_node_t *ares_server_find(const ares_channel_t *channel, 587 const ares_sconfig_t *s) 588 { 589 ares_slist_node_t *node; 590 591 for (node = ares_slist_node_first(channel->servers); node != NULL; 592 node = ares_slist_node_next(node)) { 593 const ares_server_t *server = ares_slist_node_val(node); 594 595 if (!ares_addr_match(&server->addr, &s->addr)) { 596 continue; 597 } 598 599 if (server->tcp_port != ares_sconfig_get_port(channel, s, ARES_TRUE)) { 600 continue; 601 } 602 603 if (server->udp_port != ares_sconfig_get_port(channel, s, ARES_FALSE)) { 604 continue; 605 } 606 607 return node; 608 } 609 return NULL; 610 } 611 612 static ares_bool_t ares_server_isdup(const ares_channel_t *channel, 613 ares_llist_node_t *s) 614 { 615 /* Scan backwards to see if this is a duplicate */ 616 ares_llist_node_t *prev; 617 const ares_sconfig_t *server = ares_llist_node_val(s); 618 619 for (prev = ares_llist_node_prev(s); prev != NULL; 620 prev = ares_llist_node_prev(prev)) { 621 const ares_sconfig_t *p = ares_llist_node_val(prev); 622 623 if (!ares_addr_match(&server->addr, &p->addr)) { 624 continue; 625 } 626 627 if (ares_sconfig_get_port(channel, server, ARES_TRUE) != 628 ares_sconfig_get_port(channel, p, ARES_TRUE)) { 629 continue; 630 } 631 632 if (ares_sconfig_get_port(channel, server, ARES_FALSE) != 633 ares_sconfig_get_port(channel, p, ARES_FALSE)) { 634 continue; 635 } 636 637 return ARES_TRUE; 638 } 639 640 return ARES_FALSE; 641 } 642 643 static ares_status_t ares_server_create(ares_channel_t *channel, 644 const ares_sconfig_t *sconfig, 645 size_t idx) 646 { 647 ares_status_t status; 648 ares_server_t *server = ares_malloc_zero(sizeof(*server)); 649 650 if (server == NULL) { 651 return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ 652 } 653 654 server->idx = idx; 655 server->channel = channel; 656 server->udp_port = ares_sconfig_get_port(channel, sconfig, ARES_FALSE); 657 server->tcp_port = ares_sconfig_get_port(channel, sconfig, ARES_TRUE); 658 server->addr.family = sconfig->addr.family; 659 server->next_retry_time.sec = 0; 660 server->next_retry_time.usec = 0; 661 662 if (sconfig->addr.family == AF_INET) { 663 memcpy(&server->addr.addr.addr4, &sconfig->addr.addr.addr4, 664 sizeof(server->addr.addr.addr4)); 665 } else if (sconfig->addr.family == AF_INET6) { 666 memcpy(&server->addr.addr.addr6, &sconfig->addr.addr.addr6, 667 sizeof(server->addr.addr.addr6)); 668 } 669 670 /* Copy over link-local settings */ 671 if (ares_strlen(sconfig->ll_iface)) { 672 ares_strcpy(server->ll_iface, sconfig->ll_iface, sizeof(server->ll_iface)); 673 server->ll_scope = sconfig->ll_scope; 674 } 675 676 server->connections = ares_llist_create(NULL); 677 if (server->connections == NULL) { 678 status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ 679 goto done; /* LCOV_EXCL_LINE: OutOfMemory */ 680 } 681 682 if (ares_slist_insert(channel->servers, server) == NULL) { 683 status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ 684 goto done; /* LCOV_EXCL_LINE: OutOfMemory */ 685 } 686 687 status = ARES_SUCCESS; 688 689 done: 690 if (status != ARES_SUCCESS) { 691 ares_destroy_server(server); /* LCOV_EXCL_LINE: OutOfMemory */ 692 } 693 694 return status; 695 } 696 697 static ares_bool_t ares_server_in_newconfig(const ares_server_t *server, 698 ares_llist_t *srvlist) 699 { 700 ares_llist_node_t *node; 701 const ares_channel_t *channel = server->channel; 702 703 for (node = ares_llist_node_first(srvlist); node != NULL; 704 node = ares_llist_node_next(node)) { 705 const ares_sconfig_t *s = ares_llist_node_val(node); 706 707 if (!ares_addr_match(&server->addr, &s->addr)) { 708 continue; 709 } 710 711 if (server->tcp_port != ares_sconfig_get_port(channel, s, ARES_TRUE)) { 712 continue; 713 } 714 715 if (server->udp_port != ares_sconfig_get_port(channel, s, ARES_FALSE)) { 716 continue; 717 } 718 719 return ARES_TRUE; 720 } 721 722 return ARES_FALSE; 723 } 724 725 static ares_bool_t ares_servers_remove_stale(ares_channel_t *channel, 726 ares_llist_t *srvlist) 727 { 728 ares_bool_t stale_removed = ARES_FALSE; 729 ares_slist_node_t *snode = ares_slist_node_first(channel->servers); 730 731 while (snode != NULL) { 732 ares_slist_node_t *snext = ares_slist_node_next(snode); 733 const ares_server_t *server = ares_slist_node_val(snode); 734 if (!ares_server_in_newconfig(server, srvlist)) { 735 /* This will clean up all server state via the destruction callback and 736 * move any queries to new servers */ 737 ares_slist_node_destroy(snode); 738 stale_removed = ARES_TRUE; 739 } 740 snode = snext; 741 } 742 return stale_removed; 743 } 744 745 static void ares_servers_trim_single(ares_channel_t *channel) 746 { 747 while (ares_slist_len(channel->servers) > 1) { 748 ares_slist_node_destroy(ares_slist_node_last(channel->servers)); 749 } 750 } 751 752 ares_status_t ares_servers_update(ares_channel_t *channel, 753 ares_llist_t *server_list, 754 ares_bool_t user_specified) 755 { 756 ares_llist_node_t *node; 757 size_t idx = 0; 758 ares_status_t status; 759 ares_bool_t list_changed = ARES_FALSE; 760 761 if (channel == NULL) { 762 return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */ 763 } 764 765 /* NOTE: a NULL or zero entry server list is considered valid due to 766 * real-world people needing support for this for their test harnesses 767 */ 768 769 /* Add new entries */ 770 for (node = ares_llist_node_first(server_list); node != NULL; 771 node = ares_llist_node_next(node)) { 772 const ares_sconfig_t *sconfig = ares_llist_node_val(node); 773 ares_slist_node_t *snode; 774 775 /* If a server has already appeared in the list of new servers, skip it. */ 776 if (ares_server_isdup(channel, node)) { 777 continue; 778 } 779 780 snode = ares_server_find(channel, sconfig); 781 if (snode != NULL) { 782 ares_server_t *server = ares_slist_node_val(snode); 783 784 /* Copy over link-local settings. Its possible some of this data has 785 * changed, maybe ... */ 786 if (ares_strlen(sconfig->ll_iface)) { 787 ares_strcpy(server->ll_iface, sconfig->ll_iface, 788 sizeof(server->ll_iface)); 789 server->ll_scope = sconfig->ll_scope; 790 } 791 792 if (server->idx != idx) { 793 server->idx = idx; 794 /* Index changed, reinsert node, doesn't require any memory 795 * allocations so can't fail. */ 796 ares_slist_node_reinsert(snode); 797 } 798 } else { 799 status = ares_server_create(channel, sconfig, idx); 800 if (status != ARES_SUCCESS) { 801 goto done; 802 } 803 804 list_changed = ARES_TRUE; 805 } 806 807 idx++; 808 } 809 810 /* Remove any servers that don't exist in the current configuration */ 811 if (ares_servers_remove_stale(channel, server_list)) { 812 list_changed = ARES_TRUE; 813 } 814 815 /* Trim to one server if ARES_FLAG_PRIMARY is set. */ 816 if (channel->flags & ARES_FLAG_PRIMARY) { 817 ares_servers_trim_single(channel); 818 } 819 820 if (user_specified) { 821 /* Save servers as if they were passed in as an option */ 822 channel->optmask |= ARES_OPT_SERVERS; 823 } 824 825 /* Clear any cached query results only if the server list changed */ 826 if (list_changed) { 827 ares_qcache_flush(channel->qcache); 828 } 829 830 status = ARES_SUCCESS; 831 832 done: 833 return status; 834 } 835 836 static ares_status_t 837 ares_addr_node_to_sconfig_llist(const struct ares_addr_node *servers, 838 ares_llist_t **llist) 839 { 840 const struct ares_addr_node *node; 841 ares_llist_t *s; 842 843 *llist = NULL; 844 845 s = ares_llist_create(ares_free); 846 if (s == NULL) { 847 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 848 } 849 850 for (node = servers; node != NULL; node = node->next) { 851 ares_sconfig_t *sconfig; 852 853 /* Invalid entry */ 854 if (node->family != AF_INET && node->family != AF_INET6) { 855 continue; 856 } 857 858 sconfig = ares_malloc_zero(sizeof(*sconfig)); 859 if (sconfig == NULL) { 860 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 861 } 862 863 sconfig->addr.family = node->family; 864 if (node->family == AF_INET) { 865 memcpy(&sconfig->addr.addr.addr4, &node->addr.addr4, 866 sizeof(sconfig->addr.addr.addr4)); 867 } else if (sconfig->addr.family == AF_INET6) { 868 memcpy(&sconfig->addr.addr.addr6, &node->addr.addr6, 869 sizeof(sconfig->addr.addr.addr6)); 870 } 871 872 if (ares_llist_insert_last(s, sconfig) == NULL) { 873 ares_free(sconfig); /* LCOV_EXCL_LINE: OutOfMemory */ 874 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 875 } 876 } 877 878 *llist = s; 879 return ARES_SUCCESS; 880 881 /* LCOV_EXCL_START: OutOfMemory */ 882 fail: 883 ares_llist_destroy(s); 884 return ARES_ENOMEM; 885 /* LCOV_EXCL_STOP */ 886 } 887 888 static ares_status_t 889 ares_addrpnode_to_sconfig_llist(const struct ares_addr_port_node *servers, 890 ares_llist_t **llist) 891 { 892 const struct ares_addr_port_node *node; 893 ares_llist_t *s; 894 895 *llist = NULL; 896 897 s = ares_llist_create(ares_free); 898 if (s == NULL) { 899 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 900 } 901 902 for (node = servers; node != NULL; node = node->next) { 903 ares_sconfig_t *sconfig; 904 905 /* Invalid entry */ 906 if (node->family != AF_INET && node->family != AF_INET6) { 907 continue; 908 } 909 910 sconfig = ares_malloc_zero(sizeof(*sconfig)); 911 if (sconfig == NULL) { 912 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 913 } 914 915 sconfig->addr.family = node->family; 916 if (node->family == AF_INET) { 917 memcpy(&sconfig->addr.addr.addr4, &node->addr.addr4, 918 sizeof(sconfig->addr.addr.addr4)); 919 } else if (sconfig->addr.family == AF_INET6) { 920 memcpy(&sconfig->addr.addr.addr6, &node->addr.addr6, 921 sizeof(sconfig->addr.addr.addr6)); 922 } 923 924 sconfig->tcp_port = (unsigned short)node->tcp_port; 925 sconfig->udp_port = (unsigned short)node->udp_port; 926 927 if (ares_llist_insert_last(s, sconfig) == NULL) { 928 ares_free(sconfig); /* LCOV_EXCL_LINE: OutOfMemory */ 929 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 930 } 931 } 932 933 *llist = s; 934 return ARES_SUCCESS; 935 936 /* LCOV_EXCL_START: OutOfMemory */ 937 fail: 938 ares_llist_destroy(s); 939 return ARES_ENOMEM; 940 /* LCOV_EXCL_STOP */ 941 } 942 943 ares_status_t ares_in_addr_to_sconfig_llist(const struct in_addr *servers, 944 size_t nservers, 945 ares_llist_t **llist) 946 { 947 size_t i; 948 ares_llist_t *s; 949 950 *llist = NULL; 951 952 s = ares_llist_create(ares_free); 953 if (s == NULL) { 954 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 955 } 956 957 for (i = 0; servers != NULL && i < nservers; i++) { 958 ares_sconfig_t *sconfig; 959 960 sconfig = ares_malloc_zero(sizeof(*sconfig)); 961 if (sconfig == NULL) { 962 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 963 } 964 965 sconfig->addr.family = AF_INET; 966 memcpy(&sconfig->addr.addr.addr4, &servers[i], 967 sizeof(sconfig->addr.addr.addr4)); 968 969 if (ares_llist_insert_last(s, sconfig) == NULL) { 970 goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ 971 } 972 } 973 974 *llist = s; 975 return ARES_SUCCESS; 976 977 /* LCOV_EXCL_START: OutOfMemory */ 978 fail: 979 ares_llist_destroy(s); 980 return ARES_ENOMEM; 981 /* LCOV_EXCL_STOP */ 982 } 983 984 static ares_bool_t ares_server_use_uri(const ares_server_t *server) 985 { 986 /* Currently only reason to use new format is if the ports for udp and tcp 987 * are different */ 988 if (server->tcp_port != server->udp_port) { 989 return ARES_TRUE; 990 } 991 return ARES_FALSE; 992 } 993 994 static ares_status_t ares_get_server_addr_uri(const ares_server_t *server, 995 ares_buf_t *buf) 996 { 997 ares_uri_t *uri = NULL; 998 ares_status_t status; 999 char addr[INET6_ADDRSTRLEN]; 1000 1001 uri = ares_uri_create(); 1002 if (uri == NULL) { 1003 return ARES_ENOMEM; 1004 } 1005 1006 status = ares_uri_set_scheme(uri, "dns"); 1007 if (status != ARES_SUCCESS) { 1008 goto done; 1009 } 1010 1011 ares_inet_ntop(server->addr.family, &server->addr.addr, addr, sizeof(addr)); 1012 1013 if (ares_strlen(server->ll_iface)) { 1014 char addr_iface[256]; 1015 1016 snprintf(addr_iface, sizeof(addr_iface), "%s%%%s", addr, server->ll_iface); 1017 status = ares_uri_set_host(uri, addr_iface); 1018 } else { 1019 status = ares_uri_set_host(uri, addr); 1020 } 1021 1022 if (status != ARES_SUCCESS) { 1023 goto done; 1024 } 1025 1026 status = ares_uri_set_port(uri, server->udp_port); 1027 if (status != ARES_SUCCESS) { 1028 goto done; 1029 } 1030 1031 if (server->udp_port != server->tcp_port) { 1032 char port[6]; 1033 snprintf(port, sizeof(port), "%d", server->tcp_port); 1034 status = ares_uri_set_query_key(uri, "tcpport", port); 1035 if (status != ARES_SUCCESS) { 1036 goto done; 1037 } 1038 } 1039 1040 status = ares_uri_write_buf(uri, buf); 1041 if (status != ARES_SUCCESS) { 1042 goto done; 1043 } 1044 1045 done: 1046 ares_uri_destroy(uri); 1047 return status; 1048 } 1049 1050 /* Write out the details of a server to a buffer */ 1051 ares_status_t ares_get_server_addr(const ares_server_t *server, ares_buf_t *buf) 1052 { 1053 ares_status_t status; 1054 char addr[INET6_ADDRSTRLEN]; 1055 1056 if (ares_server_use_uri(server)) { 1057 return ares_get_server_addr_uri(server, buf); 1058 } 1059 1060 /* ipv4addr or [ipv6addr] */ 1061 if (server->addr.family == AF_INET6) { 1062 status = ares_buf_append_byte(buf, '['); 1063 if (status != ARES_SUCCESS) { 1064 return status; /* LCOV_EXCL_LINE: OutOfMemory */ 1065 } 1066 } 1067 1068 ares_inet_ntop(server->addr.family, &server->addr.addr, addr, sizeof(addr)); 1069 1070 status = ares_buf_append_str(buf, addr); 1071 if (status != ARES_SUCCESS) { 1072 return status; /* LCOV_EXCL_LINE: OutOfMemory */ 1073 } 1074 1075 if (server->addr.family == AF_INET6) { 1076 status = ares_buf_append_byte(buf, ']'); 1077 if (status != ARES_SUCCESS) { 1078 return status; /* LCOV_EXCL_LINE: OutOfMemory */ 1079 } 1080 } 1081 1082 /* :port */ 1083 status = ares_buf_append_byte(buf, ':'); 1084 if (status != ARES_SUCCESS) { 1085 return status; /* LCOV_EXCL_LINE: OutOfMemory */ 1086 } 1087 1088 status = ares_buf_append_num_dec(buf, server->udp_port, 0); 1089 if (status != ARES_SUCCESS) { 1090 return status; /* LCOV_EXCL_LINE: OutOfMemory */ 1091 } 1092 1093 /* %iface */ 1094 if (ares_strlen(server->ll_iface)) { 1095 status = ares_buf_append_byte(buf, '%'); 1096 if (status != ARES_SUCCESS) { 1097 return status; /* LCOV_EXCL_LINE: OutOfMemory */ 1098 } 1099 1100 status = ares_buf_append_str(buf, server->ll_iface); 1101 if (status != ARES_SUCCESS) { 1102 return status; /* LCOV_EXCL_LINE: OutOfMemory */ 1103 } 1104 } 1105 1106 return ARES_SUCCESS; 1107 } 1108 1109 int ares_get_servers(const ares_channel_t *channel, 1110 struct ares_addr_node **servers) 1111 { 1112 struct ares_addr_node *srvr_head = NULL; 1113 struct ares_addr_node *srvr_last = NULL; 1114 struct ares_addr_node *srvr_curr; 1115 ares_status_t status = ARES_SUCCESS; 1116 ares_slist_node_t *node; 1117 1118 if (channel == NULL) { 1119 return ARES_ENODATA; 1120 } 1121 1122 ares_channel_lock(channel); 1123 1124 for (node = ares_slist_node_first(channel->servers); node != NULL; 1125 node = ares_slist_node_next(node)) { 1126 const ares_server_t *server = ares_slist_node_val(node); 1127 1128 /* Allocate storage for this server node appending it to the list */ 1129 srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_NODE); 1130 if (!srvr_curr) { 1131 status = ARES_ENOMEM; 1132 break; 1133 } 1134 if (srvr_last) { 1135 srvr_last->next = srvr_curr; 1136 } else { 1137 srvr_head = srvr_curr; 1138 } 1139 srvr_last = srvr_curr; 1140 1141 /* Fill this server node data */ 1142 srvr_curr->family = server->addr.family; 1143 if (srvr_curr->family == AF_INET) { 1144 memcpy(&srvr_curr->addr.addr4, &server->addr.addr.addr4, 1145 sizeof(srvr_curr->addr.addr4)); 1146 } else { 1147 memcpy(&srvr_curr->addr.addr6, &server->addr.addr.addr6, 1148 sizeof(srvr_curr->addr.addr6)); 1149 } 1150 } 1151 1152 if (status != ARES_SUCCESS) { 1153 ares_free_data(srvr_head); 1154 srvr_head = NULL; 1155 } 1156 1157 *servers = srvr_head; 1158 1159 ares_channel_unlock(channel); 1160 1161 return (int)status; 1162 } 1163 1164 int ares_get_servers_ports(const ares_channel_t *channel, 1165 struct ares_addr_port_node **servers) 1166 { 1167 struct ares_addr_port_node *srvr_head = NULL; 1168 struct ares_addr_port_node *srvr_last = NULL; 1169 struct ares_addr_port_node *srvr_curr; 1170 ares_status_t status = ARES_SUCCESS; 1171 ares_slist_node_t *node; 1172 1173 if (channel == NULL) { 1174 return ARES_ENODATA; 1175 } 1176 1177 ares_channel_lock(channel); 1178 1179 for (node = ares_slist_node_first(channel->servers); node != NULL; 1180 node = ares_slist_node_next(node)) { 1181 const ares_server_t *server = ares_slist_node_val(node); 1182 1183 /* Allocate storage for this server node appending it to the list */ 1184 srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_PORT_NODE); 1185 if (!srvr_curr) { 1186 status = ARES_ENOMEM; 1187 break; 1188 } 1189 if (srvr_last) { 1190 srvr_last->next = srvr_curr; 1191 } else { 1192 srvr_head = srvr_curr; 1193 } 1194 srvr_last = srvr_curr; 1195 1196 /* Fill this server node data */ 1197 srvr_curr->family = server->addr.family; 1198 srvr_curr->udp_port = server->udp_port; 1199 srvr_curr->tcp_port = server->tcp_port; 1200 1201 if (srvr_curr->family == AF_INET) { 1202 memcpy(&srvr_curr->addr.addr4, &server->addr.addr.addr4, 1203 sizeof(srvr_curr->addr.addr4)); 1204 } else { 1205 memcpy(&srvr_curr->addr.addr6, &server->addr.addr.addr6, 1206 sizeof(srvr_curr->addr.addr6)); 1207 } 1208 } 1209 1210 if (status != ARES_SUCCESS) { 1211 ares_free_data(srvr_head); 1212 srvr_head = NULL; 1213 } 1214 1215 *servers = srvr_head; 1216 1217 ares_channel_unlock(channel); 1218 return (int)status; 1219 } 1220 1221 int ares_set_servers(ares_channel_t *channel, 1222 const struct ares_addr_node *servers) 1223 { 1224 ares_llist_t *slist; 1225 ares_status_t status; 1226 1227 if (channel == NULL) { 1228 return ARES_ENODATA; 1229 } 1230 1231 status = ares_addr_node_to_sconfig_llist(servers, &slist); 1232 if (status != ARES_SUCCESS) { 1233 return (int)status; 1234 } 1235 1236 ares_channel_lock(channel); 1237 status = ares_servers_update(channel, slist, ARES_TRUE); 1238 ares_channel_unlock(channel); 1239 1240 ares_llist_destroy(slist); 1241 1242 return (int)status; 1243 } 1244 1245 int ares_set_servers_ports(ares_channel_t *channel, 1246 const struct ares_addr_port_node *servers) 1247 { 1248 ares_llist_t *slist; 1249 ares_status_t status; 1250 1251 if (channel == NULL) { 1252 return ARES_ENODATA; 1253 } 1254 1255 status = ares_addrpnode_to_sconfig_llist(servers, &slist); 1256 if (status != ARES_SUCCESS) { 1257 return (int)status; 1258 } 1259 1260 ares_channel_lock(channel); 1261 status = ares_servers_update(channel, slist, ARES_TRUE); 1262 ares_channel_unlock(channel); 1263 1264 ares_llist_destroy(slist); 1265 1266 return (int)status; 1267 } 1268 1269 /* Incoming string format: host[:port][,host[:port]]... */ 1270 /* IPv6 addresses with ports require square brackets [fe80::1]:53 */ 1271 static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv) 1272 { 1273 ares_status_t status; 1274 ares_llist_t *slist = NULL; 1275 1276 if (channel == NULL) { 1277 return ARES_ENODATA; 1278 } 1279 1280 if (ares_strlen(_csv) == 0) { 1281 /* blank all servers */ 1282 ares_channel_lock(channel); 1283 status = ares_servers_update(channel, NULL, ARES_TRUE); 1284 ares_channel_unlock(channel); 1285 return status; 1286 } 1287 1288 status = ares_sconfig_append_fromstr(channel, &slist, _csv, ARES_FALSE); 1289 if (status != ARES_SUCCESS) { 1290 ares_llist_destroy(slist); 1291 return status; 1292 } 1293 1294 ares_channel_lock(channel); 1295 status = ares_servers_update(channel, slist, ARES_TRUE); 1296 ares_channel_unlock(channel); 1297 1298 ares_llist_destroy(slist); 1299 1300 return status; 1301 } 1302 1303 /* We'll go ahead and honor ports anyhow */ 1304 int ares_set_servers_csv(ares_channel_t *channel, const char *_csv) 1305 { 1306 return (int)set_servers_csv(channel, _csv); 1307 } 1308 1309 int ares_set_servers_ports_csv(ares_channel_t *channel, const char *_csv) 1310 { 1311 return (int)set_servers_csv(channel, _csv); 1312 } 1313 1314 char *ares_get_servers_csv(const ares_channel_t *channel) 1315 { 1316 ares_buf_t *buf = NULL; 1317 char *out = NULL; 1318 ares_slist_node_t *node; 1319 1320 ares_channel_lock(channel); 1321 1322 buf = ares_buf_create(); 1323 if (buf == NULL) { 1324 goto done; /* LCOV_EXCL_LINE: OutOfMemory */ 1325 } 1326 1327 for (node = ares_slist_node_first(channel->servers); node != NULL; 1328 node = ares_slist_node_next(node)) { 1329 ares_status_t status; 1330 const ares_server_t *server = ares_slist_node_val(node); 1331 1332 if (ares_buf_len(buf)) { 1333 status = ares_buf_append_byte(buf, ','); 1334 if (status != ARES_SUCCESS) { 1335 goto done; /* LCOV_EXCL_LINE: OutOfMemory */ 1336 } 1337 } 1338 1339 status = ares_get_server_addr(server, buf); 1340 if (status != ARES_SUCCESS) { 1341 goto done; /* LCOV_EXCL_LINE: OutOfMemory */ 1342 } 1343 } 1344 1345 out = ares_buf_finish_str(buf, NULL); 1346 buf = NULL; 1347 1348 done: 1349 ares_channel_unlock(channel); 1350 ares_buf_destroy(buf); 1351 return out; 1352 } 1353 1354 void ares_set_server_state_callback(ares_channel_t *channel, 1355 ares_server_state_callback cb, void *data) 1356 { 1357 if (channel == NULL) { 1358 return; /* LCOV_EXCL_LINE: DefensiveCoding */ 1359 } 1360 channel->server_state_cb = cb; 1361 channel->server_state_cb_data = data; 1362 }