1 /* MIT License
2 *
3 * Copyright (c) 1998 Massachusetts Institute of Technology
4 * Copyright (c) 2007 Daniel Stenberg
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * SPDX-License-Identifier: MIT
26 */
27
28 #include "ares_setup.h"
29
30 #ifdef HAVE_SYS_PARAM_H
31 # include <sys/param.h>
32 #endif
33
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
36 #endif
37
38 #ifdef HAVE_NETDB_H
39 # include <netdb.h>
40 #endif
41
42 #ifdef HAVE_ARPA_INET_H
43 # include <arpa/inet.h>
44 #endif
45
46 #include "ares_nameser.h"
47
48 #if defined(ANDROID) || defined(__ANDROID__)
49 # include <sys/system_properties.h>
50 # include "ares_android.h"
51 /* From the Bionic sources */
52 # define DNS_PROP_NAME_PREFIX "net.dns"
53 # define MAX_DNS_PROPERTIES 8
54 #endif
55
56 #if defined(CARES_USE_LIBRESOLV)
57 # include <resolv.h>
58 #endif
59
60 #if defined(USE_WINSOCK) && defined(HAVE_IPHLPAPI_H)
61 # include <iphlpapi.h>
62 #endif
63
64 #include "ares.h"
65 #include "ares_inet_net_pton.h"
66 #include "ares_platform.h"
67 #include "ares_private.h"
68
69 #ifdef WATT32
70 # undef WIN32 /* Redefined in MingW/MSVC headers */
71 #endif
72
73
ares_init(ares_channel_t ** channelptr)74 int ares_init(ares_channel_t **channelptr)
75 {
76 return ares_init_options(channelptr, NULL, 0);
77 }
78
ares_query_timeout_cmp_cb(const void * arg1,const void * arg2)79 static int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2)
80 {
81 const struct query *q1 = arg1;
82 const struct query *q2 = arg2;
83
84 if (q1->timeout.tv_sec > q2->timeout.tv_sec) {
85 return 1;
86 }
87 if (q1->timeout.tv_sec < q2->timeout.tv_sec) {
88 return -1;
89 }
90
91 if (q1->timeout.tv_usec > q2->timeout.tv_usec) {
92 return 1;
93 }
94 if (q1->timeout.tv_usec < q2->timeout.tv_usec) {
95 return -1;
96 }
97
98 return 0;
99 }
100
server_sort_cb(const void * data1,const void * data2)101 static int server_sort_cb(const void *data1, const void *data2)
102 {
103 const struct server_state *s1 = data1;
104 const struct server_state *s2 = data2;
105
106 if (s1->consec_failures < s2->consec_failures) {
107 return -1;
108 }
109 if (s1->consec_failures > s2->consec_failures) {
110 return 1;
111 }
112 if (s1->idx < s2->idx) {
113 return -1;
114 }
115 if (s1->idx > s2->idx) {
116 return 1;
117 }
118 return 0;
119 }
120
server_destroy_cb(void * data)121 static void server_destroy_cb(void *data)
122 {
123 if (data == NULL) {
124 return;
125 }
126 ares__destroy_server(data);
127 }
128
init_by_defaults(ares_channel_t * channel)129 static ares_status_t init_by_defaults(ares_channel_t *channel)
130 {
131 char *hostname = NULL;
132 ares_status_t rc = ARES_SUCCESS;
133 #ifdef HAVE_GETHOSTNAME
134 const char *dot;
135 #endif
136 struct ares_addr addr;
137 ares__llist_t *sconfig = NULL;
138
139 /* Enable EDNS by default */
140 if (!(channel->optmask & ARES_OPT_FLAGS)) {
141 channel->flags = ARES_FLAG_EDNS;
142 }
143 if (channel->ednspsz == 0) {
144 channel->ednspsz = EDNSPACKETSZ;
145 }
146
147 if (channel->timeout == 0) {
148 channel->timeout = DEFAULT_TIMEOUT;
149 }
150
151 if (channel->tries == 0) {
152 channel->tries = DEFAULT_TRIES;
153 }
154
155 if (channel->ndots == 0) {
156 channel->ndots = 1;
157 }
158
159 if (ares__slist_len(channel->servers) == 0) {
160 /* Add a default local named server to the channel unless configured not
161 * to (in which case return an error).
162 */
163 if (channel->flags & ARES_FLAG_NO_DFLT_SVR) {
164 rc = ARES_ENOSERVER;
165 goto error;
166 }
167
168 addr.family = AF_INET;
169 addr.addr.addr4.s_addr = htonl(INADDR_LOOPBACK);
170
171 rc = ares__sconfig_append(&sconfig, &addr, 0, 0, NULL);
172 if (rc != ARES_SUCCESS) {
173 goto error;
174 }
175
176 rc = ares__servers_update(channel, sconfig, ARES_FALSE);
177 ares__llist_destroy(sconfig);
178
179 if (rc != ARES_SUCCESS) {
180 goto error;
181 }
182 }
183
184 #if defined(USE_WINSOCK)
185 # define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT)
186 #elif defined(ENAMETOOLONG)
187 # define toolong(x) \
188 (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || (SOCKERRNO == EINVAL))
189 #else
190 # define toolong(x) (x == -1) && (SOCKERRNO == EINVAL)
191 #endif
192
193 if (channel->ndomains == 0) {
194 /* Derive a default domain search list from the kernel hostname,
195 * or set it to empty if the hostname isn't helpful.
196 */
197 #ifndef HAVE_GETHOSTNAME
198 channel->ndomains = 0; /* default to none */
199 #else
200 GETHOSTNAME_TYPE_ARG2 lenv = 64;
201 size_t len = 64;
202 int res;
203 channel->ndomains = 0; /* default to none */
204
205 hostname = ares_malloc(len);
206 if (!hostname) {
207 rc = ARES_ENOMEM;
208 goto error;
209 }
210
211 do {
212 res = gethostname(hostname, lenv);
213
214 if (toolong(res)) {
215 char *p;
216 len *= 2;
217 lenv *= 2;
218 p = ares_realloc(hostname, len);
219 if (!p) {
220 rc = ARES_ENOMEM;
221 goto error;
222 }
223 hostname = p;
224 continue;
225 } else if (res) {
226 /* Lets not treat a gethostname failure as critical, since we
227 * are ok if gethostname doesn't even exist */
228 *hostname = '\0';
229 break;
230 }
231
232 } while (res != 0);
233
234 dot = strchr(hostname, '.');
235 if (dot) {
236 /* a dot was found */
237 channel->domains = ares_malloc(sizeof(char *));
238 if (!channel->domains) {
239 rc = ARES_ENOMEM;
240 goto error;
241 }
242 channel->domains[0] = ares_strdup(dot + 1);
243 if (!channel->domains[0]) {
244 rc = ARES_ENOMEM;
245 goto error;
246 }
247 channel->ndomains = 1;
248 }
249 #endif
250 }
251
252 if (channel->nsort == 0) {
253 channel->sortlist = NULL;
254 }
255
256 if (!channel->lookups) {
257 channel->lookups = ares_strdup("fb");
258 if (!channel->lookups) {
259 rc = ARES_ENOMEM;
260 }
261 }
262
263 error:
264 if (rc) {
265 if (channel->domains && channel->domains[0]) {
266 ares_free(channel->domains[0]);
267 }
268 if (channel->domains) {
269 ares_free(channel->domains);
270 channel->domains = NULL;
271 }
272
273 if (channel->lookups) {
274 ares_free(channel->lookups);
275 channel->lookups = NULL;
276 }
277
278 if (channel->resolvconf_path) {
279 ares_free(channel->resolvconf_path);
280 channel->resolvconf_path = NULL;
281 }
282
283 if (channel->hosts_path) {
284 ares_free(channel->hosts_path);
285 channel->hosts_path = NULL;
286 }
287 }
288
289 if (hostname) {
290 ares_free(hostname);
291 }
292
293 return rc;
294 }
295
ares_init_options(ares_channel_t ** channelptr,const struct ares_options * options,int optmask)296 int ares_init_options(ares_channel_t **channelptr,
297 const struct ares_options *options, int optmask)
298 {
299 ares_channel_t *channel;
300 ares_status_t status = ARES_SUCCESS;
301
302 if (ares_library_initialized() != ARES_SUCCESS) {
303 return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
304 }
305
306 channel = ares_malloc_zero(sizeof(*channel));
307 if (!channel) {
308 *channelptr = NULL;
309 return ARES_ENOMEM;
310 }
311
312 status = ares__channel_threading_init(channel);
313 if (status != ARES_SUCCESS) {
314 goto done;
315 }
316
317 /* Generate random key */
318 channel->rand_state = ares__init_rand_state();
319 if (channel->rand_state == NULL) {
320 status = ARES_ENOMEM;
321 DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
322 ares_strerror(status)));
323 goto done;
324 }
325
326 /* Initialize Server List */
327 channel->servers =
328 ares__slist_create(channel->rand_state, server_sort_cb, server_destroy_cb);
329 if (channel->servers == NULL) {
330 status = ARES_ENOMEM;
331 goto done;
332 }
333
334 /* Initialize our lists of queries */
335 channel->all_queries = ares__llist_create(NULL);
336 if (channel->all_queries == NULL) {
337 status = ARES_ENOMEM;
338 goto done;
339 }
340
341 channel->queries_by_qid = ares__htable_szvp_create(NULL);
342 if (channel->queries_by_qid == NULL) {
343 status = ARES_ENOMEM;
344 goto done;
345 }
346
347 channel->queries_by_timeout =
348 ares__slist_create(channel->rand_state, ares_query_timeout_cmp_cb, NULL);
349 if (channel->queries_by_timeout == NULL) {
350 status = ARES_ENOMEM;
351 goto done;
352 }
353
354 channel->connnode_by_socket = ares__htable_asvp_create(NULL);
355 if (channel->connnode_by_socket == NULL) {
356 status = ARES_ENOMEM;
357 goto done;
358 }
359
360 /* Initialize configuration by each of the four sources, from highest
361 * precedence to lowest.
362 */
363
364 status = ares__init_by_options(channel, options, optmask);
365 if (status != ARES_SUCCESS) {
366 DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
367 ares_strerror(status)));
368 /* If we fail to apply user-specified options, fail the whole init process
369 */
370 goto done;
371 }
372
373 if (channel->qcache_max_ttl > 0) {
374 status = ares__qcache_create(channel->rand_state, channel->qcache_max_ttl,
375 &channel->qcache);
376 if (status != ARES_SUCCESS) {
377 goto done;
378 }
379 }
380
381 if (status == ARES_SUCCESS) {
382 status = ares__init_by_sysconfig(channel);
383 if (status != ARES_SUCCESS) {
384 DEBUGF(fprintf(stderr, "Error: init_by_sysconfig failed: %s\n",
385 ares_strerror(status)));
386 }
387 }
388
389 /*
390 * No matter what failed or succeeded, seed defaults to provide
391 * useful behavior for things that we missed.
392 */
393 status = init_by_defaults(channel);
394 if (status != ARES_SUCCESS) {
395 DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
396 ares_strerror(status)));
397 goto done;
398 }
399
400 /* Initialize the event thread */
401 if (channel->optmask & ARES_OPT_EVENT_THREAD) {
402 status = ares_event_thread_init(channel);
403 if (status != ARES_SUCCESS) {
404 goto done;
405 }
406 }
407
408 done:
409 if (status != ARES_SUCCESS) {
410 ares_destroy(channel);
411 return (int)status;
412 }
413
414 *channelptr = channel;
415 return ARES_SUCCESS;
416 }
417
ares_reinit(ares_channel_t * channel)418 ares_status_t ares_reinit(ares_channel_t *channel)
419 {
420 ares_status_t status;
421
422 if (channel == NULL) {
423 return ARES_EFORMERR;
424 }
425
426 ares__channel_lock(channel);
427
428 status = ares__init_by_sysconfig(channel);
429 if (status != ARES_SUCCESS) {
430 DEBUGF(fprintf(stderr, "Error: init_by_sysconfig failed: %s\n",
431 ares_strerror(status)));
432 }
433
434 /* Flush cached queries on reinit */
435 if (channel->qcache) {
436 ares__qcache_flush(channel->qcache);
437 }
438
439 ares__channel_unlock(channel);
440
441 return status;
442 }
443
444 /* ares_dup() duplicates a channel handle with all its options and returns a
445 new channel handle */
ares_dup(ares_channel_t ** dest,ares_channel_t * src)446 int ares_dup(ares_channel_t **dest, ares_channel_t *src)
447 {
448 struct ares_options opts;
449 ares_status_t rc;
450 int optmask;
451
452 if (dest == NULL || src == NULL) {
453 return ARES_EFORMERR;
454 }
455
456 *dest = NULL; /* in case of failure return NULL explicitly */
457
458 ares__channel_lock(src);
459 /* First get the options supported by the old ares_save_options() function,
460 which is most of them */
461 rc = (ares_status_t)ares_save_options(src, &opts, &optmask);
462 if (rc != ARES_SUCCESS) {
463 ares_destroy_options(&opts);
464 goto done;
465 }
466
467 /* Then create the new channel with those options */
468 rc = (ares_status_t)ares_init_options(dest, &opts, optmask);
469
470 /* destroy the options copy to not leak any memory */
471 ares_destroy_options(&opts);
472
473 if (rc != ARES_SUCCESS) {
474 goto done;
475 }
476
477 /* Now clone the options that ares_save_options() doesn't support, but are
478 * user-provided */
479 (*dest)->sock_create_cb = src->sock_create_cb;
480 (*dest)->sock_create_cb_data = src->sock_create_cb_data;
481 (*dest)->sock_config_cb = src->sock_config_cb;
482 (*dest)->sock_config_cb_data = src->sock_config_cb_data;
483 (*dest)->sock_funcs = src->sock_funcs;
484 (*dest)->sock_func_cb_data = src->sock_func_cb_data;
485
486 ares_strcpy((*dest)->local_dev_name, src->local_dev_name,
487 sizeof((*dest)->local_dev_name));
488 (*dest)->local_ip4 = src->local_ip4;
489 memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
490
491
492 /* Servers are a bit unique as ares_init_options() only allows ipv4 servers
493 * and not a port per server, but there are other user specified ways, that
494 * too will toggle the optmask ARES_OPT_SERVERS to let us know. If that's
495 * the case, pull them in.
496 *
497 * We don't want to clone system-configuration servers though.
498 *
499 * We must use the "csv" format to get things like link-local address support
500 */
501
502 if (optmask & ARES_OPT_SERVERS) {
503 char *csv = ares_get_servers_csv(src);
504 if (csv == NULL) {
505 ares_destroy(*dest);
506 *dest = NULL;
507 rc = ARES_ENOMEM;
508 goto done;
509 }
510
511 rc = (ares_status_t)ares_set_servers_ports_csv(*dest, csv);
512 ares_free_string(csv);
513 if (rc != ARES_SUCCESS) {
514 ares_destroy(*dest);
515 *dest = NULL;
516 goto done;
517 }
518 }
519
520 rc = ARES_SUCCESS;
521 done:
522 ares__channel_unlock(src);
523 return (int)rc; /* everything went fine */
524 }
525
ares_set_local_ip4(ares_channel_t * channel,unsigned int local_ip)526 void ares_set_local_ip4(ares_channel_t *channel, unsigned int local_ip)
527 {
528 if (channel == NULL) {
529 return;
530 }
531 ares__channel_lock(channel);
532 channel->local_ip4 = local_ip;
533 ares__channel_unlock(channel);
534 }
535
536 /* local_ip6 should be 16 bytes in length */
ares_set_local_ip6(ares_channel_t * channel,const unsigned char * local_ip6)537 void ares_set_local_ip6(ares_channel_t *channel, const unsigned char *local_ip6)
538 {
539 if (channel == NULL) {
540 return;
541 }
542 ares__channel_lock(channel);
543 memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
544 ares__channel_unlock(channel);
545 }
546
547 /* local_dev_name should be null terminated. */
ares_set_local_dev(ares_channel_t * channel,const char * local_dev_name)548 void ares_set_local_dev(ares_channel_t *channel, const char *local_dev_name)
549 {
550 if (channel == NULL) {
551 return;
552 }
553
554 ares__channel_lock(channel);
555 ares_strcpy(channel->local_dev_name, local_dev_name,
556 sizeof(channel->local_dev_name));
557 channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
558 ares__channel_unlock(channel);
559 }
560
ares_set_sortlist(ares_channel_t * channel,const char * sortstr)561 int ares_set_sortlist(ares_channel_t *channel, const char *sortstr)
562 {
563 size_t nsort = 0;
564 struct apattern *sortlist = NULL;
565 ares_status_t status;
566
567 if (!channel) {
568 return ARES_ENODATA;
569 }
570 ares__channel_lock(channel);
571
572 status = ares__parse_sortlist(&sortlist, &nsort, sortstr);
573 if (status == ARES_SUCCESS && sortlist) {
574 if (channel->sortlist) {
575 ares_free(channel->sortlist);
576 }
577 channel->sortlist = sortlist;
578 channel->nsort = nsort;
579
580 /* Save sortlist as if it was passed in as an option */
581 channel->optmask |= ARES_OPT_SORTLIST;
582 }
583 ares__channel_unlock(channel);
584 return (int)status;
585 }
586