1
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3 * Copyright (C) 2007-2013 by Daniel Stenberg
4 *
5 * Permission to use, copy, modify, and distribute this
6 * software and its documentation for any purpose and without
7 * fee is hereby granted, provided that the above copyright
8 * notice appear in all copies and that both that copyright
9 * notice and this permission notice appear in supporting
10 * documentation, and that the name of M.I.T. not be used in
11 * advertising or publicity pertaining to distribution of the
12 * software without specific, written prior permission.
13 * M.I.T. makes no representations about the suitability of
14 * this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
16 */
17
18 #include "ares_setup.h"
19
20 #ifdef HAVE_SYS_PARAM_H
21 #include <sys/param.h>
22 #endif
23
24 #ifdef HAVE_NETINET_IN_H
25 #include <netinet/in.h>
26 #endif
27
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
31
32 #ifdef HAVE_ARPA_INET_H
33 #include <arpa/inet.h>
34 #endif
35
36 #ifdef HAVE_ARPA_NAMESER_H
37 # include <arpa/nameser.h>
38 #else
39 # include "nameser.h"
40 #endif
41 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
42 # include <arpa/nameser_compat.h>
43 #endif
44
45 #if defined(ANDROID) || defined(__ANDROID__)
46 #include <sys/system_properties.h>
47 #include "ares_android.h"
48 /* From the Bionic sources */
49 #define DNS_PROP_NAME_PREFIX "net.dns"
50 #define MAX_DNS_PROPERTIES 8
51 #endif
52
53 #if defined(CARES_USE_LIBRESOLV)
54 #include <resolv.h>
55 #endif
56
57 #include "ares.h"
58 #include "ares_inet_net_pton.h"
59 #include "ares_library_init.h"
60 #include "ares_nowarn.h"
61 #include "ares_platform.h"
62 #include "ares_private.h"
63
64 #ifdef WATT32
65 #undef WIN32 /* Redefined in MingW/MSVC headers */
66 #endif
67
68 static int init_by_options(ares_channel channel,
69 const struct ares_options *options,
70 int optmask);
71 static int init_by_environment(ares_channel channel);
72 static int init_by_resolv_conf(ares_channel channel);
73 static int init_by_defaults(ares_channel channel);
74
75 #ifndef WATT32
76 static int config_nameserver(struct server_state **servers, int *nservers,
77 char *str);
78 #endif
79 static int set_search(ares_channel channel, const char *str);
80 static int set_options(ares_channel channel, const char *str);
81 static const char *try_option(const char *p, const char *q, const char *opt);
82 static int init_id_key(rc4_key* key,int key_data_len);
83
84 static int config_sortlist(struct apattern **sortlist, int *nsort,
85 const char *str);
86 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
87 struct apattern *pat);
88 static int ip_addr(const char *s, ares_ssize_t len, struct in_addr *addr);
89 static void natural_mask(struct apattern *pat);
90 #if !defined(WIN32) && !defined(WATT32) && \
91 !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
92 static int config_domain(ares_channel channel, char *str);
93 static int config_lookup(ares_channel channel, const char *str,
94 const char *bindch, const char *altbindch,
95 const char *filech);
96 static char *try_config(char *s, const char *opt, char scc);
97 #endif
98
99 #define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
100 x->nservers > -1 && \
101 x->ndomains > -1 && \
102 x->ndots > -1 && x->timeout > -1 && \
103 x->tries > -1)
104
ares_init(ares_channel * channelptr)105 int ares_init(ares_channel *channelptr)
106 {
107 return ares_init_options(channelptr, NULL, 0);
108 }
109
ares_init_options(ares_channel * channelptr,struct ares_options * options,int optmask)110 int ares_init_options(ares_channel *channelptr, struct ares_options *options,
111 int optmask)
112 {
113 ares_channel channel;
114 int i;
115 int status = ARES_SUCCESS;
116 struct timeval now;
117
118 #ifdef CURLDEBUG
119 const char *env = getenv("CARES_MEMDEBUG");
120
121 if (env)
122 curl_memdebug(env);
123 env = getenv("CARES_MEMLIMIT");
124 if (env) {
125 char *endptr;
126 long num = strtol(env, &endptr, 10);
127 if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
128 curl_memlimit(num);
129 }
130 #endif
131
132 if (ares_library_initialized() != ARES_SUCCESS)
133 return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
134
135 channel = ares_malloc(sizeof(struct ares_channeldata));
136 if (!channel) {
137 *channelptr = NULL;
138 return ARES_ENOMEM;
139 }
140
141 now = ares__tvnow();
142
143 /* Set everything to distinguished values so we know they haven't
144 * been set yet.
145 */
146 channel->flags = -1;
147 channel->timeout = -1;
148 channel->tries = -1;
149 channel->ndots = -1;
150 channel->rotate = -1;
151 channel->udp_port = -1;
152 channel->tcp_port = -1;
153 channel->ednspsz = -1;
154 channel->socket_send_buffer_size = -1;
155 channel->socket_receive_buffer_size = -1;
156 channel->nservers = -1;
157 channel->ndomains = -1;
158 channel->nsort = -1;
159 channel->tcp_connection_generation = 0;
160 channel->lookups = NULL;
161 channel->domains = NULL;
162 channel->sortlist = NULL;
163 channel->servers = NULL;
164 channel->sock_state_cb = NULL;
165 channel->sock_state_cb_data = NULL;
166 channel->sock_create_cb = NULL;
167 channel->sock_create_cb_data = NULL;
168 channel->sock_config_cb = NULL;
169 channel->sock_config_cb_data = NULL;
170 channel->sock_funcs = NULL;
171 channel->sock_func_cb_data = NULL;
172 channel->resolvconf_path = NULL;
173
174 channel->last_server = 0;
175 channel->last_timeout_processed = (time_t)now.tv_sec;
176
177 memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name));
178 channel->local_ip4 = 0;
179 memset(&channel->local_ip6, 0, sizeof(channel->local_ip6));
180
181 /* Initialize our lists of queries */
182 ares__init_list_head(&(channel->all_queries));
183 for (i = 0; i < ARES_QID_TABLE_SIZE; i++)
184 {
185 ares__init_list_head(&(channel->queries_by_qid[i]));
186 }
187 for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++)
188 {
189 ares__init_list_head(&(channel->queries_by_timeout[i]));
190 }
191
192 /* Initialize configuration by each of the four sources, from highest
193 * precedence to lowest.
194 */
195
196 status = init_by_options(channel, options, optmask);
197 if (status != ARES_SUCCESS) {
198 DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
199 ares_strerror(status)));
200 /* If we fail to apply user-specified options, fail the whole init process */
201 goto done;
202 }
203 status = init_by_environment(channel);
204 if (status != ARES_SUCCESS)
205 DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
206 ares_strerror(status)));
207 if (status == ARES_SUCCESS) {
208 status = init_by_resolv_conf(channel);
209 if (status != ARES_SUCCESS)
210 DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n",
211 ares_strerror(status)));
212 }
213
214 /*
215 * No matter what failed or succeeded, seed defaults to provide
216 * useful behavior for things that we missed.
217 */
218 status = init_by_defaults(channel);
219 if (status != ARES_SUCCESS)
220 DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
221 ares_strerror(status)));
222
223 /* Generate random key */
224
225 if (status == ARES_SUCCESS) {
226 status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
227 if (status == ARES_SUCCESS)
228 channel->next_id = ares__generate_new_id(&channel->id_key);
229 else
230 DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
231 ares_strerror(status)));
232 }
233
234 done:
235 if (status != ARES_SUCCESS)
236 {
237 /* Something failed; clean up memory we may have allocated. */
238 if (channel->servers)
239 ares_free(channel->servers);
240 if (channel->ndomains != -1)
241 ares_strsplit_free(channel->domains, channel->ndomains);
242 if (channel->sortlist)
243 ares_free(channel->sortlist);
244 if(channel->lookups)
245 ares_free(channel->lookups);
246 if(channel->resolvconf_path)
247 ares_free(channel->resolvconf_path);
248 ares_free(channel);
249 return status;
250 }
251
252 /* Trim to one server if ARES_FLAG_PRIMARY is set. */
253 if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
254 channel->nservers = 1;
255
256 ares__init_servers_state(channel);
257
258 *channelptr = channel;
259 return ARES_SUCCESS;
260 }
261
262 /* ares_dup() duplicates a channel handle with all its options and returns a
263 new channel handle */
ares_dup(ares_channel * dest,ares_channel src)264 int ares_dup(ares_channel *dest, ares_channel src)
265 {
266 struct ares_options opts;
267 struct ares_addr_port_node *servers;
268 int non_v4_default_port = 0;
269 int i, rc;
270 int optmask;
271
272 *dest = NULL; /* in case of failure return NULL explicitly */
273
274 /* First get the options supported by the old ares_save_options() function,
275 which is most of them */
276 rc = ares_save_options(src, &opts, &optmask);
277 if(rc)
278 {
279 ares_destroy_options(&opts);
280 return rc;
281 }
282
283 /* Then create the new channel with those options */
284 rc = ares_init_options(dest, &opts, optmask);
285
286 /* destroy the options copy to not leak any memory */
287 ares_destroy_options(&opts);
288
289 if(rc)
290 return rc;
291
292 /* Now clone the options that ares_save_options() doesn't support. */
293 (*dest)->sock_create_cb = src->sock_create_cb;
294 (*dest)->sock_create_cb_data = src->sock_create_cb_data;
295 (*dest)->sock_config_cb = src->sock_config_cb;
296 (*dest)->sock_config_cb_data = src->sock_config_cb_data;
297 (*dest)->sock_funcs = src->sock_funcs;
298 (*dest)->sock_func_cb_data = src->sock_func_cb_data;
299
300 strncpy((*dest)->local_dev_name, src->local_dev_name,
301 sizeof((*dest)->local_dev_name));
302 (*dest)->local_ip4 = src->local_ip4;
303 memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
304
305 /* Full name server cloning required if there is a non-IPv4, or non-default port, nameserver */
306 for (i = 0; i < src->nservers; i++)
307 {
308 if ((src->servers[i].addr.family != AF_INET) ||
309 (src->servers[i].addr.udp_port != 0) ||
310 (src->servers[i].addr.tcp_port != 0)) {
311 non_v4_default_port++;
312 break;
313 }
314 }
315 if (non_v4_default_port) {
316 rc = ares_get_servers_ports(src, &servers);
317 if (rc != ARES_SUCCESS) {
318 ares_destroy(*dest);
319 *dest = NULL;
320 return rc;
321 }
322 rc = ares_set_servers_ports(*dest, servers);
323 ares_free_data(servers);
324 if (rc != ARES_SUCCESS) {
325 ares_destroy(*dest);
326 *dest = NULL;
327 return rc;
328 }
329 }
330
331 return ARES_SUCCESS; /* everything went fine */
332 }
333
334 /* Save options from initialized channel */
ares_save_options(ares_channel channel,struct ares_options * options,int * optmask)335 int ares_save_options(ares_channel channel, struct ares_options *options,
336 int *optmask)
337 {
338 int i, j;
339 int ipv4_nservers = 0;
340
341 /* Zero everything out */
342 memset(options, 0, sizeof(struct ares_options));
343
344 if (!ARES_CONFIG_CHECK(channel))
345 return ARES_ENODATA;
346
347 /* Traditionally the optmask wasn't saved in the channel struct so it was
348 recreated here. ROTATE is the first option that has no struct field of
349 its own in the public config struct */
350 (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS|
351 ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
352 ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
353 ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS);
354 (*optmask) |= (channel->rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE);
355
356 if (channel->resolvconf_path)
357 (*optmask) |= ARES_OPT_RESOLVCONF;
358
359 /* Copy easy stuff */
360 options->flags = channel->flags;
361
362 /* We return full millisecond resolution but that's only because we don't
363 set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */
364 options->timeout = channel->timeout;
365 options->tries = channel->tries;
366 options->ndots = channel->ndots;
367 options->udp_port = ntohs(aresx_sitous(channel->udp_port));
368 options->tcp_port = ntohs(aresx_sitous(channel->tcp_port));
369 options->sock_state_cb = channel->sock_state_cb;
370 options->sock_state_cb_data = channel->sock_state_cb_data;
371
372 /* Copy IPv4 servers that use the default port */
373 if (channel->nservers) {
374 for (i = 0; i < channel->nservers; i++)
375 {
376 if ((channel->servers[i].addr.family == AF_INET) &&
377 (channel->servers[i].addr.udp_port == 0) &&
378 (channel->servers[i].addr.tcp_port == 0))
379 ipv4_nservers++;
380 }
381 if (ipv4_nservers) {
382 options->servers = ares_malloc(ipv4_nservers * sizeof(struct in_addr));
383 if (!options->servers)
384 return ARES_ENOMEM;
385 for (i = j = 0; i < channel->nservers; i++)
386 {
387 if ((channel->servers[i].addr.family == AF_INET) &&
388 (channel->servers[i].addr.udp_port == 0) &&
389 (channel->servers[i].addr.tcp_port == 0))
390 memcpy(&options->servers[j++],
391 &channel->servers[i].addr.addrV4,
392 sizeof(channel->servers[i].addr.addrV4));
393 }
394 }
395 }
396 options->nservers = ipv4_nservers;
397
398 /* copy domains */
399 if (channel->ndomains) {
400 options->domains = ares_malloc(channel->ndomains * sizeof(char *));
401 if (!options->domains)
402 return ARES_ENOMEM;
403
404 for (i = 0; i < channel->ndomains; i++)
405 {
406 options->ndomains = i;
407 options->domains[i] = ares_strdup(channel->domains[i]);
408 if (!options->domains[i])
409 return ARES_ENOMEM;
410 }
411 }
412 options->ndomains = channel->ndomains;
413
414 /* copy lookups */
415 if (channel->lookups) {
416 options->lookups = ares_strdup(channel->lookups);
417 if (!options->lookups && channel->lookups)
418 return ARES_ENOMEM;
419 }
420
421 /* copy sortlist */
422 if (channel->nsort) {
423 options->sortlist = ares_malloc(channel->nsort * sizeof(struct apattern));
424 if (!options->sortlist)
425 return ARES_ENOMEM;
426 for (i = 0; i < channel->nsort; i++)
427 options->sortlist[i] = channel->sortlist[i];
428 }
429 options->nsort = channel->nsort;
430
431 /* copy path for resolv.conf file */
432 if (channel->resolvconf_path) {
433 options->resolvconf_path = ares_strdup(channel->resolvconf_path);
434 if (!options->resolvconf_path)
435 return ARES_ENOMEM;
436 }
437
438 return ARES_SUCCESS;
439 }
440
init_by_options(ares_channel channel,const struct ares_options * options,int optmask)441 static int init_by_options(ares_channel channel,
442 const struct ares_options *options,
443 int optmask)
444 {
445 int i;
446
447 /* Easy stuff. */
448 if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
449 channel->flags = options->flags;
450 if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1)
451 channel->timeout = options->timeout;
452 else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
453 channel->timeout = options->timeout * 1000;
454 if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
455 channel->tries = options->tries;
456 if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
457 channel->ndots = options->ndots;
458 if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1)
459 channel->rotate = 1;
460 if ((optmask & ARES_OPT_NOROTATE) && channel->rotate == -1)
461 channel->rotate = 0;
462 if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
463 channel->udp_port = htons(options->udp_port);
464 if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
465 channel->tcp_port = htons(options->tcp_port);
466 if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL)
467 {
468 channel->sock_state_cb = options->sock_state_cb;
469 channel->sock_state_cb_data = options->sock_state_cb_data;
470 }
471 if ((optmask & ARES_OPT_SOCK_SNDBUF)
472 && channel->socket_send_buffer_size == -1)
473 channel->socket_send_buffer_size = options->socket_send_buffer_size;
474 if ((optmask & ARES_OPT_SOCK_RCVBUF)
475 && channel->socket_receive_buffer_size == -1)
476 channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
477
478 if ((optmask & ARES_OPT_EDNSPSZ) && channel->ednspsz == -1)
479 channel->ednspsz = options->ednspsz;
480
481 /* Copy the IPv4 servers, if given. */
482 if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
483 {
484 /* Avoid zero size allocations at any cost */
485 if (options->nservers > 0)
486 {
487 channel->servers =
488 ares_malloc(options->nservers * sizeof(struct server_state));
489 if (!channel->servers)
490 return ARES_ENOMEM;
491 for (i = 0; i < options->nservers; i++)
492 {
493 channel->servers[i].addr.family = AF_INET;
494 channel->servers[i].addr.udp_port = 0;
495 channel->servers[i].addr.tcp_port = 0;
496 memcpy(&channel->servers[i].addr.addrV4,
497 &options->servers[i],
498 sizeof(channel->servers[i].addr.addrV4));
499 }
500 }
501 channel->nservers = options->nservers;
502 }
503
504 /* Copy the domains, if given. Keep channel->ndomains consistent so
505 * we can clean up in case of error.
506 */
507 if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
508 {
509 /* Avoid zero size allocations at any cost */
510 if (options->ndomains > 0)
511 {
512 channel->domains = ares_malloc(options->ndomains * sizeof(char *));
513 if (!channel->domains)
514 return ARES_ENOMEM;
515 for (i = 0; i < options->ndomains; i++)
516 {
517 channel->ndomains = i;
518 channel->domains[i] = ares_strdup(options->domains[i]);
519 if (!channel->domains[i])
520 return ARES_ENOMEM;
521 }
522 }
523 channel->ndomains = options->ndomains;
524 }
525
526 /* Set lookups, if given. */
527 if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
528 {
529 channel->lookups = ares_strdup(options->lookups);
530 if (!channel->lookups)
531 return ARES_ENOMEM;
532 }
533
534 /* copy sortlist */
535 if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1)) {
536 if (options->nsort > 0) {
537 channel->sortlist = ares_malloc(options->nsort * sizeof(struct apattern));
538 if (!channel->sortlist)
539 return ARES_ENOMEM;
540 for (i = 0; i < options->nsort; i++)
541 channel->sortlist[i] = options->sortlist[i];
542 }
543 channel->nsort = options->nsort;
544 }
545
546 /* Set path for resolv.conf file, if given. */
547 if ((optmask & ARES_OPT_RESOLVCONF) && !channel->resolvconf_path)
548 {
549 channel->resolvconf_path = ares_strdup(options->resolvconf_path);
550 if (!channel->resolvconf_path && options->resolvconf_path)
551 return ARES_ENOMEM;
552 }
553
554 channel->optmask = optmask;
555
556 return ARES_SUCCESS;
557 }
558
init_by_environment(ares_channel channel)559 static int init_by_environment(ares_channel channel)
560 {
561 const char *localdomain, *res_options;
562 int status;
563
564 localdomain = getenv("LOCALDOMAIN");
565 if (localdomain && channel->ndomains == -1)
566 {
567 status = set_search(channel, localdomain);
568 if (status != ARES_SUCCESS)
569 return status;
570 }
571
572 res_options = getenv("RES_OPTIONS");
573 if (res_options)
574 {
575 status = set_options(channel, res_options);
576 if (status != ARES_SUCCESS)
577 return status; /* LCOV_EXCL_LINE: set_options() never fails */
578 }
579
580 return ARES_SUCCESS;
581 }
582
583 #ifdef WIN32
584 /*
585 * get_REG_SZ()
586 *
587 * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer
588 * to the name of the registry leaf key to be queried, fetch it's string
589 * value and return a pointer in *outptr to a newly allocated memory area
590 * holding it as a null-terminated string.
591 *
592 * Returns 0 and nullifies *outptr upon inability to return a string value.
593 *
594 * Returns 1 and sets *outptr when returning a dynamically allocated string.
595 *
596 * Supported on Windows NT 3.5 and newer.
597 */
get_REG_SZ(HKEY hKey,const char * leafKeyName,char ** outptr)598 static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
599 {
600 DWORD size = 0;
601 int res;
602
603 *outptr = NULL;
604
605 /* Find out size of string stored in registry */
606 res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, NULL, &size);
607 if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
608 return 0;
609
610 /* Allocate buffer of indicated size plus one given that string
611 might have been stored without null termination */
612 *outptr = ares_malloc(size+1);
613 if (!*outptr)
614 return 0;
615
616 /* Get the value for real */
617 res = RegQueryValueExA(hKey, leafKeyName, 0, NULL,
618 (unsigned char *)*outptr, &size);
619 if ((res != ERROR_SUCCESS) || (size == 1))
620 {
621 ares_free(*outptr);
622 *outptr = NULL;
623 return 0;
624 }
625
626 /* Null terminate buffer allways */
627 *(*outptr + size) = '\0';
628
629 return 1;
630 }
631
632 /*
633 * get_REG_SZ_9X()
634 *
635 * Functionally identical to get_REG_SZ()
636 *
637 * Supported on Windows 95, 98 and ME.
638 */
get_REG_SZ_9X(HKEY hKey,const char * leafKeyName,char ** outptr)639 static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
640 {
641 DWORD dataType = 0;
642 DWORD size = 0;
643 int res;
644
645 *outptr = NULL;
646
647 /* Find out size of string stored in registry */
648 res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, NULL, &size);
649 if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
650 return 0;
651
652 /* Allocate buffer of indicated size plus one given that string
653 might have been stored without null termination */
654 *outptr = ares_malloc(size+1);
655 if (!*outptr)
656 return 0;
657
658 /* Get the value for real */
659 res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType,
660 (unsigned char *)*outptr, &size);
661 if ((res != ERROR_SUCCESS) || (size == 1))
662 {
663 ares_free(*outptr);
664 *outptr = NULL;
665 return 0;
666 }
667
668 /* Null terminate buffer allways */
669 *(*outptr + size) = '\0';
670
671 return 1;
672 }
673
674 /*
675 * get_enum_REG_SZ()
676 *
677 * Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName'
678 * pointer to the name of the registry leaf key to be queried, parent key
679 * is enumerated searching in child keys for given leaf key name and its
680 * associated string value. When located, this returns a pointer in *outptr
681 * to a newly allocated memory area holding it as a null-terminated string.
682 *
683 * Returns 0 and nullifies *outptr upon inability to return a string value.
684 *
685 * Returns 1 and sets *outptr when returning a dynamically allocated string.
686 *
687 * Supported on Windows NT 3.5 and newer.
688 */
get_enum_REG_SZ(HKEY hKeyParent,const char * leafKeyName,char ** outptr)689 static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName,
690 char **outptr)
691 {
692 char enumKeyName[256];
693 DWORD enumKeyNameBuffSize;
694 DWORD enumKeyIdx = 0;
695 HKEY hKeyEnum;
696 int gotString;
697 int res;
698
699 *outptr = NULL;
700
701 for(;;)
702 {
703 enumKeyNameBuffSize = sizeof(enumKeyName);
704 res = RegEnumKeyExA(hKeyParent, enumKeyIdx++, enumKeyName,
705 &enumKeyNameBuffSize, 0, NULL, NULL, NULL);
706 if (res != ERROR_SUCCESS)
707 break;
708 res = RegOpenKeyExA(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE,
709 &hKeyEnum);
710 if (res != ERROR_SUCCESS)
711 continue;
712 gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr);
713 RegCloseKey(hKeyEnum);
714 if (gotString)
715 break;
716 }
717
718 if (!*outptr)
719 return 0;
720
721 return 1;
722 }
723
724 /*
725 * get_DNS_Registry_9X()
726 *
727 * Functionally identical to get_DNS_Registry()
728 *
729 * Implementation supports Windows 95, 98 and ME.
730 */
get_DNS_Registry_9X(char ** outptr)731 static int get_DNS_Registry_9X(char **outptr)
732 {
733 HKEY hKey_VxD_MStcp;
734 int gotString;
735 int res;
736
737 *outptr = NULL;
738
739 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ,
740 &hKey_VxD_MStcp);
741 if (res != ERROR_SUCCESS)
742 return 0;
743
744 gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr);
745 RegCloseKey(hKey_VxD_MStcp);
746
747 if (!gotString || !*outptr)
748 return 0;
749
750 return 1;
751 }
752
753 /*
754 * get_DNS_Registry_NT()
755 *
756 * Functionally identical to get_DNS_Registry()
757 *
758 * Refs: Microsoft Knowledge Base articles KB120642 and KB314053.
759 *
760 * Implementation supports Windows NT 3.5 and newer.
761 */
get_DNS_Registry_NT(char ** outptr)762 static int get_DNS_Registry_NT(char **outptr)
763 {
764 HKEY hKey_Interfaces = NULL;
765 HKEY hKey_Tcpip_Parameters;
766 int gotString;
767 int res;
768
769 *outptr = NULL;
770
771 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
772 &hKey_Tcpip_Parameters);
773 if (res != ERROR_SUCCESS)
774 return 0;
775
776 /*
777 ** Global DNS settings override adapter specific parameters when both
778 ** are set. Additionally static DNS settings override DHCP-configured
779 ** parameters when both are set.
780 */
781
782 /* Global DNS static parameters */
783 gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr);
784 if (gotString)
785 goto done;
786
787 /* Global DNS DHCP-configured parameters */
788 gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr);
789 if (gotString)
790 goto done;
791
792 /* Try adapter specific parameters */
793 res = RegOpenKeyExA(hKey_Tcpip_Parameters, "Interfaces", 0,
794 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
795 &hKey_Interfaces);
796 if (res != ERROR_SUCCESS)
797 {
798 hKey_Interfaces = NULL;
799 goto done;
800 }
801
802 /* Adapter specific DNS static parameters */
803 gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr);
804 if (gotString)
805 goto done;
806
807 /* Adapter specific DNS DHCP-configured parameters */
808 gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr);
809
810 done:
811 if (hKey_Interfaces)
812 RegCloseKey(hKey_Interfaces);
813
814 RegCloseKey(hKey_Tcpip_Parameters);
815
816 if (!gotString || !*outptr)
817 return 0;
818
819 return 1;
820 }
821
822 /*
823 * get_DNS_Registry()
824 *
825 * Locates DNS info in the registry. When located, this returns a pointer
826 * in *outptr to a newly allocated memory area holding a null-terminated
827 * string with a space or comma seperated list of DNS IP addresses.
828 *
829 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
830 *
831 * Returns 1 and sets *outptr when returning a dynamically allocated string.
832 */
get_DNS_Registry(char ** outptr)833 static int get_DNS_Registry(char **outptr)
834 {
835 win_platform platform;
836 int gotString = 0;
837
838 *outptr = NULL;
839
840 platform = ares__getplatform();
841
842 if (platform == WIN_NT)
843 gotString = get_DNS_Registry_NT(outptr);
844 else if (platform == WIN_9X)
845 gotString = get_DNS_Registry_9X(outptr);
846
847 if (!gotString)
848 return 0;
849
850 return 1;
851 }
852
commanjoin(char ** dst,const char * const src,const size_t len)853 static void commanjoin(char** dst, const char* const src, const size_t len)
854 {
855 char *newbuf;
856 size_t newsize;
857
858 /* 1 for terminating 0 and 2 for , and terminating 0 */
859 newsize = len + (*dst ? (strlen(*dst) + 2) : 1);
860 newbuf = ares_realloc(*dst, newsize);
861 if (!newbuf)
862 return;
863 if (*dst == NULL)
864 *newbuf = '\0';
865 *dst = newbuf;
866 if (strlen(*dst) != 0)
867 strcat(*dst, ",");
868 strncat(*dst, src, len);
869 }
870
871 /*
872 * commajoin()
873 *
874 * RTF code.
875 */
commajoin(char ** dst,const char * src)876 static void commajoin(char **dst, const char *src)
877 {
878 commanjoin(dst, src, strlen(src));
879 }
880
881 /*
882 * get_DNS_NetworkParams()
883 *
884 * Locates DNS info using GetNetworkParams() function from the Internet
885 * Protocol Helper (IP Helper) API. When located, this returns a pointer
886 * in *outptr to a newly allocated memory area holding a null-terminated
887 * string with a space or comma seperated list of DNS IP addresses.
888 *
889 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
890 *
891 * Returns 1 and sets *outptr when returning a dynamically allocated string.
892 *
893 * Implementation supports Windows 98 and newer.
894 *
895 * Note: Ancient PSDK required in order to build a W98 target.
896 */
get_DNS_NetworkParams(char ** outptr)897 static int get_DNS_NetworkParams(char **outptr)
898 {
899 FIXED_INFO *fi, *newfi;
900 struct ares_addr namesrvr;
901 char *txtaddr;
902 IP_ADDR_STRING *ipAddr;
903 int res;
904 DWORD size = sizeof (*fi);
905
906 *outptr = NULL;
907
908 /* Verify run-time availability of GetNetworkParams() */
909 if (ares_fpGetNetworkParams == ZERO_NULL)
910 return 0;
911
912 fi = ares_malloc(size);
913 if (!fi)
914 return 0;
915
916 res = (*ares_fpGetNetworkParams) (fi, &size);
917 if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
918 goto done;
919
920 newfi = ares_realloc(fi, size);
921 if (!newfi)
922 goto done;
923
924 fi = newfi;
925 res = (*ares_fpGetNetworkParams) (fi, &size);
926 if (res != ERROR_SUCCESS)
927 goto done;
928
929 for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next)
930 {
931 txtaddr = &ipAddr->IpAddress.String[0];
932
933 /* Validate converting textual address to binary format. */
934 if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1)
935 {
936 if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) ||
937 (namesrvr.addrV4.S_un.S_addr == INADDR_NONE))
938 continue;
939 }
940 else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1)
941 {
942 if (memcmp(&namesrvr.addrV6, &ares_in6addr_any,
943 sizeof(namesrvr.addrV6)) == 0)
944 continue;
945 }
946 else
947 continue;
948
949 commajoin(outptr, txtaddr);
950
951 if (!*outptr)
952 break;
953 }
954
955 done:
956 if (fi)
957 ares_free(fi);
958
959 if (!*outptr)
960 return 0;
961
962 return 1;
963 }
964
ares_IsWindowsVistaOrGreater(void)965 static BOOL ares_IsWindowsVistaOrGreater(void)
966 {
967 OSVERSIONINFO vinfo;
968 memset(&vinfo, 0, sizeof(vinfo));
969 vinfo.dwOSVersionInfoSize = sizeof(vinfo);
970 #ifdef _MSC_VER
971 #pragma warning(push)
972 #pragma warning(disable:4996) /* warning C4996: 'GetVersionExW': was declared deprecated */
973 #endif
974 if (!GetVersionEx(&vinfo) || vinfo.dwMajorVersion < 6)
975 return FALSE;
976 return TRUE;
977 #ifdef _MSC_VER
978 #pragma warning(pop)
979 #endif
980 }
981
982 /* A structure to hold the string form of IPv4 and IPv6 addresses so we can
983 * sort them by a metric.
984 */
985 typedef struct
986 {
987 /* The metric we sort them by. */
988 ULONG metric;
989
990 /* Original index of the item, used as a secondary sort parameter to make
991 * qsort() stable if the metrics are equal */
992 size_t orig_idx;
993
994 /* Room enough for the string form of any IPv4 or IPv6 address that
995 * ares_inet_ntop() will create. Based on the existing c-ares practice.
996 */
997 char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
998 } Address;
999
1000 /* Sort Address values \a left and \a right by metric, returning the usual
1001 * indicators for qsort().
1002 */
compareAddresses(const void * arg1,const void * arg2)1003 static int compareAddresses(const void *arg1,
1004 const void *arg2)
1005 {
1006 const Address * const left = arg1;
1007 const Address * const right = arg2;
1008 /* Lower metric the more preferred */
1009 if(left->metric < right->metric) return -1;
1010 if(left->metric > right->metric) return 1;
1011 /* If metrics are equal, lower original index more preferred */
1012 if(left->orig_idx < right->orig_idx) return -1;
1013 if(left->orig_idx > right->orig_idx) return 1;
1014 return 0;
1015 }
1016
1017 /* There can be multiple routes to "the Internet". And there can be different
1018 * DNS servers associated with each of the interfaces that offer those routes.
1019 * We have to assume that any DNS server can serve any request. But, some DNS
1020 * servers may only respond if requested over their associated interface. But
1021 * we also want to use "the preferred route to the Internet" whenever possible
1022 * (and not use DNS servers on a non-preferred route even by forcing request
1023 * to go out on the associated non-preferred interface). i.e. We want to use
1024 * the DNS servers associated with the same interface that we would use to
1025 * make a general request to anything else.
1026 *
1027 * But, Windows won't sort the DNS servers by the metrics associated with the
1028 * routes and interfaces _even_ though it obviously sends IP packets based on
1029 * those same routes and metrics. So, we must do it ourselves.
1030 *
1031 * So, we sort the DNS servers by the same metric values used to determine how
1032 * an outgoing IP packet will go, thus effectively using the DNS servers
1033 * associated with the interface that the DNS requests themselves will
1034 * travel. This gives us optimal routing and avoids issues where DNS servers
1035 * won't respond to requests that don't arrive via some specific subnetwork
1036 * (and thus some specific interface).
1037 *
1038 * This function computes the metric we use to sort. On the interface
1039 * identified by \a luid, it determines the best route to \a dest and combines
1040 * that route's metric with \a interfaceMetric to compute a metric for the
1041 * destination address on that interface. This metric can be used as a weight
1042 * to sort the DNS server addresses associated with each interface (lower is
1043 * better).
1044 *
1045 * Note that by restricting the route search to the specific interface with
1046 * which the DNS servers are associated, this function asks the question "What
1047 * is the metric for sending IP packets to this DNS server?" which allows us
1048 * to sort the DNS servers correctly.
1049 */
getBestRouteMetric(IF_LUID * const luid,const SOCKADDR_INET * const dest,const ULONG interfaceMetric)1050 static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
1051 const SOCKADDR_INET * const dest,
1052 const ULONG interfaceMetric)
1053 {
1054 /* On this interface, get the best route to that destination. */
1055 MIB_IPFORWARD_ROW2 row;
1056 SOCKADDR_INET ignored;
1057 if(!ares_fpGetBestRoute2 ||
1058 ares_fpGetBestRoute2(/* The interface to use. The index is ignored since we are
1059 * passing a LUID.
1060 */
1061 luid, 0,
1062 /* No specific source address. */
1063 NULL,
1064 /* Our destination address. */
1065 dest,
1066 /* No options. */
1067 0,
1068 /* The route row. */
1069 &row,
1070 /* The best source address, which we don't need. */
1071 &ignored) != NO_ERROR
1072 /* If the metric is "unused" (-1) or too large for us to add the two
1073 * metrics, use the worst possible, thus sorting this last.
1074 */
1075 || row.Metric == (ULONG)-1
1076 || row.Metric > ((ULONG)-1) - interfaceMetric) {
1077 /* Return the worst possible metric. */
1078 return (ULONG)-1;
1079 }
1080
1081 /* Return the metric value from that row, plus the interface metric.
1082 *
1083 * See
1084 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa814494(v=vs.85).aspx
1085 * which describes the combination as a "sum".
1086 */
1087 return row.Metric + interfaceMetric;
1088 }
1089
1090 /*
1091 * get_DNS_AdaptersAddresses()
1092 *
1093 * Locates DNS info using GetAdaptersAddresses() function from the Internet
1094 * Protocol Helper (IP Helper) API. When located, this returns a pointer
1095 * in *outptr to a newly allocated memory area holding a null-terminated
1096 * string with a space or comma seperated list of DNS IP addresses.
1097 *
1098 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
1099 *
1100 * Returns 1 and sets *outptr when returning a dynamically allocated string.
1101 *
1102 * Implementation supports Windows XP and newer.
1103 */
1104 #define IPAA_INITIAL_BUF_SZ 15 * 1024
1105 #define IPAA_MAX_TRIES 3
get_DNS_AdaptersAddresses(char ** outptr)1106 static int get_DNS_AdaptersAddresses(char **outptr)
1107 {
1108 IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
1109 IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry;
1110 ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ;
1111 ULONG Bufsz = IPAA_INITIAL_BUF_SZ;
1112 ULONG AddrFlags = 0;
1113 int trying = IPAA_MAX_TRIES;
1114 int res;
1115
1116 /* The capacity of addresses, in elements. */
1117 size_t addressesSize;
1118 /* The number of elements in addresses. */
1119 size_t addressesIndex = 0;
1120 /* The addresses we will sort. */
1121 Address *addresses;
1122
1123 union {
1124 struct sockaddr *sa;
1125 struct sockaddr_in *sa4;
1126 struct sockaddr_in6 *sa6;
1127 } namesrvr;
1128
1129 *outptr = NULL;
1130
1131 /* Verify run-time availability of GetAdaptersAddresses() */
1132 if (ares_fpGetAdaptersAddresses == ZERO_NULL)
1133 return 0;
1134
1135 ipaa = ares_malloc(Bufsz);
1136 if (!ipaa)
1137 return 0;
1138
1139 /* Start with enough room for a few DNS server addresses and we'll grow it
1140 * as we encounter more.
1141 */
1142 addressesSize = 4;
1143 addresses = (Address*)ares_malloc(sizeof(Address) * addressesSize);
1144 if(addresses == NULL) {
1145 /* We need room for at least some addresses to function. */
1146 ares_free(ipaa);
1147 return 0;
1148 }
1149
1150 /* Usually this call suceeds with initial buffer size */
1151 res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
1152 ipaa, &ReqBufsz);
1153 if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
1154 goto done;
1155
1156 while ((res == ERROR_BUFFER_OVERFLOW) && (--trying))
1157 {
1158 if (Bufsz < ReqBufsz)
1159 {
1160 newipaa = ares_realloc(ipaa, ReqBufsz);
1161 if (!newipaa)
1162 goto done;
1163 Bufsz = ReqBufsz;
1164 ipaa = newipaa;
1165 }
1166 res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
1167 ipaa, &ReqBufsz);
1168 if (res == ERROR_SUCCESS)
1169 break;
1170 }
1171 if (res != ERROR_SUCCESS)
1172 goto done;
1173
1174 for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next)
1175 {
1176 if(ipaaEntry->OperStatus != IfOperStatusUp)
1177 continue;
1178
1179 /* For each interface, find any associated DNS servers as IPv4 or IPv6
1180 * addresses. For each found address, find the best route to that DNS
1181 * server address _on_ _that_ _interface_ (at this moment in time) and
1182 * compute the resulting total metric, just as Windows routing will do.
1183 * Then, sort all the addresses found by the metric.
1184 */
1185 for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress;
1186 ipaDNSAddr;
1187 ipaDNSAddr = ipaDNSAddr->Next)
1188 {
1189 namesrvr.sa = ipaDNSAddr->Address.lpSockaddr;
1190
1191 if (namesrvr.sa->sa_family == AF_INET)
1192 {
1193 if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) ||
1194 (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE))
1195 continue;
1196
1197 /* Allocate room for another address, if necessary, else skip. */
1198 if(addressesIndex == addressesSize) {
1199 const size_t newSize = addressesSize + 4;
1200 Address * const newMem =
1201 (Address*)ares_realloc(addresses, sizeof(Address) * newSize);
1202 if(newMem == NULL) {
1203 continue;
1204 }
1205 addresses = newMem;
1206 addressesSize = newSize;
1207 }
1208
1209 /* Vista required for Luid or Ipv4Metric */
1210 if (ares_IsWindowsVistaOrGreater())
1211 {
1212 /* Save the address as the next element in addresses. */
1213 addresses[addressesIndex].metric =
1214 getBestRouteMetric(&ipaaEntry->Luid,
1215 (SOCKADDR_INET*)(namesrvr.sa),
1216 ipaaEntry->Ipv4Metric);
1217 }
1218 else
1219 {
1220 addresses[addressesIndex].metric = (ULONG)-1;
1221 }
1222
1223 /* Record insertion index to make qsort stable */
1224 addresses[addressesIndex].orig_idx = addressesIndex;
1225
1226 if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
1227 addresses[addressesIndex].text,
1228 sizeof(addresses[0].text))) {
1229 continue;
1230 }
1231 ++addressesIndex;
1232 }
1233 else if (namesrvr.sa->sa_family == AF_INET6)
1234 {
1235 if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any,
1236 sizeof(namesrvr.sa6->sin6_addr)) == 0)
1237 continue;
1238
1239 /* Allocate room for another address, if necessary, else skip. */
1240 if(addressesIndex == addressesSize) {
1241 const size_t newSize = addressesSize + 4;
1242 Address * const newMem =
1243 (Address*)ares_realloc(addresses, sizeof(Address) * newSize);
1244 if(newMem == NULL) {
1245 continue;
1246 }
1247 addresses = newMem;
1248 addressesSize = newSize;
1249 }
1250
1251 /* Vista required for Luid or Ipv4Metric */
1252 if (ares_IsWindowsVistaOrGreater())
1253 {
1254 /* Save the address as the next element in addresses. */
1255 addresses[addressesIndex].metric =
1256 getBestRouteMetric(&ipaaEntry->Luid,
1257 (SOCKADDR_INET*)(namesrvr.sa),
1258 ipaaEntry->Ipv6Metric);
1259 }
1260 else
1261 {
1262 addresses[addressesIndex].metric = (ULONG)-1;
1263 }
1264
1265 /* Record insertion index to make qsort stable */
1266 addresses[addressesIndex].orig_idx = addressesIndex;
1267
1268 if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr,
1269 addresses[addressesIndex].text,
1270 sizeof(addresses[0].text))) {
1271 continue;
1272 }
1273 ++addressesIndex;
1274 }
1275 else {
1276 /* Skip non-IPv4/IPv6 addresses completely. */
1277 continue;
1278 }
1279 }
1280 }
1281
1282 /* Sort all of the textual addresses by their metric (and original index if
1283 * metrics are equal). */
1284 qsort(addresses, addressesIndex, sizeof(*addresses), compareAddresses);
1285
1286 /* Join them all into a single string, removing duplicates. */
1287 {
1288 size_t i;
1289 for(i = 0; i < addressesIndex; ++i) {
1290 size_t j;
1291 /* Look for this address text appearing previously in the results. */
1292 for(j = 0; j < i; ++j) {
1293 if(strcmp(addresses[j].text, addresses[i].text) == 0) {
1294 break;
1295 }
1296 }
1297 /* Iff we didn't emit this address already, emit it now. */
1298 if(j == i) {
1299 /* Add that to outptr (if we can). */
1300 commajoin(outptr, addresses[i].text);
1301 }
1302 }
1303 }
1304
1305 done:
1306 ares_free(addresses);
1307
1308 if (ipaa)
1309 ares_free(ipaa);
1310
1311 if (!*outptr) {
1312 return 0;
1313 }
1314
1315 return 1;
1316 }
1317
1318 /*
1319 * get_DNS_Windows()
1320 *
1321 * Locates DNS info from Windows employing most suitable methods available at
1322 * run-time no matter which Windows version it is. When located, this returns
1323 * a pointer in *outptr to a newly allocated memory area holding a string with
1324 * a space or comma seperated list of DNS IP addresses, null-terminated.
1325 *
1326 * Returns 0 and nullifies *outptr upon inability to return DNSes string.
1327 *
1328 * Returns 1 and sets *outptr when returning a dynamically allocated string.
1329 *
1330 * Implementation supports Windows 95 and newer.
1331 */
get_DNS_Windows(char ** outptr)1332 static int get_DNS_Windows(char **outptr)
1333 {
1334 /* Try using IP helper API GetAdaptersAddresses(). IPv4 + IPv6, also sorts
1335 * DNS servers by interface route metrics to try to use the best DNS server. */
1336 if (get_DNS_AdaptersAddresses(outptr))
1337 return 1;
1338
1339 /* Try using IP helper API GetNetworkParams(). IPv4 only. */
1340 if (get_DNS_NetworkParams(outptr))
1341 return 1;
1342
1343 /* Fall-back to registry information */
1344 return get_DNS_Registry(outptr);
1345 }
1346
1347 /*
1348 * get_SuffixList_Windows()
1349 *
1350 * Reads the "DNS Suffix Search List" from registry and writes the list items
1351 * whitespace separated to outptr. If the Search List is empty, the
1352 * "Primary Dns Suffix" is written to outptr.
1353 *
1354 * Returns 0 and nullifies *outptr upon inability to return the suffix list.
1355 *
1356 * Returns 1 and sets *outptr when returning a dynamically allocated string.
1357 *
1358 * Implementation supports Windows Server 2003 and newer
1359 */
get_SuffixList_Windows(char ** outptr)1360 static int get_SuffixList_Windows(char **outptr)
1361 {
1362 HKEY hKey, hKeyEnum;
1363 char keyName[256];
1364 DWORD keyNameBuffSize;
1365 DWORD keyIdx = 0;
1366 char *p = NULL;
1367
1368 *outptr = NULL;
1369
1370 if (ares__getplatform() != WIN_NT)
1371 return 0;
1372
1373 /* 1. Global DNS Suffix Search List */
1374 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
1375 KEY_READ, &hKey) == ERROR_SUCCESS)
1376 {
1377 get_REG_SZ(hKey, SEARCHLIST_KEY, outptr);
1378 if (get_REG_SZ(hKey, DOMAIN_KEY, &p))
1379 {
1380 commajoin(outptr, p);
1381 ares_free(p);
1382 p = NULL;
1383 }
1384 RegCloseKey(hKey);
1385 }
1386
1387 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NT_DNSCLIENT, 0,
1388 KEY_READ, &hKey) == ERROR_SUCCESS)
1389 {
1390 if (get_REG_SZ(hKey, SEARCHLIST_KEY, &p))
1391 {
1392 commajoin(outptr, p);
1393 ares_free(p);
1394 p = NULL;
1395 }
1396 RegCloseKey(hKey);
1397 }
1398
1399 /* 2. Connection Specific Search List composed of:
1400 * a. Primary DNS Suffix */
1401 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_DNSCLIENT, 0,
1402 KEY_READ, &hKey) == ERROR_SUCCESS)
1403 {
1404 if (get_REG_SZ(hKey, PRIMARYDNSSUFFIX_KEY, &p))
1405 {
1406 commajoin(outptr, p);
1407 ares_free(p);
1408 p = NULL;
1409 }
1410 RegCloseKey(hKey);
1411 }
1412
1413 /* b. Interface SearchList, Domain, DhcpDomain */
1414 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY "\\" INTERFACES_KEY, 0,
1415 KEY_READ, &hKey) == ERROR_SUCCESS)
1416 {
1417 for(;;)
1418 {
1419 keyNameBuffSize = sizeof(keyName);
1420 if (RegEnumKeyExA(hKey, keyIdx++, keyName, &keyNameBuffSize,
1421 0, NULL, NULL, NULL)
1422 != ERROR_SUCCESS)
1423 break;
1424 if (RegOpenKeyExA(hKey, keyName, 0, KEY_QUERY_VALUE, &hKeyEnum)
1425 != ERROR_SUCCESS)
1426 continue;
1427 /* p can be comma separated (SearchList) */
1428 if (get_REG_SZ(hKeyEnum, SEARCHLIST_KEY, &p))
1429 {
1430 commajoin(outptr, p);
1431 ares_free(p);
1432 p = NULL;
1433 }
1434 if (get_REG_SZ(hKeyEnum, DOMAIN_KEY, &p))
1435 {
1436 commajoin(outptr, p);
1437 ares_free(p);
1438 p = NULL;
1439 }
1440 if (get_REG_SZ(hKeyEnum, DHCPDOMAIN_KEY, &p))
1441 {
1442 commajoin(outptr, p);
1443 ares_free(p);
1444 p = NULL;
1445 }
1446 RegCloseKey(hKeyEnum);
1447 }
1448 RegCloseKey(hKey);
1449 }
1450
1451 return *outptr != NULL;
1452 }
1453
1454 #endif
1455
init_by_resolv_conf(ares_channel channel)1456 static int init_by_resolv_conf(ares_channel channel)
1457 {
1458 #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32) && \
1459 !defined(CARES_USE_LIBRESOLV)
1460 char *line = NULL;
1461 #endif
1462 int status = -1, nservers = 0, nsort = 0;
1463 struct server_state *servers = NULL;
1464 struct apattern *sortlist = NULL;
1465
1466 #ifdef WIN32
1467
1468 if (channel->nservers > -1) /* don't override ARES_OPT_SERVER */
1469 return ARES_SUCCESS;
1470
1471 if (get_DNS_Windows(&line))
1472 {
1473 status = config_nameserver(&servers, &nservers, line);
1474 ares_free(line);
1475 }
1476
1477 if (channel->ndomains == -1 && get_SuffixList_Windows(&line))
1478 {
1479 status = set_search(channel, line);
1480 ares_free(line);
1481 }
1482
1483 if (status == ARES_SUCCESS)
1484 status = ARES_EOF;
1485 else
1486 /* Catch the case when all the above checks fail (which happens when there
1487 is no network card or the cable is unplugged) */
1488 status = ARES_EFILE;
1489
1490 #elif defined(__riscos__)
1491
1492 /* Under RISC OS, name servers are listed in the
1493 system variable Inet$Resolvers, space separated. */
1494
1495 line = getenv("Inet$Resolvers");
1496 status = ARES_EOF;
1497 if (line) {
1498 char *resolvers = ares_strdup(line), *pos, *space;
1499
1500 if (!resolvers)
1501 return ARES_ENOMEM;
1502
1503 pos = resolvers;
1504 do {
1505 space = strchr(pos, ' ');
1506 if (space)
1507 *space = '\0';
1508 status = config_nameserver(&servers, &nservers, pos);
1509 if (status != ARES_SUCCESS)
1510 break;
1511 pos = space + 1;
1512 } while (space);
1513
1514 if (status == ARES_SUCCESS)
1515 status = ARES_EOF;
1516
1517 ares_free(resolvers);
1518 }
1519
1520 #elif defined(WATT32)
1521 int i;
1522
1523 sock_init();
1524 for (i = 0; def_nameservers[i]; i++)
1525 ;
1526 if (i == 0)
1527 return ARES_SUCCESS; /* use localhost DNS server */
1528
1529 nservers = i;
1530 servers = ares_malloc(sizeof(struct server_state));
1531 if (!servers)
1532 return ARES_ENOMEM;
1533 memset(servers, 0, sizeof(struct server_state));
1534
1535 for (i = 0; def_nameservers[i]; i++)
1536 {
1537 servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]);
1538 servers[i].addr.family = AF_INET;
1539 servers[i].addr.udp_port = 0;
1540 servers[i].addr.tcp_port = 0;
1541 }
1542 status = ARES_EOF;
1543
1544 #elif defined(ANDROID) || defined(__ANDROID__)
1545 unsigned int i;
1546 char **dns_servers;
1547 char *domains;
1548 size_t num_servers;
1549
1550 /* Use the Android connectivity manager to get a list
1551 * of DNS servers. As of Android 8 (Oreo) net.dns#
1552 * system properties are no longer available. Google claims this
1553 * improves privacy. Apps now need the ACCESS_NETWORK_STATE
1554 * permission and must use the ConnectivityManager which
1555 * is Java only. */
1556 dns_servers = ares_get_android_server_list(MAX_DNS_PROPERTIES, &num_servers);
1557 if (dns_servers != NULL)
1558 {
1559 for (i = 0; i < num_servers; i++)
1560 {
1561 status = config_nameserver(&servers, &nservers, dns_servers[i]);
1562 if (status != ARES_SUCCESS)
1563 break;
1564 status = ARES_EOF;
1565 }
1566 for (i = 0; i < num_servers; i++)
1567 {
1568 ares_free(dns_servers[i]);
1569 }
1570 ares_free(dns_servers);
1571 }
1572 if (channel->ndomains == -1)
1573 {
1574 domains = ares_get_android_search_domains_list();
1575 set_search(channel, domains);
1576 ares_free(domains);
1577 }
1578
1579 # ifdef HAVE___SYSTEM_PROPERTY_GET
1580 /* Old way using the system property still in place as
1581 * a fallback. Older android versions can still use this.
1582 * it's possible for older apps not not have added the new
1583 * permission and we want to try to avoid breaking those.
1584 *
1585 * We'll only run this if we don't have any dns servers
1586 * because this will get the same ones (if it works). */
1587 if (status != ARES_EOF) {
1588 char propname[PROP_NAME_MAX];
1589 char propvalue[PROP_VALUE_MAX]="";
1590 for (i = 1; i <= MAX_DNS_PROPERTIES; i++) {
1591 snprintf(propname, sizeof(propname), "%s%u", DNS_PROP_NAME_PREFIX, i);
1592 if (__system_property_get(propname, propvalue) < 1) {
1593 status = ARES_EOF;
1594 break;
1595 }
1596
1597 status = config_nameserver(&servers, &nservers, propvalue);
1598 if (status != ARES_SUCCESS)
1599 break;
1600 status = ARES_EOF;
1601 }
1602 }
1603 # endif /* HAVE___SYSTEM_PROPERTY_GET */
1604 #elif defined(CARES_USE_LIBRESOLV)
1605 struct __res_state res;
1606 memset(&res, 0, sizeof(res));
1607 int result = res_ninit(&res);
1608 if (result == 0 && (res.options & RES_INIT)) {
1609 status = ARES_EOF;
1610
1611 if (channel->nservers == -1) {
1612 union res_sockaddr_union addr[MAXNS];
1613 int nscount = res_getservers(&res, addr, MAXNS);
1614 for (int i = 0; i < nscount; ++i) {
1615 char str[INET6_ADDRSTRLEN];
1616 int config_status;
1617 sa_family_t family = addr[i].sin.sin_family;
1618 if (family == AF_INET) {
1619 ares_inet_ntop(family, &addr[i].sin.sin_addr, str, sizeof(str));
1620 } else if (family == AF_INET6) {
1621 ares_inet_ntop(family, &addr[i].sin6.sin6_addr, str, sizeof(str));
1622 } else {
1623 continue;
1624 }
1625
1626 config_status = config_nameserver(&servers, &nservers, str);
1627 if (config_status != ARES_SUCCESS) {
1628 status = config_status;
1629 break;
1630 }
1631 }
1632 }
1633 if (channel->ndomains == -1) {
1634 int entries = 0;
1635 while ((entries < MAXDNSRCH) && res.dnsrch[entries])
1636 entries++;
1637
1638 channel->domains = ares_malloc(entries * sizeof(char *));
1639 if (!channel->domains) {
1640 status = ARES_ENOMEM;
1641 } else {
1642 channel->ndomains = entries;
1643 for (int i = 0; i < channel->ndomains; ++i) {
1644 channel->domains[i] = ares_strdup(res.dnsrch[i]);
1645 if (!channel->domains[i])
1646 status = ARES_ENOMEM;
1647 }
1648 }
1649 }
1650 if (channel->ndots == -1)
1651 channel->ndots = res.ndots;
1652 if (channel->tries == -1)
1653 channel->tries = res.retry;
1654 if (channel->rotate == -1)
1655 channel->rotate = res.options & RES_ROTATE;
1656 if (channel->timeout == -1)
1657 channel->timeout = res.retrans * 1000;
1658
1659 res_ndestroy(&res);
1660 }
1661 #else
1662 {
1663 char *p;
1664 FILE *fp;
1665 size_t linesize;
1666 int error;
1667 int update_domains;
1668 const char *resolvconf_path;
1669
1670 /* Don't read resolv.conf and friends if we don't have to */
1671 if (ARES_CONFIG_CHECK(channel))
1672 return ARES_SUCCESS;
1673
1674 /* Only update search domains if they're not already specified */
1675 update_domains = (channel->ndomains == -1);
1676
1677 /* Support path for resolvconf filename set by ares_init_options */
1678 if(channel->resolvconf_path) {
1679 resolvconf_path = channel->resolvconf_path;
1680 } else {
1681 resolvconf_path = PATH_RESOLV_CONF;
1682 }
1683
1684 fp = fopen(resolvconf_path, "r");
1685 if (fp) {
1686 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
1687 {
1688 if ((p = try_config(line, "domain", ';')) && update_domains)
1689 status = config_domain(channel, p);
1690 else if ((p = try_config(line, "lookup", ';')) && !channel->lookups)
1691 status = config_lookup(channel, p, "bind", NULL, "file");
1692 else if ((p = try_config(line, "search", ';')) && update_domains)
1693 status = set_search(channel, p);
1694 else if ((p = try_config(line, "nameserver", ';')) &&
1695 channel->nservers == -1)
1696 status = config_nameserver(&servers, &nservers, p);
1697 else if ((p = try_config(line, "sortlist", ';')) &&
1698 channel->nsort == -1)
1699 status = config_sortlist(&sortlist, &nsort, p);
1700 else if ((p = try_config(line, "options", ';')))
1701 status = set_options(channel, p);
1702 else
1703 status = ARES_SUCCESS;
1704 if (status != ARES_SUCCESS)
1705 break;
1706 }
1707 fclose(fp);
1708 }
1709 else {
1710 error = ERRNO;
1711 switch(error) {
1712 case ENOENT:
1713 case ESRCH:
1714 status = ARES_EOF;
1715 break;
1716 default:
1717 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1718 error, strerror(error)));
1719 DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
1720 status = ARES_EFILE;
1721 }
1722 }
1723
1724 if ((status == ARES_EOF) && (!channel->lookups)) {
1725 /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
1726 fp = fopen("/etc/nsswitch.conf", "r");
1727 if (fp) {
1728 while ((status = ares__read_line(fp, &line, &linesize)) ==
1729 ARES_SUCCESS)
1730 {
1731 if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups)
1732 (void)config_lookup(channel, p, "dns", "resolve", "files");
1733 }
1734 fclose(fp);
1735 }
1736 else {
1737 error = ERRNO;
1738 switch(error) {
1739 case ENOENT:
1740 case ESRCH:
1741 break;
1742 default:
1743 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1744 error, strerror(error)));
1745 DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1746 "/etc/nsswitch.conf"));
1747 }
1748
1749 /* ignore error, maybe we will get luck in next if clause */
1750 status = ARES_EOF;
1751 }
1752 }
1753
1754 if ((status == ARES_EOF) && (!channel->lookups)) {
1755 /* Linux / GNU libc 2.x and possibly others have host.conf */
1756 fp = fopen("/etc/host.conf", "r");
1757 if (fp) {
1758 while ((status = ares__read_line(fp, &line, &linesize)) ==
1759 ARES_SUCCESS)
1760 {
1761 if ((p = try_config(line, "order", '\0')) && !channel->lookups)
1762 /* ignore errors */
1763 (void)config_lookup(channel, p, "bind", NULL, "hosts");
1764 }
1765 fclose(fp);
1766 }
1767 else {
1768 error = ERRNO;
1769 switch(error) {
1770 case ENOENT:
1771 case ESRCH:
1772 break;
1773 default:
1774 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1775 error, strerror(error)));
1776 DEBUGF(fprintf(stderr, "Error opening file: %s\n",
1777 "/etc/host.conf"));
1778 }
1779
1780 /* ignore error, maybe we will get luck in next if clause */
1781 status = ARES_EOF;
1782 }
1783 }
1784
1785 if ((status == ARES_EOF) && (!channel->lookups)) {
1786 /* Tru64 uses /etc/svc.conf */
1787 fp = fopen("/etc/svc.conf", "r");
1788 if (fp) {
1789 while ((status = ares__read_line(fp, &line, &linesize)) ==
1790 ARES_SUCCESS)
1791 {
1792 if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups)
1793 /* ignore errors */
1794 (void)config_lookup(channel, p, "bind", NULL, "local");
1795 }
1796 fclose(fp);
1797 }
1798 else {
1799 error = ERRNO;
1800 switch(error) {
1801 case ENOENT:
1802 case ESRCH:
1803 break;
1804 default:
1805 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1806 error, strerror(error)));
1807 DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
1808 }
1809
1810 /* ignore error, default value will be chosen for `channel->lookups` */
1811 status = ARES_EOF;
1812 }
1813 }
1814
1815 if(line)
1816 ares_free(line);
1817 }
1818
1819 #endif
1820
1821 /* Handle errors. */
1822 if (status != ARES_EOF)
1823 {
1824 if (servers != NULL)
1825 ares_free(servers);
1826 if (sortlist != NULL)
1827 ares_free(sortlist);
1828 return status;
1829 }
1830
1831 /* If we got any name server entries, fill them in. */
1832 if (servers)
1833 {
1834 channel->servers = servers;
1835 channel->nservers = nservers;
1836 }
1837
1838 /* If we got any sortlist entries, fill them in. */
1839 if (sortlist)
1840 {
1841 channel->sortlist = sortlist;
1842 channel->nsort = nsort;
1843 }
1844
1845 return ARES_SUCCESS;
1846 }
1847
init_by_defaults(ares_channel channel)1848 static int init_by_defaults(ares_channel channel)
1849 {
1850 char *hostname = NULL;
1851 int rc = ARES_SUCCESS;
1852 #ifdef HAVE_GETHOSTNAME
1853 char *dot;
1854 #endif
1855
1856 if (channel->flags == -1)
1857 channel->flags = 0;
1858 if (channel->timeout == -1)
1859 channel->timeout = DEFAULT_TIMEOUT;
1860 if (channel->tries == -1)
1861 channel->tries = DEFAULT_TRIES;
1862 if (channel->ndots == -1)
1863 channel->ndots = 1;
1864 if (channel->rotate == -1)
1865 channel->rotate = 0;
1866 if (channel->udp_port == -1)
1867 channel->udp_port = htons(NAMESERVER_PORT);
1868 if (channel->tcp_port == -1)
1869 channel->tcp_port = htons(NAMESERVER_PORT);
1870
1871 if (channel->ednspsz == -1)
1872 channel->ednspsz = EDNSPACKETSZ;
1873
1874 if (channel->nservers == -1) {
1875 /* If nobody specified servers, try a local named. */
1876 channel->servers = ares_malloc(sizeof(struct server_state));
1877 if (!channel->servers) {
1878 rc = ARES_ENOMEM;
1879 goto error;
1880 }
1881 channel->servers[0].addr.family = AF_INET;
1882 channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK);
1883 channel->servers[0].addr.udp_port = 0;
1884 channel->servers[0].addr.tcp_port = 0;
1885 channel->nservers = 1;
1886 }
1887
1888 #if defined(USE_WINSOCK)
1889 #define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT)
1890 #elif defined(ENAMETOOLONG)
1891 #define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \
1892 (SOCKERRNO == EINVAL))
1893 #else
1894 #define toolong(x) (x == -1) && (SOCKERRNO == EINVAL)
1895 #endif
1896
1897 if (channel->ndomains == -1) {
1898 /* Derive a default domain search list from the kernel hostname,
1899 * or set it to empty if the hostname isn't helpful.
1900 */
1901 #ifndef HAVE_GETHOSTNAME
1902 channel->ndomains = 0; /* default to none */
1903 #else
1904 GETHOSTNAME_TYPE_ARG2 lenv = 64;
1905 size_t len = 64;
1906 int res;
1907 channel->ndomains = 0; /* default to none */
1908
1909 hostname = ares_malloc(len);
1910 if(!hostname) {
1911 rc = ARES_ENOMEM;
1912 goto error;
1913 }
1914
1915 do {
1916 res = gethostname(hostname, lenv);
1917
1918 if(toolong(res)) {
1919 char *p;
1920 len *= 2;
1921 lenv *= 2;
1922 p = ares_realloc(hostname, len);
1923 if(!p) {
1924 rc = ARES_ENOMEM;
1925 goto error;
1926 }
1927 hostname = p;
1928 continue;
1929 }
1930 else if(res) {
1931 /* Lets not treat a gethostname failure as critical, since we
1932 * are ok if gethostname doesn't even exist */
1933 *hostname = '\0';
1934 break;
1935 }
1936
1937 } while (res != 0);
1938
1939 dot = strchr(hostname, '.');
1940 if (dot) {
1941 /* a dot was found */
1942 channel->domains = ares_malloc(sizeof(char *));
1943 if (!channel->domains) {
1944 rc = ARES_ENOMEM;
1945 goto error;
1946 }
1947 channel->domains[0] = ares_strdup(dot + 1);
1948 if (!channel->domains[0]) {
1949 rc = ARES_ENOMEM;
1950 goto error;
1951 }
1952 channel->ndomains = 1;
1953 }
1954 #endif
1955 }
1956
1957 if (channel->nsort == -1) {
1958 channel->sortlist = NULL;
1959 channel->nsort = 0;
1960 }
1961
1962 if (!channel->lookups) {
1963 channel->lookups = ares_strdup("fb");
1964 if (!channel->lookups)
1965 rc = ARES_ENOMEM;
1966 }
1967
1968 error:
1969 if(rc) {
1970 if(channel->servers) {
1971 ares_free(channel->servers);
1972 channel->servers = NULL;
1973 }
1974
1975 if(channel->domains && channel->domains[0])
1976 ares_free(channel->domains[0]);
1977 if(channel->domains) {
1978 ares_free(channel->domains);
1979 channel->domains = NULL;
1980 }
1981
1982 if(channel->lookups) {
1983 ares_free(channel->lookups);
1984 channel->lookups = NULL;
1985 }
1986
1987 if(channel->resolvconf_path) {
1988 ares_free(channel->resolvconf_path);
1989 channel->resolvconf_path = NULL;
1990 }
1991 }
1992
1993 if(hostname)
1994 ares_free(hostname);
1995
1996 return rc;
1997 }
1998
1999 #if !defined(WIN32) && !defined(WATT32) && \
2000 !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
config_domain(ares_channel channel,char * str)2001 static int config_domain(ares_channel channel, char *str)
2002 {
2003 char *q;
2004
2005 /* Set a single search domain. */
2006 q = str;
2007 while (*q && !ISSPACE(*q))
2008 q++;
2009 *q = '\0';
2010 return set_search(channel, str);
2011 }
2012
2013 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
2014 defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
2015 /* workaround icc 9.1 optimizer issue */
2016 # define vqualifier volatile
2017 #else
2018 # define vqualifier
2019 #endif
2020
config_lookup(ares_channel channel,const char * str,const char * bindch,const char * altbindch,const char * filech)2021 static int config_lookup(ares_channel channel, const char *str,
2022 const char *bindch, const char *altbindch,
2023 const char *filech)
2024 {
2025 char lookups[3], *l;
2026 const char *vqualifier p;
2027 int found;
2028
2029 if (altbindch == NULL)
2030 altbindch = bindch;
2031
2032 /* Set the lookup order. Only the first letter of each work
2033 * is relevant, and it has to be "b" for DNS or "f" for the
2034 * host file. Ignore everything else.
2035 */
2036 l = lookups;
2037 p = str;
2038 found = 0;
2039 while (*p)
2040 {
2041 if ((*p == *bindch || *p == *altbindch || *p == *filech) && l < lookups + 2) {
2042 if (*p == *bindch || *p == *altbindch) *l++ = 'b';
2043 else *l++ = 'f';
2044 found = 1;
2045 }
2046 while (*p && !ISSPACE(*p) && (*p != ','))
2047 p++;
2048 while (*p && (ISSPACE(*p) || (*p == ',')))
2049 p++;
2050 }
2051 if (!found)
2052 return ARES_ENOTINITIALIZED;
2053 *l = '\0';
2054 channel->lookups = ares_strdup(lookups);
2055 return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
2056 }
2057 #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ & !CARES_USE_LIBRESOLV */
2058
2059 #ifndef WATT32
2060 /* Validate that the ip address matches the subnet (network base and network
2061 * mask) specified. Addresses are specified in standard Network Byte Order as
2062 * 16 bytes, and the netmask is 0 to 128 (bits).
2063 */
ares_ipv6_subnet_matches(const unsigned char netbase[16],unsigned char netmask,const unsigned char ipaddr[16])2064 static int ares_ipv6_subnet_matches(const unsigned char netbase[16],
2065 unsigned char netmask,
2066 const unsigned char ipaddr[16])
2067 {
2068 unsigned char mask[16] = { 0 };
2069 unsigned char i;
2070
2071 /* Misuse */
2072 if (netmask > 128)
2073 return 0;
2074
2075 /* Quickly set whole bytes */
2076 memset(mask, 0xFF, netmask / 8);
2077
2078 /* Set remaining bits */
2079 if(netmask % 8) {
2080 mask[netmask / 8] = (unsigned char)(0xff << (8 - (netmask % 8)));
2081 }
2082
2083 for (i=0; i<16; i++) {
2084 if ((netbase[i] & mask[i]) != (ipaddr[i] & mask[i]))
2085 return 0;
2086 }
2087
2088 return 1;
2089 }
2090
2091 /* Return true iff the IPv6 ipaddr is blacklisted. */
ares_ipv6_server_blacklisted(const unsigned char ipaddr[16])2092 static int ares_ipv6_server_blacklisted(const unsigned char ipaddr[16])
2093 {
2094 /* A list of blacklisted IPv6 subnets. */
2095 const struct {
2096 const unsigned char netbase[16];
2097 unsigned char netmask;
2098 } blacklist[] = {
2099 /* fec0::/10 was deprecated by [RFC3879] in September 2004. Formerly a
2100 * Site-Local scoped address prefix. These are never valid DNS servers,
2101 * but are known to be returned at least sometimes on Windows and Android.
2102 */
2103 {
2104 {
2105 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2107 },
2108 10
2109 }
2110 };
2111 size_t i;
2112
2113 /* See if ipaddr matches any of the entries in the blacklist. */
2114 for (i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); ++i) {
2115 if (ares_ipv6_subnet_matches(
2116 blacklist[i].netbase, blacklist[i].netmask, ipaddr))
2117 return 1;
2118 }
2119 return 0;
2120 }
2121
2122 /* Add the IPv4 or IPv6 nameservers in str (separated by commas) to the
2123 * servers list, updating servers and nservers as required.
2124 *
2125 * This will silently ignore blacklisted IPv6 nameservers as detected by
2126 * ares_ipv6_server_blacklisted().
2127 *
2128 * Returns an error code on failure, else ARES_SUCCESS.
2129 */
config_nameserver(struct server_state ** servers,int * nservers,char * str)2130 static int config_nameserver(struct server_state **servers, int *nservers,
2131 char *str)
2132 {
2133 struct ares_addr host;
2134 struct server_state *newserv;
2135 char *p, *txtaddr;
2136 /* On Windows, there may be more than one nameserver specified in the same
2137 * registry key, so we parse input as a space or comma seperated list.
2138 */
2139 for (p = str; p;)
2140 {
2141 /* Skip whitespace and commas. */
2142 while (*p && (ISSPACE(*p) || (*p == ',')))
2143 p++;
2144 if (!*p)
2145 /* No more input, done. */
2146 break;
2147
2148 /* Pointer to start of IPv4 or IPv6 address part. */
2149 txtaddr = p;
2150
2151 /* Advance past this address. */
2152 while (*p && !ISSPACE(*p) && (*p != ','))
2153 p++;
2154 if (*p)
2155 /* Null terminate this address. */
2156 *p++ = '\0';
2157 else
2158 /* Reached end of input, done when this address is processed. */
2159 p = NULL;
2160
2161 /* Convert textual address to binary format. */
2162 if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
2163 host.family = AF_INET;
2164 else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1
2165 /* Silently skip blacklisted IPv6 servers. */
2166 && !ares_ipv6_server_blacklisted(
2167 (const unsigned char *)&host.addrV6))
2168 host.family = AF_INET6;
2169 else
2170 continue;
2171
2172 /* Resize servers state array. */
2173 newserv = ares_realloc(*servers, (*nservers + 1) *
2174 sizeof(struct server_state));
2175 if (!newserv)
2176 return ARES_ENOMEM;
2177
2178 /* Store address data. */
2179 newserv[*nservers].addr.family = host.family;
2180 newserv[*nservers].addr.udp_port = 0;
2181 newserv[*nservers].addr.tcp_port = 0;
2182 if (host.family == AF_INET)
2183 memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
2184 sizeof(host.addrV4));
2185 else
2186 memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
2187 sizeof(host.addrV6));
2188
2189 /* Update arguments. */
2190 *servers = newserv;
2191 *nservers += 1;
2192 }
2193
2194 return ARES_SUCCESS;
2195 }
2196 #endif /* !WATT32 */
2197
config_sortlist(struct apattern ** sortlist,int * nsort,const char * str)2198 static int config_sortlist(struct apattern **sortlist, int *nsort,
2199 const char *str)
2200 {
2201 struct apattern pat;
2202 const char *q;
2203
2204 /* Add sortlist entries. */
2205 while (*str && *str != ';')
2206 {
2207 int bits;
2208 char ipbuf[16], ipbufpfx[32];
2209 /* Find just the IP */
2210 q = str;
2211 while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
2212 q++;
2213 memcpy(ipbuf, str, q-str);
2214 ipbuf[q-str] = '\0';
2215 /* Find the prefix */
2216 if (*q == '/')
2217 {
2218 const char *str2 = q+1;
2219 while (*q && *q != ';' && !ISSPACE(*q))
2220 q++;
2221 memcpy(ipbufpfx, str, q-str);
2222 ipbufpfx[q-str] = '\0';
2223 str = str2;
2224 }
2225 else
2226 ipbufpfx[0] = '\0';
2227 /* Lets see if it is CIDR */
2228 /* First we'll try IPv6 */
2229 if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf,
2230 &pat.addrV6,
2231 sizeof(pat.addrV6))) > 0)
2232 {
2233 pat.type = PATTERN_CIDR;
2234 pat.mask.bits = (unsigned short)bits;
2235 pat.family = AF_INET6;
2236 if (!sortlist_alloc(sortlist, nsort, &pat)) {
2237 ares_free(*sortlist);
2238 *sortlist = NULL;
2239 return ARES_ENOMEM;
2240 }
2241 }
2242 else if (ipbufpfx[0] &&
2243 (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4,
2244 sizeof(pat.addrV4))) > 0)
2245 {
2246 pat.type = PATTERN_CIDR;
2247 pat.mask.bits = (unsigned short)bits;
2248 pat.family = AF_INET;
2249 if (!sortlist_alloc(sortlist, nsort, &pat)) {
2250 ares_free(*sortlist);
2251 *sortlist = NULL;
2252 return ARES_ENOMEM;
2253 }
2254 }
2255 /* See if it is just a regular IP */
2256 else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0)
2257 {
2258 if (ipbufpfx[0])
2259 {
2260 memcpy(ipbuf, str, q-str);
2261 ipbuf[q-str] = '\0';
2262 if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0)
2263 natural_mask(&pat);
2264 }
2265 else
2266 natural_mask(&pat);
2267 pat.family = AF_INET;
2268 pat.type = PATTERN_MASK;
2269 if (!sortlist_alloc(sortlist, nsort, &pat)) {
2270 ares_free(*sortlist);
2271 *sortlist = NULL;
2272 return ARES_ENOMEM;
2273 }
2274 }
2275 else
2276 {
2277 while (*q && *q != ';' && !ISSPACE(*q))
2278 q++;
2279 }
2280 str = q;
2281 while (ISSPACE(*str))
2282 str++;
2283 }
2284
2285 return ARES_SUCCESS;
2286 }
2287
set_search(ares_channel channel,const char * str)2288 static int set_search(ares_channel channel, const char *str)
2289 {
2290 size_t cnt;
2291
2292 if(channel->ndomains != -1) {
2293 /* LCOV_EXCL_START: all callers check ndomains == -1 */
2294 /* if we already have some domains present, free them first */
2295 ares_strsplit_free(channel->domains, channel->ndomains);
2296 channel->domains = NULL;
2297 channel->ndomains = -1;
2298 } /* LCOV_EXCL_STOP */
2299
2300 channel->domains = ares_strsplit(str, ", ", 1, &cnt);
2301 channel->ndomains = (int)cnt;
2302 if (channel->domains == NULL || channel->ndomains == 0) {
2303 channel->domains = NULL;
2304 channel->ndomains = -1;
2305 }
2306
2307 return ARES_SUCCESS;
2308 }
2309
set_options(ares_channel channel,const char * str)2310 static int set_options(ares_channel channel, const char *str)
2311 {
2312 const char *p, *q, *val;
2313
2314 p = str;
2315 while (*p)
2316 {
2317 q = p;
2318 while (*q && !ISSPACE(*q))
2319 q++;
2320 val = try_option(p, q, "ndots:");
2321 if (val && channel->ndots == -1)
2322 channel->ndots = aresx_sltosi(strtol(val, NULL, 10));
2323 val = try_option(p, q, "retrans:");
2324 if (val && channel->timeout == -1)
2325 channel->timeout = aresx_sltosi(strtol(val, NULL, 10));
2326 val = try_option(p, q, "retry:");
2327 if (val && channel->tries == -1)
2328 channel->tries = aresx_sltosi(strtol(val, NULL, 10));
2329 val = try_option(p, q, "rotate");
2330 if (val && channel->rotate == -1)
2331 channel->rotate = 1;
2332 p = q;
2333 while (ISSPACE(*p))
2334 p++;
2335 }
2336
2337 return ARES_SUCCESS;
2338 }
2339
try_option(const char * p,const char * q,const char * opt)2340 static const char *try_option(const char *p, const char *q, const char *opt)
2341 {
2342 size_t len = strlen(opt);
2343 return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL;
2344 }
2345
2346 #if !defined(WIN32) && !defined(WATT32) && \
2347 !defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
try_config(char * s,const char * opt,char scc)2348 static char *try_config(char *s, const char *opt, char scc)
2349 {
2350 size_t len;
2351 char *p;
2352 char *q;
2353
2354 if (!s || !opt)
2355 /* no line or no option */
2356 return NULL; /* LCOV_EXCL_LINE */
2357
2358 /* Hash '#' character is always used as primary comment char, additionally
2359 a not-NUL secondary comment char will be considered when specified. */
2360
2361 /* trim line comment */
2362 p = s;
2363 if(scc)
2364 while (*p && (*p != '#') && (*p != scc))
2365 p++;
2366 else
2367 while (*p && (*p != '#'))
2368 p++;
2369 *p = '\0';
2370
2371 /* trim trailing whitespace */
2372 q = p - 1;
2373 while ((q >= s) && ISSPACE(*q))
2374 q--;
2375 *++q = '\0';
2376
2377 /* skip leading whitespace */
2378 p = s;
2379 while (*p && ISSPACE(*p))
2380 p++;
2381
2382 if (!*p)
2383 /* empty line */
2384 return NULL;
2385
2386 if ((len = strlen(opt)) == 0)
2387 /* empty option */
2388 return NULL; /* LCOV_EXCL_LINE */
2389
2390 if (strncmp(p, opt, len) != 0)
2391 /* line and option do not match */
2392 return NULL;
2393
2394 /* skip over given option name */
2395 p += len;
2396
2397 if (!*p)
2398 /* no option value */
2399 return NULL; /* LCOV_EXCL_LINE */
2400
2401 if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p))
2402 /* whitespace between option name and value is mandatory
2403 for given option names which do not end with ':' or '=' */
2404 return NULL;
2405
2406 /* skip over whitespace */
2407 while (*p && ISSPACE(*p))
2408 p++;
2409
2410 if (!*p)
2411 /* no option value */
2412 return NULL;
2413
2414 /* return pointer to option value */
2415 return p;
2416 }
2417 #endif /* !WIN32 & !WATT32 & !ANDROID & !__ANDROID__ */
2418
ip_addr(const char * ipbuf,ares_ssize_t len,struct in_addr * addr)2419 static int ip_addr(const char *ipbuf, ares_ssize_t len, struct in_addr *addr)
2420 {
2421
2422 /* Four octets and three periods yields at most 15 characters. */
2423 if (len > 15)
2424 return -1;
2425
2426 if (ares_inet_pton(AF_INET, ipbuf, addr) < 1)
2427 return -1;
2428
2429 return 0;
2430 }
2431
natural_mask(struct apattern * pat)2432 static void natural_mask(struct apattern *pat)
2433 {
2434 struct in_addr addr;
2435
2436 /* Store a host-byte-order copy of pat in a struct in_addr. Icky,
2437 * but portable.
2438 */
2439 addr.s_addr = ntohl(pat->addrV4.s_addr);
2440
2441 /* This is out of date in the CIDR world, but some people might
2442 * still rely on it.
2443 */
2444 if (IN_CLASSA(addr.s_addr))
2445 pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET);
2446 else if (IN_CLASSB(addr.s_addr))
2447 pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET);
2448 else
2449 pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET);
2450 }
2451
sortlist_alloc(struct apattern ** sortlist,int * nsort,struct apattern * pat)2452 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
2453 struct apattern *pat)
2454 {
2455 struct apattern *newsort;
2456 newsort = ares_realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
2457 if (!newsort)
2458 return 0;
2459 newsort[*nsort] = *pat;
2460 *sortlist = newsort;
2461 (*nsort)++;
2462 return 1;
2463 }
2464
2465 /* initialize an rc4 key. If possible a cryptographically secure random key
2466 is generated using a suitable function (for example win32's RtlGenRandom as
2467 described in
2468 http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
2469 otherwise the code defaults to cross-platform albeit less secure mechanism
2470 using rand
2471 */
randomize_key(unsigned char * key,int key_data_len)2472 static void randomize_key(unsigned char* key,int key_data_len)
2473 {
2474 int randomized = 0;
2475 int counter=0;
2476 #ifdef WIN32
2477 BOOLEAN res;
2478 if (ares_fpSystemFunction036)
2479 {
2480 res = (*ares_fpSystemFunction036) (key, key_data_len);
2481 if (res)
2482 randomized = 1;
2483 }
2484 #else /* !WIN32 */
2485 #ifdef RANDOM_FILE
2486 FILE *f = fopen(RANDOM_FILE, "rb");
2487 if(f) {
2488 counter = aresx_uztosi(fread(key, 1, key_data_len, f));
2489 fclose(f);
2490 }
2491 #endif
2492 #endif /* WIN32 */
2493
2494 if (!randomized) {
2495 for (;counter<key_data_len;counter++)
2496 key[counter]=(unsigned char)(rand() % 256); /* LCOV_EXCL_LINE */
2497 }
2498 }
2499
init_id_key(rc4_key * key,int key_data_len)2500 static int init_id_key(rc4_key* key,int key_data_len)
2501 {
2502 unsigned char index1;
2503 unsigned char index2;
2504 unsigned char* state;
2505 short counter;
2506 unsigned char *key_data_ptr = 0;
2507
2508 key_data_ptr = ares_malloc(key_data_len);
2509 if (!key_data_ptr)
2510 return ARES_ENOMEM;
2511 memset(key_data_ptr, 0, key_data_len);
2512
2513 state = &key->state[0];
2514 for(counter = 0; counter < 256; counter++)
2515 /* unnecessary AND but it keeps some compilers happier */
2516 state[counter] = (unsigned char)(counter & 0xff);
2517 randomize_key(key->state,key_data_len);
2518 key->x = 0;
2519 key->y = 0;
2520 index1 = 0;
2521 index2 = 0;
2522 for(counter = 0; counter < 256; counter++)
2523 {
2524 index2 = (unsigned char)((key_data_ptr[index1] + state[counter] +
2525 index2) % 256);
2526 ARES_SWAP_BYTE(&state[counter], &state[index2]);
2527
2528 index1 = (unsigned char)((index1 + 1) % key_data_len);
2529 }
2530 ares_free(key_data_ptr);
2531 return ARES_SUCCESS;
2532 }
2533
ares_set_local_ip4(ares_channel channel,unsigned int local_ip)2534 void ares_set_local_ip4(ares_channel channel, unsigned int local_ip)
2535 {
2536 channel->local_ip4 = local_ip;
2537 }
2538
2539 /* local_ip6 should be 16 bytes in length */
ares_set_local_ip6(ares_channel channel,const unsigned char * local_ip6)2540 void ares_set_local_ip6(ares_channel channel,
2541 const unsigned char* local_ip6)
2542 {
2543 memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
2544 }
2545
2546 /* local_dev_name should be null terminated. */
ares_set_local_dev(ares_channel channel,const char * local_dev_name)2547 void ares_set_local_dev(ares_channel channel,
2548 const char* local_dev_name)
2549 {
2550 strncpy(channel->local_dev_name, local_dev_name,
2551 sizeof(channel->local_dev_name));
2552 channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
2553 }
2554
2555
ares_set_socket_callback(ares_channel channel,ares_sock_create_callback cb,void * data)2556 void ares_set_socket_callback(ares_channel channel,
2557 ares_sock_create_callback cb,
2558 void *data)
2559 {
2560 channel->sock_create_cb = cb;
2561 channel->sock_create_cb_data = data;
2562 }
2563
ares_set_socket_configure_callback(ares_channel channel,ares_sock_config_callback cb,void * data)2564 void ares_set_socket_configure_callback(ares_channel channel,
2565 ares_sock_config_callback cb,
2566 void *data)
2567 {
2568 channel->sock_config_cb = cb;
2569 channel->sock_config_cb_data = data;
2570 }
2571
ares_set_socket_functions(ares_channel channel,const struct ares_socket_functions * funcs,void * data)2572 void ares_set_socket_functions(ares_channel channel,
2573 const struct ares_socket_functions * funcs,
2574 void *data)
2575 {
2576 channel->sock_funcs = funcs;
2577 channel->sock_func_cb_data = data;
2578 }
2579
ares_set_sortlist(ares_channel channel,const char * sortstr)2580 int ares_set_sortlist(ares_channel channel, const char *sortstr)
2581 {
2582 int nsort = 0;
2583 struct apattern *sortlist = NULL;
2584 int status;
2585
2586 if (!channel)
2587 return ARES_ENODATA;
2588
2589 status = config_sortlist(&sortlist, &nsort, sortstr);
2590 if (status == ARES_SUCCESS && sortlist) {
2591 if (channel->sortlist)
2592 ares_free(channel->sortlist);
2593 channel->sortlist = sortlist;
2594 channel->nsort = nsort;
2595 }
2596 return status;
2597 }
2598
ares__init_servers_state(ares_channel channel)2599 void ares__init_servers_state(ares_channel channel)
2600 {
2601 struct server_state *server;
2602 int i;
2603
2604 for (i = 0; i < channel->nservers; i++)
2605 {
2606 server = &channel->servers[i];
2607 server->udp_socket = ARES_SOCKET_BAD;
2608 server->tcp_socket = ARES_SOCKET_BAD;
2609 server->tcp_connection_generation = ++channel->tcp_connection_generation;
2610 server->tcp_lenbuf_pos = 0;
2611 server->tcp_buffer_pos = 0;
2612 server->tcp_buffer = NULL;
2613 server->tcp_length = 0;
2614 server->qhead = NULL;
2615 server->qtail = NULL;
2616 ares__init_list_head(&server->queries_to_server);
2617 server->channel = channel;
2618 server->is_broken = 0;
2619 }
2620 }
2621