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_setup.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
43 #if defined(USE_WINSOCK)
44 # if defined(HAVE_IPHLPAPI_H)
45 # include <iphlpapi.h>
46 # endif
47 # if defined(HAVE_NETIOAPI_H)
48 # include <netioapi.h>
49 # endif
50 #endif
51
52 #include "ares.h"
53 #include "ares_data.h"
54 #include "ares_inet_net_pton.h"
55 #include "ares_private.h"
56
57 typedef struct {
58 struct ares_addr addr;
59 unsigned short tcp_port;
60 unsigned short udp_port;
61
62 char ll_iface[IF_NAMESIZE];
63 unsigned int ll_scope;
64 } ares_sconfig_t;
65
ares__addr_match(const struct ares_addr * addr1,const struct ares_addr * addr2)66 static ares_bool_t ares__addr_match(const struct ares_addr *addr1,
67 const struct ares_addr *addr2)
68 {
69 if (addr1 == NULL && addr2 == NULL) {
70 return ARES_TRUE;
71 }
72
73 if (addr1 == NULL || addr2 == NULL) {
74 return ARES_FALSE;
75 }
76
77 if (addr1->family != addr2->family) {
78 return ARES_FALSE;
79 }
80
81 if (addr1->family == AF_INET && memcmp(&addr1->addr.addr4, &addr2->addr.addr4,
82 sizeof(addr1->addr.addr4)) == 0) {
83 return ARES_TRUE;
84 }
85
86 if (addr1->family == AF_INET6 &&
87 memcmp(&addr1->addr.addr6._S6_un._S6_u8, &addr2->addr.addr6._S6_un._S6_u8,
88 sizeof(addr1->addr.addr6._S6_un._S6_u8)) == 0) {
89 return ARES_TRUE;
90 }
91
92 return ARES_FALSE;
93 }
94
ares__subnet_match(const struct ares_addr * addr,const struct ares_addr * subnet,unsigned char netmask)95 ares_bool_t ares__subnet_match(const struct ares_addr *addr,
96 const struct ares_addr *subnet,
97 unsigned char netmask)
98 {
99 const unsigned char *addr_ptr;
100 const unsigned char *subnet_ptr;
101 size_t len;
102 size_t i;
103
104 if (addr == NULL || subnet == NULL) {
105 return ARES_FALSE;
106 }
107
108 if (addr->family != subnet->family) {
109 return ARES_FALSE;
110 }
111
112 if (addr->family == AF_INET) {
113 addr_ptr = (const unsigned char *)&addr->addr.addr4;
114 subnet_ptr = (const unsigned char *)&subnet->addr.addr4;
115 len = 4;
116
117 if (netmask > 32) {
118 return ARES_FALSE;
119 }
120 } else if (addr->family == AF_INET6) {
121 addr_ptr = (const unsigned char *)&addr->addr.addr6;
122 subnet_ptr = (const unsigned char *)&subnet->addr.addr6;
123 len = 16;
124
125 if (netmask > 128) {
126 return ARES_FALSE;
127 }
128 } else {
129 return ARES_FALSE;
130 }
131
132 for (i = 0; i < len && netmask > 0; i++) {
133 unsigned char mask = 0xff;
134 if (netmask < 8) {
135 mask <<= (8 - netmask);
136 netmask = 0;
137 } else {
138 netmask -= 8;
139 }
140
141 if ((addr_ptr[i] & mask) != (subnet_ptr[i] & mask)) {
142 return ARES_FALSE;
143 }
144 }
145
146 return ARES_TRUE;
147 }
148
ares__addr_is_linklocal(const struct ares_addr * addr)149 ares_bool_t ares__addr_is_linklocal(const struct ares_addr *addr)
150 {
151 struct ares_addr subnet;
152 const unsigned char subnetaddr[16] = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00 };
155
156 /* fe80::/10 */
157 subnet.family = AF_INET6;
158 memcpy(&subnet.addr.addr6, subnetaddr, 16);
159
160 return ares__subnet_match(addr, &subnet, 10);
161 }
162
ares_server_blacklisted(const struct ares_addr * addr)163 static ares_bool_t ares_server_blacklisted(const struct ares_addr *addr)
164 {
165 /* A list of blacklisted IPv6 subnets. */
166 const struct {
167 const unsigned char netbase[16];
168 unsigned char netmask;
169 } blacklist_v6[] = {
170 /* fec0::/10 was deprecated by [RFC3879] in September 2004. Formerly a
171 * Site-Local scoped address prefix. These are never valid DNS servers,
172 * but are known to be returned at least sometimes on Windows and Android.
173 */
174 {{ 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0x00, 0x00 },
176 10}
177 };
178
179 size_t i;
180
181 if (addr->family != AF_INET6) {
182 return ARES_FALSE;
183 }
184
185 /* See if ipaddr matches any of the entries in the blacklist. */
186 for (i = 0; i < sizeof(blacklist_v6) / sizeof(*blacklist_v6); i++) {
187 struct ares_addr subnet;
188 subnet.family = AF_INET6;
189 memcpy(&subnet.addr.addr6, blacklist_v6[i].netbase, 16);
190 if (ares__subnet_match(addr, &subnet, blacklist_v6[i].netmask)) {
191 return ARES_TRUE;
192 }
193 }
194 return ARES_FALSE;
195 }
196
197 /* Parse address and port in these formats, either ipv4 or ipv6 addresses
198 * are allowed:
199 * ipaddr
200 * ipv4addr:port
201 * [ipaddr]
202 * [ipaddr]:port
203 *
204 * Modifiers: %iface
205 *
206 * TODO: #domain modifier
207 *
208 * If a port is not specified, will set port to 0.
209 *
210 * Will fail if an IPv6 nameserver as detected by
211 * ares_ipv6_server_blacklisted()
212 *
213 * Returns an error code on failure, else ARES_SUCCESS
214 */
215
parse_nameserver(ares__buf_t * buf,ares_sconfig_t * sconfig)216 static ares_status_t parse_nameserver(ares__buf_t *buf, ares_sconfig_t *sconfig)
217 {
218 ares_status_t status;
219 char ipaddr[INET6_ADDRSTRLEN] = "";
220 size_t addrlen;
221
222 memset(sconfig, 0, sizeof(*sconfig));
223
224 /* Consume any leading whitespace */
225 ares__buf_consume_whitespace(buf, ARES_TRUE);
226
227 /* pop off IP address. If it is in [ ] then it can be ipv4 or ipv6. If
228 * not, ipv4 only */
229 if (ares__buf_begins_with(buf, (const unsigned char *)"[", 1)) {
230 /* Consume [ */
231 ares__buf_consume(buf, 1);
232
233 ares__buf_tag(buf);
234
235 /* Consume until ] */
236 if (ares__buf_consume_until_charset(buf, (const unsigned char *)"]", 1,
237 ARES_TRUE) == 0) {
238 return ARES_EBADSTR;
239 }
240
241 status = ares__buf_tag_fetch_string(buf, ipaddr, sizeof(ipaddr));
242 if (status != ARES_SUCCESS) {
243 return status;
244 }
245
246 /* Skip over ] */
247 ares__buf_consume(buf, 1);
248 } else {
249 size_t offset;
250
251 /* Not in [ ], see if '.' is in first 4 characters, if it is, then its ipv4,
252 * otherwise treat as ipv6 */
253 ares__buf_tag(buf);
254
255 offset = ares__buf_consume_until_charset(buf, (const unsigned char *)".", 1,
256 ARES_TRUE);
257 ares__buf_tag_rollback(buf);
258 ares__buf_tag(buf);
259
260 if (offset > 0 && offset < 4) {
261 /* IPv4 */
262 if (ares__buf_consume_charset(buf, (const unsigned char *)"0123456789.",
263 11) == 0) {
264 return ARES_EBADSTR;
265 }
266 } else {
267 /* IPv6 */
268 const unsigned char ipv6_charset[] = "ABCDEFabcdef0123456789.:";
269 if (ares__buf_consume_charset(buf, ipv6_charset, sizeof(ipv6_charset)) ==
270 0) {
271 return ARES_EBADSTR;
272 }
273 }
274
275 status = ares__buf_tag_fetch_string(buf, ipaddr, sizeof(ipaddr));
276 if (status != ARES_SUCCESS) {
277 return status;
278 }
279 }
280
281 /* Convert ip address from string to network byte order */
282 sconfig->addr.family = AF_UNSPEC;
283 if (ares_dns_pton(ipaddr, &sconfig->addr, &addrlen) == NULL) {
284 return ARES_EBADSTR;
285 }
286
287 /* Pull off port */
288 if (ares__buf_begins_with(buf, (const unsigned char *)":", 1)) {
289 char portstr[6];
290
291 /* Consume : */
292 ares__buf_consume(buf, 1);
293
294 ares__buf_tag(buf);
295
296 /* Read numbers */
297 if (ares__buf_consume_charset(buf, (const unsigned char *)"0123456789",
298 10) == 0) {
299 return ARES_EBADSTR;
300 }
301
302 status = ares__buf_tag_fetch_string(buf, portstr, sizeof(portstr));
303 if (status != ARES_SUCCESS) {
304 return status;
305 }
306
307 sconfig->udp_port = (unsigned short)atoi(portstr);
308 sconfig->tcp_port = sconfig->udp_port;
309 }
310
311 /* Pull off interface modifier */
312 if (ares__buf_begins_with(buf, (const unsigned char *)"%", 1)) {
313 const unsigned char iface_charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
314 "abcdefghijklmnopqrstuvwxyz"
315 "0123456789.-_\\:{}";
316 /* Consume % */
317 ares__buf_consume(buf, 1);
318
319 ares__buf_tag(buf);
320
321 if (ares__buf_consume_charset(buf, iface_charset, sizeof(iface_charset)) ==
322 0) {
323 return ARES_EBADSTR;
324 }
325
326 status = ares__buf_tag_fetch_string(buf, sconfig->ll_iface,
327 sizeof(sconfig->ll_iface));
328 if (status != ARES_SUCCESS) {
329 return status;
330 }
331 }
332
333 /* Consume any trailing whitespace so we can bail out if there is something
334 * after we didn't read */
335 ares__buf_consume_whitespace(buf, ARES_TRUE);
336
337 if (ares__buf_len(buf) != 0) {
338 return ARES_EBADSTR;
339 }
340
341 return ARES_SUCCESS;
342 }
343
ares__sconfig_linklocal(ares_sconfig_t * s,const char * ll_iface)344 static ares_status_t ares__sconfig_linklocal(ares_sconfig_t *s,
345 const char *ll_iface)
346 {
347 unsigned int ll_scope = 0;
348
349 if (ares_str_isnum(ll_iface)) {
350 char ifname[IF_NAMESIZE] = "";
351 ll_scope = (unsigned int)atoi(ll_iface);
352 if (ares__if_indextoname(ll_scope, ifname, sizeof(ifname)) == NULL) {
353 DEBUGF(fprintf(stderr, "Interface %s for ipv6 Link Local not found\n",
354 ll_iface));
355 return ARES_ENOTFOUND;
356 }
357 ares_strcpy(s->ll_iface, ifname, sizeof(s->ll_iface));
358 s->ll_scope = ll_scope;
359 return ARES_SUCCESS;
360 }
361
362 ll_scope = ares__if_nametoindex(ll_iface);
363 if (ll_scope == 0) {
364 DEBUGF(fprintf(stderr, "Interface %s for ipv6 Link Local not found\n",
365 ll_iface));
366 return ARES_ENOTFOUND;
367 }
368 ares_strcpy(s->ll_iface, ll_iface, sizeof(s->ll_iface));
369 s->ll_scope = ll_scope;
370 return ARES_SUCCESS;
371 }
372
ares__sconfig_append(ares__llist_t ** sconfig,const struct ares_addr * addr,unsigned short udp_port,unsigned short tcp_port,const char * ll_iface)373 ares_status_t ares__sconfig_append(ares__llist_t **sconfig,
374 const struct ares_addr *addr,
375 unsigned short udp_port,
376 unsigned short tcp_port,
377 const char *ll_iface)
378 {
379 ares_sconfig_t *s;
380 ares_status_t status;
381
382 if (sconfig == NULL || addr == NULL) {
383 return ARES_EFORMERR;
384 }
385
386 /* Silently skip blacklisted IPv6 servers. */
387 if (ares_server_blacklisted(addr)) {
388 return ARES_SUCCESS;
389 }
390
391 s = ares_malloc_zero(sizeof(*s));
392 if (s == NULL) {
393 return ARES_ENOMEM;
394 }
395
396 if (*sconfig == NULL) {
397 *sconfig = ares__llist_create(ares_free);
398 if (*sconfig == NULL) {
399 status = ARES_ENOMEM;
400 goto fail;
401 }
402 }
403
404 memcpy(&s->addr, addr, sizeof(s->addr));
405 s->udp_port = udp_port;
406 s->tcp_port = tcp_port;
407
408 /* Handle link-local enumeration */
409 if (ares_strlen(ll_iface) && ares__addr_is_linklocal(&s->addr)) {
410 status = ares__sconfig_linklocal(s, ll_iface);
411 /* Silently ignore this entry */
412 if (status != ARES_SUCCESS) {
413 status = ARES_SUCCESS;
414 goto fail;
415 }
416 }
417
418 if (ares__llist_insert_last(*sconfig, s) == NULL) {
419 status = ARES_ENOMEM;
420 goto fail;
421 }
422
423 return ARES_SUCCESS;
424
425 fail:
426 ares_free(s);
427
428 return status;
429 }
430
431 /* Add the IPv4 or IPv6 nameservers in str (separated by commas or spaces) to
432 * the servers list, updating servers and nservers as required.
433 *
434 * If a nameserver is encapsulated in [ ] it may optionally include a port
435 * suffix, e.g.:
436 * [127.0.0.1]:59591
437 *
438 * The extended format is required to support OpenBSD's resolv.conf format:
439 * https://man.openbsd.org/OpenBSD-5.1/resolv.conf.5
440 * As well as MacOS libresolv that may include a non-default port number.
441 *
442 * This will silently ignore blacklisted IPv6 nameservers as detected by
443 * ares_ipv6_server_blacklisted().
444 *
445 * Returns an error code on failure, else ARES_SUCCESS.
446 */
ares__sconfig_append_fromstr(ares__llist_t ** sconfig,const char * str,ares_bool_t ignore_invalid)447 ares_status_t ares__sconfig_append_fromstr(ares__llist_t **sconfig,
448 const char *str,
449 ares_bool_t ignore_invalid)
450 {
451 ares_status_t status = ARES_SUCCESS;
452 ares__buf_t *buf = NULL;
453 ares__llist_t *list = NULL;
454 ares__llist_node_t *node;
455
456 /* On Windows, there may be more than one nameserver specified in the same
457 * registry key, so we parse input as a space or comma separated list.
458 */
459 buf = ares__buf_create_const((const unsigned char *)str, ares_strlen(str));
460 if (buf == NULL) {
461 status = ARES_ENOMEM;
462 goto done;
463 }
464
465 status = ares__buf_split(buf, (const unsigned char *)" ,", 2,
466 ARES_BUF_SPLIT_NONE, &list);
467 if (status != ARES_SUCCESS) {
468 goto done;
469 }
470
471 for (node = ares__llist_node_first(list); node != NULL;
472 node = ares__llist_node_next(node)) {
473 ares__buf_t *entry = ares__llist_node_val(node);
474 ares_sconfig_t s;
475
476 status = parse_nameserver(entry, &s);
477 if (status != ARES_SUCCESS) {
478 if (ignore_invalid) {
479 continue;
480 } else {
481 goto done;
482 }
483 }
484
485 status = ares__sconfig_append(sconfig, &s.addr, s.udp_port, s.tcp_port,
486 s.ll_iface);
487 if (status != ARES_SUCCESS) {
488 goto done;
489 }
490 }
491
492 status = ARES_SUCCESS;
493
494 done:
495 ares__llist_destroy(list);
496 ares__buf_destroy(buf);
497 return status;
498 }
499
ares__sconfig_get_port(const ares_channel_t * channel,const ares_sconfig_t * s,ares_bool_t is_tcp)500 static unsigned short ares__sconfig_get_port(const ares_channel_t *channel,
501 const ares_sconfig_t *s,
502 ares_bool_t is_tcp)
503 {
504 unsigned short port = is_tcp ? s->tcp_port : s->udp_port;
505
506 if (port == 0) {
507 port = is_tcp ? channel->tcp_port : channel->udp_port;
508 }
509
510 if (port == 0) {
511 port = 53;
512 }
513
514 return port;
515 }
516
ares__server_find(ares_channel_t * channel,const ares_sconfig_t * s)517 static ares__slist_node_t *ares__server_find(ares_channel_t *channel,
518 const ares_sconfig_t *s)
519 {
520 ares__slist_node_t *node;
521
522 for (node = ares__slist_node_first(channel->servers); node != NULL;
523 node = ares__slist_node_next(node)) {
524 const struct server_state *server = ares__slist_node_val(node);
525
526 if (!ares__addr_match(&server->addr, &s->addr)) {
527 continue;
528 }
529
530 if (server->tcp_port != ares__sconfig_get_port(channel, s, ARES_TRUE)) {
531 continue;
532 }
533
534 if (server->udp_port != ares__sconfig_get_port(channel, s, ARES_FALSE)) {
535 continue;
536 }
537
538 return node;
539 }
540 return NULL;
541 }
542
ares__server_isdup(const ares_channel_t * channel,ares__llist_node_t * s)543 static ares_bool_t ares__server_isdup(const ares_channel_t *channel,
544 ares__llist_node_t *s)
545 {
546 /* Scan backwards to see if this is a duplicate */
547 ares__llist_node_t *prev;
548 const ares_sconfig_t *server = ares__llist_node_val(s);
549
550 for (prev = ares__llist_node_prev(s); prev != NULL;
551 prev = ares__llist_node_prev(prev)) {
552 const ares_sconfig_t *p = ares__llist_node_val(prev);
553
554 if (!ares__addr_match(&server->addr, &p->addr)) {
555 continue;
556 }
557
558 if (ares__sconfig_get_port(channel, server, ARES_TRUE) !=
559 ares__sconfig_get_port(channel, p, ARES_TRUE)) {
560 continue;
561 }
562
563 if (ares__sconfig_get_port(channel, server, ARES_FALSE) !=
564 ares__sconfig_get_port(channel, p, ARES_FALSE)) {
565 continue;
566 }
567
568 return ARES_TRUE;
569 }
570
571 return ARES_FALSE;
572 }
573
ares__server_create(ares_channel_t * channel,const ares_sconfig_t * sconfig,size_t idx)574 static ares_status_t ares__server_create(ares_channel_t *channel,
575 const ares_sconfig_t *sconfig,
576 size_t idx)
577 {
578 ares_status_t status;
579 struct server_state *server = ares_malloc_zero(sizeof(*server));
580
581 if (server == NULL) {
582 return ARES_ENOMEM;
583 }
584
585 server->idx = idx;
586 server->channel = channel;
587 server->udp_port = ares__sconfig_get_port(channel, sconfig, ARES_FALSE);
588 server->tcp_port = ares__sconfig_get_port(channel, sconfig, ARES_TRUE);
589 server->addr.family = sconfig->addr.family;
590
591 if (sconfig->addr.family == AF_INET) {
592 memcpy(&server->addr.addr.addr4, &sconfig->addr.addr.addr4,
593 sizeof(server->addr.addr.addr4));
594 } else if (sconfig->addr.family == AF_INET6) {
595 memcpy(&server->addr.addr.addr6, &sconfig->addr.addr.addr6,
596 sizeof(server->addr.addr.addr6));
597 }
598
599 /* Copy over link-local settings */
600 if (ares_strlen(sconfig->ll_iface)) {
601 ares_strcpy(server->ll_iface, sconfig->ll_iface, sizeof(server->ll_iface));
602 server->ll_scope = sconfig->ll_scope;
603 }
604
605 server->tcp_parser = ares__buf_create();
606 if (server->tcp_parser == NULL) {
607 status = ARES_ENOMEM;
608 goto done;
609 }
610
611 server->tcp_send = ares__buf_create();
612 if (server->tcp_send == NULL) {
613 status = ARES_ENOMEM;
614 goto done;
615 }
616
617 server->connections = ares__llist_create(NULL);
618 if (server->connections == NULL) {
619 status = ARES_ENOMEM;
620 goto done;
621 }
622
623 if (ares__slist_insert(channel->servers, server) == NULL) {
624 status = ARES_ENOMEM;
625 goto done;
626 }
627
628 status = ARES_SUCCESS;
629
630 done:
631 if (status != ARES_SUCCESS) {
632 ares__destroy_server(server);
633 }
634
635 return status;
636 }
637
ares__server_in_newconfig(const struct server_state * server,ares__llist_t * srvlist)638 static ares_bool_t ares__server_in_newconfig(const struct server_state *server,
639 ares__llist_t *srvlist)
640 {
641 ares__llist_node_t *node;
642 const ares_channel_t *channel = server->channel;
643
644 for (node = ares__llist_node_first(srvlist); node != NULL;
645 node = ares__llist_node_next(node)) {
646 const ares_sconfig_t *s = ares__llist_node_val(node);
647
648 if (!ares__addr_match(&server->addr, &s->addr)) {
649 continue;
650 }
651
652 if (server->tcp_port != ares__sconfig_get_port(channel, s, ARES_TRUE)) {
653 continue;
654 }
655
656 if (server->udp_port != ares__sconfig_get_port(channel, s, ARES_FALSE)) {
657 continue;
658 }
659
660 return ARES_TRUE;
661 }
662
663 return ARES_FALSE;
664 }
665
ares__servers_remove_stale(ares_channel_t * channel,ares__llist_t * srvlist)666 static void ares__servers_remove_stale(ares_channel_t *channel,
667 ares__llist_t *srvlist)
668 {
669 ares__slist_node_t *snode = ares__slist_node_first(channel->servers);
670
671 while (snode != NULL) {
672 ares__slist_node_t *snext = ares__slist_node_next(snode);
673 const struct server_state *server = ares__slist_node_val(snode);
674 if (!ares__server_in_newconfig(server, srvlist)) {
675 /* This will clean up all server state via the destruction callback and
676 * move any queries to new servers */
677 ares__slist_node_destroy(snode);
678 }
679 snode = snext;
680 }
681 }
682
ares__servers_trim_single(ares_channel_t * channel)683 static void ares__servers_trim_single(ares_channel_t *channel)
684 {
685 while (ares__slist_len(channel->servers) > 1) {
686 ares__slist_node_destroy(ares__slist_node_last(channel->servers));
687 }
688 }
689
ares__servers_update(ares_channel_t * channel,ares__llist_t * server_list,ares_bool_t user_specified)690 ares_status_t ares__servers_update(ares_channel_t *channel,
691 ares__llist_t *server_list,
692 ares_bool_t user_specified)
693 {
694 ares__llist_node_t *node;
695 size_t idx = 0;
696 ares_status_t status;
697
698 if (channel == NULL) {
699 return ARES_EFORMERR;
700 }
701
702 ares__channel_lock(channel);
703
704 /* NOTE: a NULL or zero entry server list is considered valid due to
705 * real-world people needing support for this for their test harnesses
706 */
707
708 /* Add new entries */
709 for (node = ares__llist_node_first(server_list); node != NULL;
710 node = ares__llist_node_next(node)) {
711 const ares_sconfig_t *sconfig = ares__llist_node_val(node);
712 ares__slist_node_t *snode;
713
714 /* Don't add duplicate servers! */
715 if (ares__server_isdup(channel, node)) {
716 continue;
717 }
718
719 snode = ares__server_find(channel, sconfig);
720 if (snode != NULL) {
721 struct server_state *server = ares__slist_node_val(snode);
722
723 /* Copy over link-local settings. Its possible some of this data has
724 * changed, maybe ... */
725 if (ares_strlen(sconfig->ll_iface)) {
726 ares_strcpy(server->ll_iface, sconfig->ll_iface,
727 sizeof(server->ll_iface));
728 server->ll_scope = sconfig->ll_scope;
729 }
730
731 if (server->idx != idx) {
732 server->idx = idx;
733 /* Index changed, reinsert node, doesn't require any memory
734 * allocations so can't fail. */
735 ares__slist_node_reinsert(snode);
736 }
737 } else {
738 status = ares__server_create(channel, sconfig, idx);
739 if (status != ARES_SUCCESS) {
740 goto done;
741 }
742 }
743
744 idx++;
745 }
746
747 /* Remove any servers that don't exist in the current configuration */
748 ares__servers_remove_stale(channel, server_list);
749
750 /* Trim to one server if ARES_FLAG_PRIMARY is set. */
751 if (channel->flags & ARES_FLAG_PRIMARY) {
752 ares__servers_trim_single(channel);
753 }
754
755 if (user_specified) {
756 /* Save servers as if they were passed in as an option */
757 channel->optmask |= ARES_OPT_SERVERS;
758 }
759
760 /* Clear any cached query results */
761 ares__qcache_flush(channel->qcache);
762
763 status = ARES_SUCCESS;
764
765 done:
766 ares__channel_unlock(channel);
767 return status;
768 }
769
770 static ares_status_t
ares_addr_node_to_server_config_llist(const struct ares_addr_node * servers,ares__llist_t ** llist)771 ares_addr_node_to_server_config_llist(const struct ares_addr_node *servers,
772 ares__llist_t **llist)
773 {
774 const struct ares_addr_node *node;
775 ares__llist_t *s;
776
777 *llist = NULL;
778
779 s = ares__llist_create(ares_free);
780 if (s == NULL) {
781 goto fail;
782 }
783
784 for (node = servers; node != NULL; node = node->next) {
785 ares_sconfig_t *sconfig;
786
787 /* Invalid entry */
788 if (node->family != AF_INET && node->family != AF_INET6) {
789 continue;
790 }
791
792 sconfig = ares_malloc_zero(sizeof(*sconfig));
793 if (sconfig == NULL) {
794 goto fail;
795 }
796
797 sconfig->addr.family = node->family;
798 if (node->family == AF_INET) {
799 memcpy(&sconfig->addr.addr.addr4, &node->addr.addr4,
800 sizeof(sconfig->addr.addr.addr4));
801 } else if (sconfig->addr.family == AF_INET6) {
802 memcpy(&sconfig->addr.addr.addr6, &node->addr.addr6,
803 sizeof(sconfig->addr.addr.addr6));
804 }
805
806 if (ares__llist_insert_last(s, sconfig) == NULL) {
807 ares_free(sconfig);
808 goto fail;
809 }
810 }
811
812 *llist = s;
813 return ARES_SUCCESS;
814
815 fail:
816 ares__llist_destroy(s);
817 return ARES_ENOMEM;
818 }
819
ares_addr_port_node_to_server_config_llist(const struct ares_addr_port_node * servers,ares__llist_t ** llist)820 static ares_status_t ares_addr_port_node_to_server_config_llist(
821 const struct ares_addr_port_node *servers, ares__llist_t **llist)
822 {
823 const struct ares_addr_port_node *node;
824 ares__llist_t *s;
825
826 *llist = NULL;
827
828 s = ares__llist_create(ares_free);
829 if (s == NULL) {
830 goto fail;
831 }
832
833 for (node = servers; node != NULL; node = node->next) {
834 ares_sconfig_t *sconfig;
835
836 /* Invalid entry */
837 if (node->family != AF_INET && node->family != AF_INET6) {
838 continue;
839 }
840
841 sconfig = ares_malloc_zero(sizeof(*sconfig));
842 if (sconfig == NULL) {
843 goto fail;
844 }
845
846 sconfig->addr.family = node->family;
847 if (node->family == AF_INET) {
848 memcpy(&sconfig->addr.addr.addr4, &node->addr.addr4,
849 sizeof(sconfig->addr.addr.addr4));
850 } else if (sconfig->addr.family == AF_INET6) {
851 memcpy(&sconfig->addr.addr.addr6, &node->addr.addr6,
852 sizeof(sconfig->addr.addr.addr6));
853 }
854
855 sconfig->tcp_port = (unsigned short)node->tcp_port;
856 sconfig->udp_port = (unsigned short)node->udp_port;
857
858 if (ares__llist_insert_last(s, sconfig) == NULL) {
859 ares_free(sconfig);
860 goto fail;
861 }
862 }
863
864 *llist = s;
865 return ARES_SUCCESS;
866
867 fail:
868 ares__llist_destroy(s);
869 return ARES_ENOMEM;
870 }
871
ares_in_addr_to_server_config_llist(const struct in_addr * servers,size_t nservers,ares__llist_t ** llist)872 ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
873 size_t nservers,
874 ares__llist_t **llist)
875 {
876 size_t i;
877 ares__llist_t *s;
878
879 *llist = NULL;
880
881 s = ares__llist_create(ares_free);
882 if (s == NULL) {
883 goto fail;
884 }
885
886 for (i = 0; servers != NULL && i < nservers; i++) {
887 ares_sconfig_t *sconfig;
888
889 sconfig = ares_malloc_zero(sizeof(*sconfig));
890 if (sconfig == NULL) {
891 goto fail;
892 }
893
894 sconfig->addr.family = AF_INET;
895 memcpy(&sconfig->addr.addr.addr4, &servers[i],
896 sizeof(sconfig->addr.addr.addr4));
897
898 if (ares__llist_insert_last(s, sconfig) == NULL) {
899 goto fail;
900 }
901 }
902
903 *llist = s;
904 return ARES_SUCCESS;
905
906 fail:
907 ares__llist_destroy(s);
908 return ARES_ENOMEM;
909 }
910
ares_get_servers(ares_channel_t * channel,struct ares_addr_node ** servers)911 int ares_get_servers(ares_channel_t *channel, struct ares_addr_node **servers)
912 {
913 struct ares_addr_node *srvr_head = NULL;
914 struct ares_addr_node *srvr_last = NULL;
915 struct ares_addr_node *srvr_curr;
916 ares_status_t status = ARES_SUCCESS;
917 ares__slist_node_t *node;
918
919 if (channel == NULL) {
920 return ARES_ENODATA;
921 }
922
923 ares__channel_lock(channel);
924
925 for (node = ares__slist_node_first(channel->servers); node != NULL;
926 node = ares__slist_node_next(node)) {
927 const struct server_state *server = ares__slist_node_val(node);
928
929 /* Allocate storage for this server node appending it to the list */
930 srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_NODE);
931 if (!srvr_curr) {
932 status = ARES_ENOMEM;
933 break;
934 }
935 if (srvr_last) {
936 srvr_last->next = srvr_curr;
937 } else {
938 srvr_head = srvr_curr;
939 }
940 srvr_last = srvr_curr;
941
942 /* Fill this server node data */
943 srvr_curr->family = server->addr.family;
944 if (srvr_curr->family == AF_INET) {
945 memcpy(&srvr_curr->addr.addr4, &server->addr.addr.addr4,
946 sizeof(srvr_curr->addr.addr4));
947 } else {
948 memcpy(&srvr_curr->addr.addr6, &server->addr.addr.addr6,
949 sizeof(srvr_curr->addr.addr6));
950 }
951 }
952
953 if (status != ARES_SUCCESS) {
954 ares_free_data(srvr_head);
955 srvr_head = NULL;
956 }
957
958 *servers = srvr_head;
959
960 ares__channel_unlock(channel);
961
962 return (int)status;
963 }
964
ares_get_servers_ports(ares_channel_t * channel,struct ares_addr_port_node ** servers)965 int ares_get_servers_ports(ares_channel_t *channel,
966 struct ares_addr_port_node **servers)
967 {
968 struct ares_addr_port_node *srvr_head = NULL;
969 struct ares_addr_port_node *srvr_last = NULL;
970 struct ares_addr_port_node *srvr_curr;
971 ares_status_t status = ARES_SUCCESS;
972 ares__slist_node_t *node;
973
974 if (channel == NULL) {
975 return ARES_ENODATA;
976 }
977
978 ares__channel_lock(channel);
979
980 for (node = ares__slist_node_first(channel->servers); node != NULL;
981 node = ares__slist_node_next(node)) {
982 const struct server_state *server = ares__slist_node_val(node);
983
984 /* Allocate storage for this server node appending it to the list */
985 srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_PORT_NODE);
986 if (!srvr_curr) {
987 status = ARES_ENOMEM;
988 break;
989 }
990 if (srvr_last) {
991 srvr_last->next = srvr_curr;
992 } else {
993 srvr_head = srvr_curr;
994 }
995 srvr_last = srvr_curr;
996
997 /* Fill this server node data */
998 srvr_curr->family = server->addr.family;
999 srvr_curr->udp_port = server->udp_port;
1000 srvr_curr->tcp_port = server->tcp_port;
1001
1002 if (srvr_curr->family == AF_INET) {
1003 memcpy(&srvr_curr->addr.addr4, &server->addr.addr.addr4,
1004 sizeof(srvr_curr->addr.addr4));
1005 } else {
1006 memcpy(&srvr_curr->addr.addr6, &server->addr.addr.addr6,
1007 sizeof(srvr_curr->addr.addr6));
1008 }
1009 }
1010
1011 if (status != ARES_SUCCESS) {
1012 ares_free_data(srvr_head);
1013 srvr_head = NULL;
1014 }
1015
1016 *servers = srvr_head;
1017
1018 ares__channel_unlock(channel);
1019 return (int)status;
1020 }
1021
ares_set_servers(ares_channel_t * channel,const struct ares_addr_node * servers)1022 int ares_set_servers(ares_channel_t *channel,
1023 const struct ares_addr_node *servers)
1024 {
1025 ares__llist_t *slist;
1026 ares_status_t status;
1027
1028 if (channel == NULL) {
1029 return ARES_ENODATA;
1030 }
1031
1032 status = ares_addr_node_to_server_config_llist(servers, &slist);
1033 if (status != ARES_SUCCESS) {
1034 return (int)status;
1035 }
1036
1037 /* NOTE: lock is in ares__servers_update() */
1038 status = ares__servers_update(channel, slist, ARES_TRUE);
1039
1040 ares__llist_destroy(slist);
1041
1042 return (int)status;
1043 }
1044
ares_set_servers_ports(ares_channel_t * channel,const struct ares_addr_port_node * servers)1045 int ares_set_servers_ports(ares_channel_t *channel,
1046 const struct ares_addr_port_node *servers)
1047 {
1048 ares__llist_t *slist;
1049 ares_status_t status;
1050
1051 if (channel == NULL) {
1052 return ARES_ENODATA;
1053 }
1054
1055 status = ares_addr_port_node_to_server_config_llist(servers, &slist);
1056 if (status != ARES_SUCCESS) {
1057 return (int)status;
1058 }
1059
1060 /* NOTE: lock is in ares__servers_update() */
1061 status = ares__servers_update(channel, slist, ARES_TRUE);
1062
1063 ares__llist_destroy(slist);
1064
1065 return (int)status;
1066 }
1067
1068 /* Incoming string format: host[:port][,host[:port]]... */
1069 /* IPv6 addresses with ports require square brackets [fe80::1]:53 */
set_servers_csv(ares_channel_t * channel,const char * _csv)1070 static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv)
1071 {
1072 ares_status_t status;
1073 ares__llist_t *slist = NULL;
1074
1075 if (channel == NULL) {
1076 return ARES_ENODATA;
1077 }
1078
1079 /* NOTE: lock is in ares__servers_update() */
1080
1081 if (ares_strlen(_csv) == 0) {
1082 /* blank all servers */
1083 return (ares_status_t)ares_set_servers_ports(channel, NULL);
1084 }
1085
1086 status = ares__sconfig_append_fromstr(&slist, _csv, ARES_FALSE);
1087 if (status != ARES_SUCCESS) {
1088 ares__llist_destroy(slist);
1089 return status;
1090 }
1091
1092 /* NOTE: lock is in ares__servers_update() */
1093 status = ares__servers_update(channel, slist, ARES_TRUE);
1094
1095 ares__llist_destroy(slist);
1096
1097 return status;
1098 }
1099
1100 /* We'll go ahead and honor ports anyhow */
ares_set_servers_csv(ares_channel_t * channel,const char * _csv)1101 int ares_set_servers_csv(ares_channel_t *channel, const char *_csv)
1102 {
1103 /* NOTE: lock is in ares__servers_update() */
1104 return (int)set_servers_csv(channel, _csv);
1105 }
1106
ares_set_servers_ports_csv(ares_channel_t * channel,const char * _csv)1107 int ares_set_servers_ports_csv(ares_channel_t *channel, const char *_csv)
1108 {
1109 /* NOTE: lock is in ares__servers_update() */
1110 return (int)set_servers_csv(channel, _csv);
1111 }
1112
ares_get_servers_csv(ares_channel_t * channel)1113 char *ares_get_servers_csv(ares_channel_t *channel)
1114 {
1115 ares__buf_t *buf = NULL;
1116 char *out = NULL;
1117 ares__slist_node_t *node;
1118
1119 ares__channel_lock(channel);
1120
1121 buf = ares__buf_create();
1122 if (buf == NULL) {
1123 goto done;
1124 }
1125
1126 for (node = ares__slist_node_first(channel->servers); node != NULL;
1127 node = ares__slist_node_next(node)) {
1128 ares_status_t status;
1129 const struct server_state *server = ares__slist_node_val(node);
1130 char addr[64];
1131
1132 if (ares__buf_len(buf)) {
1133 status = ares__buf_append_byte(buf, ',');
1134 if (status != ARES_SUCCESS) {
1135 goto done;
1136 }
1137 }
1138
1139 /* ipv4addr or [ipv6addr] */
1140 if (server->addr.family == AF_INET6) {
1141 status = ares__buf_append_byte(buf, '[');
1142 if (status != ARES_SUCCESS) {
1143 goto done;
1144 }
1145 }
1146
1147 ares_inet_ntop(server->addr.family, &server->addr.addr, addr, sizeof(addr));
1148
1149 status = ares__buf_append_str(buf, addr);
1150 if (status != ARES_SUCCESS) {
1151 goto done;
1152 }
1153
1154 if (server->addr.family == AF_INET6) {
1155 status = ares__buf_append_byte(buf, ']');
1156 if (status != ARES_SUCCESS) {
1157 goto done;
1158 }
1159 }
1160
1161 /* :port */
1162 status = ares__buf_append_byte(buf, ':');
1163 if (status != ARES_SUCCESS) {
1164 goto done;
1165 }
1166
1167 status = ares__buf_append_num_dec(buf, server->udp_port, 0);
1168 if (status != ARES_SUCCESS) {
1169 goto done;
1170 }
1171
1172 /* %iface */
1173 if (ares_strlen(server->ll_iface)) {
1174 status = ares__buf_append_byte(buf, '%');
1175 if (status != ARES_SUCCESS) {
1176 goto done;
1177 }
1178
1179 status = ares__buf_append_str(buf, server->ll_iface);
1180 if (status != ARES_SUCCESS) {
1181 goto done;
1182 }
1183 }
1184 }
1185
1186 out = ares__buf_finish_str(buf, NULL);
1187 buf = NULL;
1188
1189 done:
1190 ares__channel_unlock(channel);
1191 ares__buf_destroy(buf);
1192 return out;
1193 }
1194