• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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