1
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3 * Copyright (C) 2007-2011 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_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27
28 #ifdef HAVE_SYS_SOCKET_H
29 #include <sys/socket.h>
30 #endif
31
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
34 #endif
35
36 #ifdef HAVE_NETDB_H
37 #include <netdb.h>
38 #endif
39
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
43
44 #ifdef HAVE_ARPA_NAMESER_H
45 # include <arpa/nameser.h>
46 #else
47 # include "nameser.h"
48 #endif
49 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
50 # include <arpa/nameser_compat.h>
51 #endif
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <ctype.h>
61 #include <time.h>
62
63 #ifdef ANDROID
64 #include <sys/system_properties.h>
65 #endif
66
67 #include "ares.h"
68 #include "inet_net_pton.h"
69 #include "ares_library_init.h"
70 #include "ares_nowarn.h"
71 #include "ares_platform.h"
72 #include "inet_ntop.h"
73 #include "ares_private.h"
74
75 #ifdef WATT32
76 #undef WIN32 /* Redefined in MingW/MSVC headers */
77 #endif
78
79 static int init_by_options(ares_channel channel, const struct ares_options *options,
80 int optmask);
81 static int init_by_environment(ares_channel channel);
82 static int init_by_resolv_conf(ares_channel channel);
83 static int init_by_defaults(ares_channel channel);
84
85 #ifndef WATT32
86 static int config_nameserver(struct server_state **servers, int *nservers,
87 char *str);
88 #endif
89 static int set_search(ares_channel channel, const char *str);
90 static int set_options(ares_channel channel, const char *str);
91 static const char *try_option(const char *p, const char *q, const char *opt);
92 static int init_id_key(rc4_key* key,int key_data_len);
93
94 #if !defined(WIN32) && !defined(WATT32)
95 static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat);
96 static int ip_addr(const char *s, ssize_t len, struct in_addr *addr);
97 static void natural_mask(struct apattern *pat);
98 static int config_domain(ares_channel channel, char *str);
99 static int config_lookup(ares_channel channel, const char *str,
100 const char *bindch, const char *filech);
101 static int config_sortlist(struct apattern **sortlist, int *nsort,
102 const char *str);
103 static char *try_config(char *s, const char *opt, char scc);
104 #endif
105
106 #define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
107 x->nservers > -1 && \
108 x->ndomains > -1 && \
109 x->ndots > -1 && x->timeout > -1 && \
110 x->tries > -1)
111
ares_init(ares_channel * channelptr)112 int ares_init(ares_channel *channelptr)
113 {
114 return ares_init_options(channelptr, NULL, 0);
115 }
116
ares_init_options(ares_channel * channelptr,struct ares_options * options,int optmask)117 int ares_init_options(ares_channel *channelptr, struct ares_options *options,
118 int optmask)
119 {
120 ares_channel channel;
121 int i;
122 int status = ARES_SUCCESS;
123 struct timeval now;
124
125 #ifdef CURLDEBUG
126 const char *env = getenv("CARES_MEMDEBUG");
127
128 if (env)
129 curl_memdebug(env);
130 env = getenv("CARES_MEMLIMIT");
131 if (env) {
132 char *endptr;
133 long num = strtol(env, &endptr, 10);
134 if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
135 curl_memlimit(num);
136 }
137 #endif
138
139 if (ares_library_initialized() != ARES_SUCCESS)
140 return ARES_ENOTINITIALIZED;
141
142 channel = malloc(sizeof(struct ares_channeldata));
143 if (!channel) {
144 *channelptr = NULL;
145 return ARES_ENOMEM;
146 }
147
148 now = ares__tvnow();
149
150 /* Set everything to distinguished values so we know they haven't
151 * been set yet.
152 */
153 channel->flags = -1;
154 channel->timeout = -1;
155 channel->tries = -1;
156 channel->ndots = -1;
157 channel->rotate = -1;
158 channel->udp_port = -1;
159 channel->tcp_port = -1;
160 channel->socket_send_buffer_size = -1;
161 channel->socket_receive_buffer_size = -1;
162 channel->nservers = -1;
163 channel->ndomains = -1;
164 channel->nsort = -1;
165 channel->tcp_connection_generation = 0;
166 channel->lookups = NULL;
167 channel->domains = NULL;
168 channel->sortlist = NULL;
169 channel->servers = NULL;
170 channel->sock_state_cb = NULL;
171 channel->sock_state_cb_data = NULL;
172 channel->sock_create_cb = NULL;
173 channel->sock_create_cb_data = NULL;
174
175 channel->last_server = 0;
176 channel->last_timeout_processed = (time_t)now.tv_sec;
177
178 memset(&channel->local_dev_name, 0, sizeof(channel->local_dev_name));
179 channel->local_ip4 = 0;
180 memset(&channel->local_ip6, 0, sizeof(channel->local_ip6));
181
182 /* Initialize our lists of queries */
183 ares__init_list_head(&(channel->all_queries));
184 for (i = 0; i < ARES_QID_TABLE_SIZE; i++)
185 {
186 ares__init_list_head(&(channel->queries_by_qid[i]));
187 }
188 for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++)
189 {
190 ares__init_list_head(&(channel->queries_by_timeout[i]));
191 }
192
193 /* Initialize configuration by each of the four sources, from highest
194 * precedence to lowest.
195 */
196
197 if (status == ARES_SUCCESS) {
198 status = init_by_options(channel, options, optmask);
199 if (status != ARES_SUCCESS)
200 DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
201 ares_strerror(status)));
202 }
203 if (status == ARES_SUCCESS) {
204 status = init_by_environment(channel);
205 if (status != ARES_SUCCESS)
206 DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
207 ares_strerror(status)));
208 }
209 if (status == ARES_SUCCESS) {
210 status = init_by_resolv_conf(channel);
211 if (status != ARES_SUCCESS)
212 DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n",
213 ares_strerror(status)));
214 }
215
216 /*
217 * No matter what failed or succeeded, seed defaults to provide
218 * useful behavior for things that we missed.
219 */
220 status = init_by_defaults(channel);
221 if (status != ARES_SUCCESS)
222 DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
223 ares_strerror(status)));
224
225 /* Generate random key */
226
227 if (status == ARES_SUCCESS) {
228 status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
229 if (status == ARES_SUCCESS)
230 channel->next_id = ares__generate_new_id(&channel->id_key);
231 else
232 DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n",
233 ares_strerror(status)));
234 }
235
236 if (status != ARES_SUCCESS)
237 {
238 /* Something failed; clean up memory we may have allocated. */
239 if (channel->servers)
240 free(channel->servers);
241 if (channel->domains)
242 {
243 for (i = 0; i < channel->ndomains; i++)
244 free(channel->domains[i]);
245 free(channel->domains);
246 }
247 if (channel->sortlist)
248 free(channel->sortlist);
249 if(channel->lookups)
250 free(channel->lookups);
251 free(channel);
252 return status;
253 }
254
255 /* Trim to one server if ARES_FLAG_PRIMARY is set. */
256 if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
257 channel->nservers = 1;
258
259 ares__init_servers_state(channel);
260
261 *channelptr = channel;
262 return ARES_SUCCESS;
263 }
264
265 /* ares_dup() duplicates a channel handle with all its options and returns a
266 new channel handle */
ares_dup(ares_channel * dest,ares_channel src)267 int ares_dup(ares_channel *dest, ares_channel src)
268 {
269 struct ares_options opts;
270 struct ares_addr_node *servers;
271 int ipv6_nservers = 0;
272 int i, rc;
273 int optmask;
274
275 *dest = NULL; /* in case of failure return NULL explicitly */
276
277 /* First get the options supported by the old ares_save_options() function,
278 which is most of them */
279 rc = ares_save_options(src, &opts, &optmask);
280 if(rc)
281 return rc;
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
296 strncpy((*dest)->local_dev_name, src->local_dev_name, sizeof(src->local_dev_name));
297 (*dest)->local_ip4 = src->local_ip4;
298 memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
299
300 /* Full name server cloning required when not all are IPv4 */
301 for (i = 0; i < src->nservers; i++)
302 {
303 if (src->servers[i].addr.family != AF_INET) {
304 ipv6_nservers++;
305 break;
306 }
307 }
308 if (ipv6_nservers) {
309 rc = ares_get_servers(src, &servers);
310 if (rc != ARES_SUCCESS)
311 return rc;
312 rc = ares_set_servers(*dest, servers);
313 ares_free_data(servers);
314 if (rc != ARES_SUCCESS)
315 return rc;
316 }
317
318 return ARES_SUCCESS; /* everything went fine */
319 }
320
321 /* Save options from initialized channel */
ares_save_options(ares_channel channel,struct ares_options * options,int * optmask)322 int ares_save_options(ares_channel channel, struct ares_options *options,
323 int *optmask)
324 {
325 int i, j;
326 int ipv4_nservers = 0;
327
328 /* Zero everything out */
329 memset(options, 0, sizeof(struct ares_options));
330
331 if (!ARES_CONFIG_CHECK(channel))
332 return ARES_ENODATA;
333
334 /* Traditionally the optmask wasn't saved in the channel struct so it was
335 recreated here. ROTATE is the first option that has no struct field of
336 its own in the public config struct */
337 (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS|
338 ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
339 ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
340 ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS) |
341 (channel->optmask & ARES_OPT_ROTATE);
342
343 /* Copy easy stuff */
344 options->flags = channel->flags;
345
346 /* We return full millisecond resolution but that's only because we don't
347 set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */
348 options->timeout = channel->timeout;
349 options->tries = channel->tries;
350 options->ndots = channel->ndots;
351 options->udp_port = (unsigned short)channel->udp_port;
352 options->tcp_port = (unsigned short)channel->tcp_port;
353 options->sock_state_cb = channel->sock_state_cb;
354 options->sock_state_cb_data = channel->sock_state_cb_data;
355
356 /* Copy IPv4 servers */
357 if (channel->nservers) {
358 for (i = 0; i < channel->nservers; i++)
359 {
360 if (channel->servers[i].addr.family == AF_INET)
361 ipv4_nservers++;
362 }
363 if (ipv4_nservers) {
364 options->servers = malloc(ipv4_nservers * sizeof(struct in_addr));
365 if (!options->servers)
366 return ARES_ENOMEM;
367 for (i = j = 0; i < channel->nservers; i++)
368 {
369 if (channel->servers[i].addr.family == AF_INET)
370 memcpy(&options->servers[j++],
371 &channel->servers[i].addr.addrV4,
372 sizeof(channel->servers[i].addr.addrV4));
373 }
374 }
375 }
376 options->nservers = ipv4_nservers;
377
378 /* copy domains */
379 if (channel->ndomains) {
380 options->domains = malloc(channel->ndomains * sizeof(char *));
381 if (!options->domains)
382 return ARES_ENOMEM;
383
384 for (i = 0; i < channel->ndomains; i++)
385 {
386 options->ndomains = i;
387 options->domains[i] = strdup(channel->domains[i]);
388 if (!options->domains[i])
389 return ARES_ENOMEM;
390 }
391 }
392 options->ndomains = channel->ndomains;
393
394 /* copy lookups */
395 if (channel->lookups) {
396 options->lookups = strdup(channel->lookups);
397 if (!options->lookups && channel->lookups)
398 return ARES_ENOMEM;
399 }
400
401 /* copy sortlist */
402 if (channel->nsort) {
403 options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
404 if (!options->sortlist)
405 return ARES_ENOMEM;
406 for (i = 0; i < channel->nsort; i++)
407 options->sortlist[i] = channel->sortlist[i];
408 }
409 options->nsort = channel->nsort;
410
411 return ARES_SUCCESS;
412 }
413
init_by_options(ares_channel channel,const struct ares_options * options,int optmask)414 static int init_by_options(ares_channel channel,
415 const struct ares_options *options,
416 int optmask)
417 {
418 int i;
419
420 /* Easy stuff. */
421 if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
422 channel->flags = options->flags;
423 if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1)
424 channel->timeout = options->timeout;
425 else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
426 channel->timeout = options->timeout * 1000;
427 if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
428 channel->tries = options->tries;
429 if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
430 channel->ndots = options->ndots;
431 if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1)
432 channel->rotate = 1;
433 if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
434 channel->udp_port = options->udp_port;
435 if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
436 channel->tcp_port = options->tcp_port;
437 if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL)
438 {
439 channel->sock_state_cb = options->sock_state_cb;
440 channel->sock_state_cb_data = options->sock_state_cb_data;
441 }
442 if ((optmask & ARES_OPT_SOCK_SNDBUF)
443 && channel->socket_send_buffer_size == -1)
444 channel->socket_send_buffer_size = options->socket_send_buffer_size;
445 if ((optmask & ARES_OPT_SOCK_RCVBUF)
446 && channel->socket_receive_buffer_size == -1)
447 channel->socket_receive_buffer_size = options->socket_receive_buffer_size;
448
449 /* Copy the IPv4 servers, if given. */
450 if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
451 {
452 /* Avoid zero size allocations at any cost */
453 if (options->nservers > 0)
454 {
455 channel->servers =
456 malloc(options->nservers * sizeof(struct server_state));
457 if (!channel->servers)
458 return ARES_ENOMEM;
459 for (i = 0; i < options->nservers; i++)
460 {
461 channel->servers[i].addr.family = AF_INET;
462 memcpy(&channel->servers[i].addr.addrV4,
463 &options->servers[i],
464 sizeof(channel->servers[i].addr.addrV4));
465 }
466 }
467 channel->nservers = options->nservers;
468 }
469
470 /* Copy the domains, if given. Keep channel->ndomains consistent so
471 * we can clean up in case of error.
472 */
473 if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
474 {
475 /* Avoid zero size allocations at any cost */
476 if (options->ndomains > 0)
477 {
478 channel->domains = malloc(options->ndomains * sizeof(char *));
479 if (!channel->domains)
480 return ARES_ENOMEM;
481 for (i = 0; i < options->ndomains; i++)
482 {
483 channel->ndomains = i;
484 channel->domains[i] = strdup(options->domains[i]);
485 if (!channel->domains[i])
486 return ARES_ENOMEM;
487 }
488 }
489 channel->ndomains = options->ndomains;
490 }
491
492 /* Set lookups, if given. */
493 if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
494 {
495 channel->lookups = strdup(options->lookups);
496 if (!channel->lookups)
497 return ARES_ENOMEM;
498 }
499
500 /* copy sortlist */
501 if ((optmask & ARES_OPT_SORTLIST) && (channel->nsort == -1) &&
502 (options->nsort>0)) {
503 channel->sortlist = malloc(options->nsort * sizeof(struct apattern));
504 if (!channel->sortlist)
505 return ARES_ENOMEM;
506 for (i = 0; i < options->nsort; i++)
507 channel->sortlist[i] = options->sortlist[i];
508 channel->nsort = options->nsort;
509 }
510
511 channel->optmask = optmask;
512
513 return ARES_SUCCESS;
514 }
515
init_by_environment(ares_channel channel)516 static int init_by_environment(ares_channel channel)
517 {
518 const char *localdomain, *res_options;
519 int status;
520
521 localdomain = getenv("LOCALDOMAIN");
522 if (localdomain && channel->ndomains == -1)
523 {
524 status = set_search(channel, localdomain);
525 if (status != ARES_SUCCESS)
526 return status;
527 }
528
529 res_options = getenv("RES_OPTIONS");
530 if (res_options)
531 {
532 status = set_options(channel, res_options);
533 if (status != ARES_SUCCESS)
534 return status;
535 }
536
537 return ARES_SUCCESS;
538 }
539
540 #ifdef WIN32
541 /*
542 * Warning: returns a dynamically allocated buffer, the user MUST
543 * use free() if the function returns 1
544 */
get_res_nt(HKEY hKey,const char * subkey,char ** obuf)545 static int get_res_nt(HKEY hKey, const char *subkey, char **obuf)
546 {
547 /* Test for the size we need */
548 DWORD size = 0;
549 int result;
550
551 result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
552 if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
553 return 0;
554 *obuf = malloc(size+1);
555 if (!*obuf)
556 return 0;
557
558 if (RegQueryValueEx(hKey, subkey, 0, NULL,
559 (LPBYTE)*obuf, &size) != ERROR_SUCCESS)
560 {
561 free(*obuf);
562 return 0;
563 }
564 if (size == 1)
565 {
566 free(*obuf);
567 return 0;
568 }
569 return 1;
570 }
571
get_res_interfaces_nt(HKEY hKey,const char * subkey,char ** obuf)572 static int get_res_interfaces_nt(HKEY hKey, const char *subkey, char **obuf)
573 {
574 char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */
575 DWORD enum_size = 39;
576 int idx = 0;
577 HKEY hVal;
578
579 while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0,
580 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
581 {
582 int rc;
583
584 enum_size = 39;
585 if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) !=
586 ERROR_SUCCESS)
587 continue;
588 rc = get_res_nt(hVal, subkey, obuf);
589 RegCloseKey(hVal);
590 if (rc)
591 return 1;
592 }
593 return 0;
594 }
595
596 /**
597 * The desired output for this method is that we set "ret_buf" to
598 * something like:
599 *
600 * 192.168.0.1,dns01.my.domain,fe80::200:f8ff:fe21:67cf
601 *
602 * The only ordering requirement is that primary servers are listed
603 * before secondary. There is no requirement that IPv4 addresses should
604 * necessarily be before IPv6.
605 *
606 * Note that ret_size should ideally be big enough to hold around
607 * 2-3 IPv4 and 2-3 IPv6 addresses.
608 *
609 * Finally, we need to return the total number of DNS servers located.
610 */
get_iphlpapi_dns_info(char * ret_buf,size_t ret_size)611 static int get_iphlpapi_dns_info (char *ret_buf, size_t ret_size)
612 {
613 const size_t ipv4_size = INET_ADDRSTRLEN + 1; /* +1 for ',' at end */
614 const size_t ipv6_size = INET6_ADDRSTRLEN + 12; /* +12 for "%0123456789," at end */
615 size_t left = ret_size;
616 char *ret = ret_buf;
617 int count = 0;
618
619 /* Use the GetAdaptersAddresses method if it's available, otherwise
620 fall back to GetNetworkParams. */
621 if (ares_fpGetAdaptersAddresses != ZERO_NULL)
622 {
623 const ULONG working_buf_size = 15000;
624 IP_ADAPTER_ADDRESSES *pFirstEntry = NULL;
625 IP_ADAPTER_ADDRESSES *pEntry = NULL;
626 ULONG bufSize = 0;
627 ULONG result = 0;
628
629 /* According to MSDN, the recommended way to do this is to use a temporary
630 buffer of 15K, to "dramatically reduce the chance that the GetAdaptersAddresses
631 method returns ERROR_BUFFER_OVERFLOW" */
632 pFirstEntry = ( IP_ADAPTER_ADDRESSES * ) malloc( working_buf_size );
633 bufSize = working_buf_size;
634 if( !pFirstEntry )
635 return 0;
636
637 /* Call the method one time */
638 result = ( *ares_fpGetAdaptersAddresses )( AF_UNSPEC, 0, 0, pFirstEntry, &bufSize );
639 if( result == ERROR_BUFFER_OVERFLOW )
640 {
641 /* Reallocate, bufSize should now be set to the required size */
642 pFirstEntry = ( IP_ADAPTER_ADDRESSES * ) realloc( pFirstEntry, bufSize );
643 if( !pFirstEntry )
644 return 0;
645
646 /* Call the method a second time */
647 result = ( *ares_fpGetAdaptersAddresses )( AF_UNSPEC, 0, 0, pFirstEntry, &bufSize );
648 if( result == ERROR_BUFFER_OVERFLOW )
649 {
650 /* Reallocate, bufSize should now be set to the required size */
651 pFirstEntry = ( IP_ADAPTER_ADDRESSES * ) realloc( pFirstEntry, bufSize );
652 if( !pFirstEntry )
653 return 0;
654
655 /* Call the method a third time. The maximum number of times we're going to do
656 this is 3. Three shall be the number thou shalt count, and the number of the
657 counting shall be three. Five is right out. */
658 result = ( *ares_fpGetAdaptersAddresses )( AF_UNSPEC, 0, 0, pFirstEntry, &bufSize );
659 }
660 }
661
662 /* Check the current result for failure */
663 if( result != ERROR_SUCCESS )
664 {
665 free( pFirstEntry );
666 return 0;
667 }
668
669 /* process the results */
670 for( pEntry = pFirstEntry ; pEntry != NULL ; pEntry = pEntry->Next )
671 {
672 IP_ADAPTER_DNS_SERVER_ADDRESS* pDNSAddr = pEntry->FirstDnsServerAddress;
673 for( ; pDNSAddr != NULL ; pDNSAddr = pDNSAddr->Next )
674 {
675 struct sockaddr *pGenericAddr = pDNSAddr->Address.lpSockaddr;
676 size_t stringlen = 0;
677
678 if( pGenericAddr->sa_family == AF_INET && left > ipv4_size )
679 {
680 /* Handle the v4 case */
681 struct sockaddr_in *pIPv4Addr = ( struct sockaddr_in * ) pGenericAddr;
682 ares_inet_ntop( AF_INET, &pIPv4Addr->sin_addr, ret, ipv4_size - 1 ); /* -1 for comma */
683
684 /* Append a comma to the end, THEN NULL. Should be OK because we
685 already tested the size at the top of the if statement. */
686 stringlen = strlen( ret );
687 ret[ stringlen ] = ',';
688 ret[ stringlen + 1 ] = '\0';
689 ret += stringlen + 1;
690 left -= ret - ret_buf;
691 ++count;
692 }
693 else if( pGenericAddr->sa_family == AF_INET6 && left > ipv6_size )
694 {
695 /* Handle the v6 case */
696 struct sockaddr_in6 *pIPv6Addr = ( struct sockaddr_in6 * ) pGenericAddr;
697 ares_inet_ntop( AF_INET6, &pIPv6Addr->sin6_addr, ret, ipv6_size - 1 ); /* -1 for comma */
698
699 /* Append a comma to the end, THEN NULL. Should be OK because we
700 already tested the size at the top of the if statement. */
701 stringlen = strlen( ret );
702 ret[ stringlen ] = ',';
703 ret[ stringlen + 1 ] = '\0';
704 ret += stringlen + 1;
705 left -= ret - ret_buf;
706 ++count;
707
708 /* NB on Windows this also returns stuff in the fec0::/10 range,
709 seems to be hard-coded somehow. Do we need to ignore them? */
710 }
711 }
712 }
713
714 if( pFirstEntry )
715 free( pFirstEntry );
716 if (ret > ret_buf)
717 ret[-1] = '\0';
718 return count;
719 }
720 else
721 {
722 FIXED_INFO *fi, *newfi;
723 DWORD size = sizeof (*fi);
724 IP_ADDR_STRING *ipAddr;
725 int i;
726 int debug = 0;
727 HRESULT res;
728
729 fi = malloc(size);
730 if (!fi)
731 return 0;
732
733 res = (*ares_fpGetNetworkParams) (fi, &size);
734 if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
735 goto quit;
736
737 newfi = realloc(fi, size);
738 if (!newfi)
739 goto quit;
740
741 fi = newfi;
742 res = (*ares_fpGetNetworkParams) (fi, &size);
743 if (res != ERROR_SUCCESS)
744 goto quit;
745
746 if (debug)
747 {
748 printf ("Host Name: %s\n", fi->HostName);
749 printf ("Domain Name: %s\n", fi->DomainName);
750 printf ("DNS Servers:\n"
751 " %s (primary)\n", fi->DnsServerList.IpAddress.String);
752 }
753 if (strlen(fi->DnsServerList.IpAddress.String) > 0 &&
754 inet_addr(fi->DnsServerList.IpAddress.String) != INADDR_NONE &&
755 left > ipv4_size)
756 {
757 ret += sprintf (ret, "%s,", fi->DnsServerList.IpAddress.String);
758 left -= ret - ret_buf;
759 ++count;
760 }
761
762 for (i = 0, ipAddr = fi->DnsServerList.Next; ipAddr && left > ipv4_size;
763 ipAddr = ipAddr->Next, i++)
764 {
765 if (inet_addr(ipAddr->IpAddress.String) != INADDR_NONE)
766 {
767 ret += sprintf (ret, "%s,", ipAddr->IpAddress.String);
768 left -= ret - ret_buf;
769 ++count;
770 }
771 if (debug)
772 printf (" %s (secondary %d)\n", ipAddr->IpAddress.String, i+1);
773 }
774
775 quit:
776 if (fi)
777 free(fi);
778
779 if (debug && left <= ipv4_size)
780 printf ("Too many nameservers. Truncating to %d addressess", count);
781 if (ret > ret_buf)
782 ret[-1] = '\0';
783 return count;
784 }
785 }
786 #endif
787
init_by_resolv_conf(ares_channel channel)788 static int init_by_resolv_conf(ares_channel channel)
789 {
790 #ifndef WATT32
791 char *line = NULL;
792 #endif
793 int status = -1, nservers = 0, nsort = 0;
794 struct server_state *servers = NULL;
795 struct apattern *sortlist = NULL;
796
797 #ifdef WIN32
798
799 /*
800 NameServer info via IPHLPAPI (IP helper API):
801 GetNetworkParams() should be the trusted source for this.
802 Available in Win-98/2000 and later. If that fail, fall-back to
803 registry information.
804
805 NameServer Registry:
806
807 On Windows 9X, the DNS server can be found in:
808 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP\NameServer
809
810 On Windows NT/2000/XP/2003:
811 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\NameServer
812 or
813 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DhcpNameServer
814 or
815 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
816 NameServer
817 or
818 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
819 DhcpNameServer
820 */
821
822 HKEY mykey;
823 HKEY subkey;
824 DWORD data_type;
825 DWORD bytes;
826 DWORD result;
827 char buf[512];
828 win_platform platform;
829
830 if (channel->nservers > -1) /* don't override ARES_OPT_SERVER */
831 return ARES_SUCCESS;
832
833 if (get_iphlpapi_dns_info(buf,sizeof(buf)) > 0)
834 {
835 status = config_nameserver(&servers, &nservers, buf);
836 if (status == ARES_SUCCESS)
837 goto okay;
838 }
839
840 platform = ares__getplatform();
841
842 if (platform == WIN_NT)
843 {
844 if (RegOpenKeyEx(
845 HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
846 KEY_READ, &mykey
847 ) == ERROR_SUCCESS)
848 {
849 RegOpenKeyEx(mykey, "Interfaces", 0,
850 KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey);
851 if (get_res_nt(mykey, NAMESERVER, &line))
852 {
853 status = config_nameserver(&servers, &nservers, line);
854 free(line);
855 }
856 else if (get_res_nt(mykey, DHCPNAMESERVER, &line))
857 {
858 status = config_nameserver(&servers, &nservers, line);
859 free(line);
860 }
861 /* Try the interfaces */
862 else if (get_res_interfaces_nt(subkey, NAMESERVER, &line))
863 {
864 status = config_nameserver(&servers, &nservers, line);
865 free(line);
866 }
867 else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
868 {
869 status = config_nameserver(&servers, &nservers, line);
870 free(line);
871 }
872 RegCloseKey(subkey);
873 RegCloseKey(mykey);
874 }
875 }
876 else if (platform == WIN_9X)
877 {
878 if (RegOpenKeyEx(
879 HKEY_LOCAL_MACHINE, WIN_NS_9X, 0,
880 KEY_READ, &mykey
881 ) == ERROR_SUCCESS)
882 {
883 if ((result = RegQueryValueEx(
884 mykey, NAMESERVER, NULL, &data_type,
885 NULL, &bytes
886 )
887 ) == ERROR_SUCCESS ||
888 result == ERROR_MORE_DATA)
889 {
890 if (bytes)
891 {
892 line = malloc(bytes+1);
893 if (RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type,
894 (unsigned char *)line, &bytes) ==
895 ERROR_SUCCESS)
896 {
897 status = config_nameserver(&servers, &nservers, line);
898 }
899 free(line);
900 }
901 }
902 }
903 RegCloseKey(mykey);
904 }
905
906 if (status == ARES_SUCCESS)
907 status = ARES_EOF;
908 else
909 /* Catch the case when all the above checks fail (which happens when there
910 is no network card or the cable is unplugged) */
911 status = ARES_EFILE;
912
913 #elif defined(__riscos__)
914
915 /* Under RISC OS, name servers are listed in the
916 system variable Inet$Resolvers, space separated. */
917
918 line = getenv("Inet$Resolvers");
919 status = ARES_EOF;
920 if (line) {
921 char *resolvers = strdup(line), *pos, *space;
922
923 if (!resolvers)
924 return ARES_ENOMEM;
925
926 pos = resolvers;
927 do {
928 space = strchr(pos, ' ');
929 if (space)
930 *space = '\0';
931 status = config_nameserver(&servers, &nservers, pos);
932 if (status != ARES_SUCCESS)
933 break;
934 pos = space + 1;
935 } while (space);
936
937 if (status == ARES_SUCCESS)
938 status = ARES_EOF;
939
940 free(resolvers);
941 }
942
943 #elif defined(WATT32)
944 int i;
945
946 sock_init();
947 for (i = 0; def_nameservers[i]; i++)
948 ;
949 if (i == 0)
950 return ARES_SUCCESS; /* use localhost DNS server */
951
952 nservers = i;
953 servers = calloc(i, sizeof(struct server_state));
954 if (!servers)
955 return ARES_ENOMEM;
956
957 for (i = 0; def_nameservers[i]; i++)
958 {
959 servers[i].addr.addrV4.s_addr = htonl(def_nameservers[i]);
960 servers[i].addr.family = AF_INET;
961 }
962 status = ARES_EOF;
963
964 #elif defined(ANDROID)
965 char value[PROP_VALUE_MAX]="";
966 __system_property_get("net.dns1", value);
967 status = config_nameserver(&servers, &nservers, value);
968 if (status == ARES_SUCCESS)
969 status = ARES_EOF;
970 #else
971 {
972 char *p;
973 FILE *fp;
974 size_t linesize;
975 int error;
976
977 /* Don't read resolv.conf and friends if we don't have to */
978 if (ARES_CONFIG_CHECK(channel))
979 return ARES_SUCCESS;
980
981 fp = fopen(PATH_RESOLV_CONF, "r");
982 if (fp) {
983 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
984 {
985 if ((p = try_config(line, "domain", ';')))
986 status = config_domain(channel, p);
987 else if ((p = try_config(line, "lookup", ';')) && !channel->lookups)
988 status = config_lookup(channel, p, "bind", "file");
989 else if ((p = try_config(line, "search", ';')))
990 status = set_search(channel, p);
991 else if ((p = try_config(line, "nameserver", ';')) &&
992 channel->nservers == -1)
993 status = config_nameserver(&servers, &nservers, p);
994 else if ((p = try_config(line, "sortlist", ';')) &&
995 channel->nsort == -1)
996 status = config_sortlist(&sortlist, &nsort, p);
997 else if ((p = try_config(line, "options", ';')))
998 status = set_options(channel, p);
999 else
1000 status = ARES_SUCCESS;
1001 if (status != ARES_SUCCESS)
1002 break;
1003 }
1004 fclose(fp);
1005 }
1006 else {
1007 error = ERRNO;
1008 switch(error) {
1009 case ENOENT:
1010 case ESRCH:
1011 status = ARES_EOF;
1012 break;
1013 default:
1014 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1015 error, strerror(error)));
1016 DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
1017 status = ARES_EFILE;
1018 }
1019 }
1020
1021 if ((status == ARES_EOF) && (!channel->lookups)) {
1022 /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */
1023 fp = fopen("/etc/nsswitch.conf", "r");
1024 if (fp) {
1025 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
1026 {
1027 if ((p = try_config(line, "hosts:", '\0')) && !channel->lookups)
1028 /* ignore errors */
1029 (void)config_lookup(channel, p, "dns", "files");
1030 }
1031 fclose(fp);
1032 }
1033 else {
1034 error = ERRNO;
1035 switch(error) {
1036 case ENOENT:
1037 case ESRCH:
1038 status = ARES_EOF;
1039 break;
1040 default:
1041 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1042 error, strerror(error)));
1043 DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/nsswitch.conf"));
1044 status = ARES_EFILE;
1045 }
1046 }
1047 }
1048
1049 if ((status == ARES_EOF) && (!channel->lookups)) {
1050 /* Linux / GNU libc 2.x and possibly others have host.conf */
1051 fp = fopen("/etc/host.conf", "r");
1052 if (fp) {
1053 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
1054 {
1055 if ((p = try_config(line, "order", '\0')) && !channel->lookups)
1056 /* ignore errors */
1057 (void)config_lookup(channel, p, "bind", "hosts");
1058 }
1059 fclose(fp);
1060 }
1061 else {
1062 error = ERRNO;
1063 switch(error) {
1064 case ENOENT:
1065 case ESRCH:
1066 status = ARES_EOF;
1067 break;
1068 default:
1069 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1070 error, strerror(error)));
1071 DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/host.conf"));
1072 status = ARES_EFILE;
1073 }
1074 }
1075 }
1076
1077 if ((status == ARES_EOF) && (!channel->lookups)) {
1078 /* Tru64 uses /etc/svc.conf */
1079 fp = fopen("/etc/svc.conf", "r");
1080 if (fp) {
1081 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
1082 {
1083 if ((p = try_config(line, "hosts=", '\0')) && !channel->lookups)
1084 /* ignore errors */
1085 (void)config_lookup(channel, p, "bind", "local");
1086 }
1087 fclose(fp);
1088 }
1089 else {
1090 error = ERRNO;
1091 switch(error) {
1092 case ENOENT:
1093 case ESRCH:
1094 status = ARES_EOF;
1095 break;
1096 default:
1097 DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
1098 error, strerror(error)));
1099 DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
1100 status = ARES_EFILE;
1101 }
1102 }
1103 }
1104
1105 if(line)
1106 free(line);
1107 }
1108
1109 #endif
1110
1111 /* Handle errors. */
1112 if (status != ARES_EOF)
1113 {
1114 if (servers != NULL)
1115 free(servers);
1116 if (sortlist != NULL)
1117 free(sortlist);
1118 return status;
1119 }
1120
1121 /* If we got any name server entries, fill them in. */
1122 #ifdef WIN32
1123 okay:
1124 #endif
1125 if (servers)
1126 {
1127 channel->servers = servers;
1128 channel->nservers = nservers;
1129 }
1130
1131 /* If we got any sortlist entries, fill them in. */
1132 if (sortlist)
1133 {
1134 channel->sortlist = sortlist;
1135 channel->nsort = nsort;
1136 }
1137
1138 return ARES_SUCCESS;
1139 }
1140
init_by_defaults(ares_channel channel)1141 static int init_by_defaults(ares_channel channel)
1142 {
1143 char *hostname = NULL;
1144 int rc = ARES_SUCCESS;
1145 #ifdef HAVE_GETHOSTNAME
1146 char *dot;
1147 #endif
1148
1149 if (channel->flags == -1)
1150 channel->flags = 0;
1151 if (channel->timeout == -1)
1152 channel->timeout = DEFAULT_TIMEOUT;
1153 if (channel->tries == -1)
1154 channel->tries = DEFAULT_TRIES;
1155 if (channel->ndots == -1)
1156 channel->ndots = 1;
1157 if (channel->rotate == -1)
1158 channel->rotate = 0;
1159 if (channel->udp_port == -1)
1160 channel->udp_port = htons(NAMESERVER_PORT);
1161 if (channel->tcp_port == -1)
1162 channel->tcp_port = htons(NAMESERVER_PORT);
1163
1164 if (channel->nservers == -1) {
1165 /* If nobody specified servers, try a local named. */
1166 channel->servers = malloc(sizeof(struct server_state));
1167 if (!channel->servers) {
1168 rc = ARES_ENOMEM;
1169 goto error;
1170 }
1171 channel->servers[0].addr.family = AF_INET;
1172 channel->servers[0].addr.addrV4.s_addr = htonl(INADDR_LOOPBACK);
1173 channel->nservers = 1;
1174 }
1175
1176 #if defined(USE_WINSOCK)
1177 #define toolong(x) (x == -1) && (SOCKERRNO == WSAEFAULT)
1178 #elif defined(ENAMETOOLONG)
1179 #define toolong(x) (x == -1) && ((SOCKERRNO == ENAMETOOLONG) || \
1180 (SOCKERRNO == EINVAL))
1181 #else
1182 #define toolong(x) (x == -1) && (SOCKERRNO == EINVAL)
1183 #endif
1184
1185 if (channel->ndomains == -1) {
1186 /* Derive a default domain search list from the kernel hostname,
1187 * or set it to empty if the hostname isn't helpful.
1188 */
1189 size_t len = 64;
1190 int res;
1191 channel->ndomains = 0; /* default to none */
1192
1193 #ifdef HAVE_GETHOSTNAME
1194 hostname = malloc(len);
1195 if(!hostname) {
1196 rc = ARES_ENOMEM;
1197 goto error;
1198 }
1199
1200 do {
1201 res = gethostname(hostname, len);
1202
1203 if(toolong(res)) {
1204 char *p;
1205 len *= 2;
1206 p = realloc(hostname, len);
1207 if(!p) {
1208 rc = ARES_ENOMEM;
1209 goto error;
1210 }
1211 hostname = p;
1212 continue;
1213 }
1214 else if(res) {
1215 rc = ARES_EBADNAME;
1216 goto error;
1217 }
1218
1219 } while(0);
1220
1221 dot = strchr(hostname, '.');
1222 if (dot) {
1223 /* a dot was found */
1224 channel->domains = malloc(sizeof(char *));
1225 if (!channel->domains) {
1226 rc = ARES_ENOMEM;
1227 goto error;
1228 }
1229 channel->domains[0] = strdup(dot + 1);
1230 if (!channel->domains[0]) {
1231 rc = ARES_ENOMEM;
1232 goto error;
1233 }
1234 channel->ndomains = 1;
1235 }
1236 #endif
1237 }
1238
1239 if (channel->nsort == -1) {
1240 channel->sortlist = NULL;
1241 channel->nsort = 0;
1242 }
1243
1244 if (!channel->lookups) {
1245 channel->lookups = strdup("fb");
1246 if (!channel->lookups)
1247 rc = ARES_ENOMEM;
1248 }
1249
1250 error:
1251 if(rc) {
1252 if(channel->servers)
1253 free(channel->servers);
1254
1255 if(channel->domains && channel->domains[0])
1256 free(channel->domains[0]);
1257 if(channel->domains)
1258 free(channel->domains);
1259 if(channel->lookups)
1260 free(channel->lookups);
1261 }
1262
1263 if(hostname)
1264 free(hostname);
1265
1266 return rc;
1267 }
1268
1269 #if !defined(WIN32) && !defined(WATT32)
config_domain(ares_channel channel,char * str)1270 static int config_domain(ares_channel channel, char *str)
1271 {
1272 char *q;
1273
1274 /* Set a single search domain. */
1275 q = str;
1276 while (*q && !ISSPACE(*q))
1277 q++;
1278 *q = '\0';
1279 return set_search(channel, str);
1280 }
1281
1282 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
1283 defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
1284 /* workaround icc 9.1 optimizer issue */
1285 # define vqualifier volatile
1286 #else
1287 # define vqualifier
1288 #endif
1289
config_lookup(ares_channel channel,const char * str,const char * bindch,const char * filech)1290 static int config_lookup(ares_channel channel, const char *str,
1291 const char *bindch, const char *filech)
1292 {
1293 char lookups[3], *l;
1294 const char *vqualifier p;
1295
1296 /* Set the lookup order. Only the first letter of each work
1297 * is relevant, and it has to be "b" for DNS or "f" for the
1298 * host file. Ignore everything else.
1299 */
1300 l = lookups;
1301 p = str;
1302 while (*p)
1303 {
1304 if ((*p == *bindch || *p == *filech) && l < lookups + 2) {
1305 if (*p == *bindch) *l++ = 'b';
1306 else *l++ = 'f';
1307 }
1308 while (*p && !ISSPACE(*p) && (*p != ','))
1309 p++;
1310 while (*p && (ISSPACE(*p) || (*p == ',')))
1311 p++;
1312 }
1313 *l = '\0';
1314 channel->lookups = strdup(lookups);
1315 return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
1316 }
1317 #endif /* !WIN32 & !WATT32 */
1318
1319 #ifndef WATT32
config_nameserver(struct server_state ** servers,int * nservers,char * str)1320 static int config_nameserver(struct server_state **servers, int *nservers,
1321 char *str)
1322 {
1323 struct ares_addr host;
1324 struct server_state *newserv;
1325 char *p, *txtaddr;
1326 /* On Windows, there may be more than one nameserver specified in the same
1327 * registry key, so we parse input as a space or comma seperated list.
1328 */
1329 for (p = str; p;)
1330 {
1331 /* Skip whitespace and commas. */
1332 while (*p && (ISSPACE(*p) || (*p == ',')))
1333 p++;
1334 if (!*p)
1335 /* No more input, done. */
1336 break;
1337
1338 /* Pointer to start of IPv4 or IPv6 address part. */
1339 txtaddr = p;
1340
1341 /* Advance past this address. */
1342 while (*p && !ISSPACE(*p) && (*p != ','))
1343 p++;
1344 if (*p)
1345 /* Null terminate this address. */
1346 *p++ = '\0';
1347 else
1348 /* Reached end of input, done when this address is processed. */
1349 p = NULL;
1350
1351 /* Convert textual address to binary format. */
1352 if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
1353 host.family = AF_INET;
1354 else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1)
1355 host.family = AF_INET6;
1356 else
1357 continue;
1358
1359 /* Resize servers state array. */
1360 newserv = realloc(*servers, (*nservers + 1) *
1361 sizeof(struct server_state));
1362 if (!newserv)
1363 return ARES_ENOMEM;
1364
1365 /* Store address data. */
1366 newserv[*nservers].addr.family = host.family;
1367 if (host.family == AF_INET)
1368 memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
1369 sizeof(host.addrV4));
1370 else
1371 memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
1372 sizeof(host.addrV6));
1373
1374 /* Update arguments. */
1375 *servers = newserv;
1376 *nservers += 1;
1377 }
1378
1379 return ARES_SUCCESS;
1380 }
1381
1382 #ifndef WIN32
config_sortlist(struct apattern ** sortlist,int * nsort,const char * str)1383 static int config_sortlist(struct apattern **sortlist, int *nsort,
1384 const char *str)
1385 {
1386 struct apattern pat;
1387 const char *q;
1388
1389 /* Add sortlist entries. */
1390 while (*str && *str != ';')
1391 {
1392 int bits;
1393 char ipbuf[16], ipbufpfx[32];
1394 /* Find just the IP */
1395 q = str;
1396 while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
1397 q++;
1398 memcpy(ipbuf, str, q-str);
1399 ipbuf[q-str] = '\0';
1400 /* Find the prefix */
1401 if (*q == '/')
1402 {
1403 const char *str2 = q+1;
1404 while (*q && *q != ';' && !ISSPACE(*q))
1405 q++;
1406 memcpy(ipbufpfx, str, q-str);
1407 ipbufpfx[q-str] = '\0';
1408 str = str2;
1409 }
1410 else
1411 ipbufpfx[0] = '\0';
1412 /* Lets see if it is CIDR */
1413 /* First we'll try IPv6 */
1414 if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf,
1415 &pat.addrV6,
1416 sizeof(pat.addrV6))) > 0)
1417 {
1418 pat.type = PATTERN_CIDR;
1419 pat.mask.bits = (unsigned short)bits;
1420 pat.family = AF_INET6;
1421 if (!sortlist_alloc(sortlist, nsort, &pat))
1422 return ARES_ENOMEM;
1423 }
1424 else if (ipbufpfx[0] &&
1425 (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4,
1426 sizeof(pat.addrV4))) > 0)
1427 {
1428 pat.type = PATTERN_CIDR;
1429 pat.mask.bits = (unsigned short)bits;
1430 pat.family = AF_INET;
1431 if (!sortlist_alloc(sortlist, nsort, &pat))
1432 return ARES_ENOMEM;
1433 }
1434 /* See if it is just a regular IP */
1435 else if (ip_addr(ipbuf, q-str, &pat.addrV4) == 0)
1436 {
1437 if (ipbufpfx[0])
1438 {
1439 memcpy(ipbuf, str, q-str);
1440 ipbuf[q-str] = '\0';
1441 if (ip_addr(ipbuf, q-str, &pat.mask.addr4) != 0)
1442 natural_mask(&pat);
1443 }
1444 else
1445 natural_mask(&pat);
1446 pat.family = AF_INET;
1447 pat.type = PATTERN_MASK;
1448 if (!sortlist_alloc(sortlist, nsort, &pat))
1449 return ARES_ENOMEM;
1450 }
1451 else
1452 {
1453 while (*q && *q != ';' && !ISSPACE(*q))
1454 q++;
1455 }
1456 str = q;
1457 while (ISSPACE(*str))
1458 str++;
1459 }
1460
1461 return ARES_SUCCESS;
1462 }
1463 #endif /* !WIN32 */
1464 #endif /* !WATT32 */
1465
set_search(ares_channel channel,const char * str)1466 static int set_search(ares_channel channel, const char *str)
1467 {
1468 int n;
1469 const char *p, *q;
1470
1471 if(channel->ndomains != -1) {
1472 /* if we already have some domains present, free them first */
1473 for(n=0; n < channel->ndomains; n++)
1474 free(channel->domains[n]);
1475 free(channel->domains);
1476 channel->domains = NULL;
1477 channel->ndomains = -1;
1478 }
1479
1480 /* Count the domains given. */
1481 n = 0;
1482 p = str;
1483 while (*p)
1484 {
1485 while (*p && !ISSPACE(*p))
1486 p++;
1487 while (ISSPACE(*p))
1488 p++;
1489 n++;
1490 }
1491
1492 if (!n)
1493 {
1494 channel->ndomains = 0;
1495 return ARES_SUCCESS;
1496 }
1497
1498 channel->domains = malloc(n * sizeof(char *));
1499 if (!channel->domains)
1500 return ARES_ENOMEM;
1501
1502 /* Now copy the domains. */
1503 n = 0;
1504 p = str;
1505 while (*p)
1506 {
1507 channel->ndomains = n;
1508 q = p;
1509 while (*q && !ISSPACE(*q))
1510 q++;
1511 channel->domains[n] = malloc(q - p + 1);
1512 if (!channel->domains[n])
1513 return ARES_ENOMEM;
1514 memcpy(channel->domains[n], p, q - p);
1515 channel->domains[n][q - p] = 0;
1516 p = q;
1517 while (ISSPACE(*p))
1518 p++;
1519 n++;
1520 }
1521 channel->ndomains = n;
1522
1523 return ARES_SUCCESS;
1524 }
1525
set_options(ares_channel channel,const char * str)1526 static int set_options(ares_channel channel, const char *str)
1527 {
1528 const char *p, *q, *val;
1529
1530 p = str;
1531 while (*p)
1532 {
1533 q = p;
1534 while (*q && !ISSPACE(*q))
1535 q++;
1536 val = try_option(p, q, "ndots:");
1537 if (val && channel->ndots == -1)
1538 channel->ndots = aresx_sltosi(strtol(val, NULL, 10));
1539 val = try_option(p, q, "retrans:");
1540 if (val && channel->timeout == -1)
1541 channel->timeout = aresx_sltosi(strtol(val, NULL, 10));
1542 val = try_option(p, q, "retry:");
1543 if (val && channel->tries == -1)
1544 channel->tries = aresx_sltosi(strtol(val, NULL, 10));
1545 val = try_option(p, q, "rotate");
1546 if (val && channel->rotate == -1)
1547 channel->rotate = 1;
1548 p = q;
1549 while (ISSPACE(*p))
1550 p++;
1551 }
1552
1553 return ARES_SUCCESS;
1554 }
1555
try_option(const char * p,const char * q,const char * opt)1556 static const char *try_option(const char *p, const char *q, const char *opt)
1557 {
1558 size_t len = strlen(opt);
1559 return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL;
1560 }
1561
1562 #if !defined(WIN32) && !defined(WATT32)
try_config(char * s,const char * opt,char scc)1563 static char *try_config(char *s, const char *opt, char scc)
1564 {
1565 size_t len;
1566 char *p;
1567 char *q;
1568
1569 if (!s || !opt)
1570 /* no line or no option */
1571 return NULL;
1572
1573 /* Hash '#' character is always used as primary comment char, additionally
1574 a not-NUL secondary comment char will be considered when specified. */
1575
1576 /* trim line comment */
1577 p = s;
1578 if(scc)
1579 while (*p && (*p != '#') && (*p != scc))
1580 p++;
1581 else
1582 while (*p && (*p != '#'))
1583 p++;
1584 *p = '\0';
1585
1586 /* trim trailing whitespace */
1587 q = p - 1;
1588 while ((q >= s) && ISSPACE(*q))
1589 q--;
1590 *++q = '\0';
1591
1592 /* skip leading whitespace */
1593 p = s;
1594 while (*p && ISSPACE(*p))
1595 p++;
1596
1597 if (!*p)
1598 /* empty line */
1599 return NULL;
1600
1601 if ((len = strlen(opt)) == 0)
1602 /* empty option */
1603 return NULL;
1604
1605 if (strncmp(p, opt, len) != 0)
1606 /* line and option do not match */
1607 return NULL;
1608
1609 /* skip over given option name */
1610 p += len;
1611
1612 if (!*p)
1613 /* no option value */
1614 return NULL;
1615
1616 if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p))
1617 /* whitespace between option name and value is mandatory
1618 for given option names which do not end with ':' or '=' */
1619 return NULL;
1620
1621 /* skip over whitespace */
1622 while (*p && ISSPACE(*p))
1623 p++;
1624
1625 if (!*p)
1626 /* no option value */
1627 return NULL;
1628
1629 /* return pointer to option value */
1630 return p;
1631 }
1632
sortlist_alloc(struct apattern ** sortlist,int * nsort,struct apattern * pat)1633 static int sortlist_alloc(struct apattern **sortlist, int *nsort,
1634 struct apattern *pat)
1635 {
1636 struct apattern *newsort;
1637 newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
1638 if (!newsort)
1639 return 0;
1640 newsort[*nsort] = *pat;
1641 *sortlist = newsort;
1642 (*nsort)++;
1643 return 1;
1644 }
1645
ip_addr(const char * ipbuf,ssize_t len,struct in_addr * addr)1646 static int ip_addr(const char *ipbuf, ssize_t len, struct in_addr *addr)
1647 {
1648
1649 /* Four octets and three periods yields at most 15 characters. */
1650 if (len > 15)
1651 return -1;
1652
1653 addr->s_addr = inet_addr(ipbuf);
1654 if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
1655 return -1;
1656 return 0;
1657 }
1658
natural_mask(struct apattern * pat)1659 static void natural_mask(struct apattern *pat)
1660 {
1661 struct in_addr addr;
1662
1663 /* Store a host-byte-order copy of pat in a struct in_addr. Icky,
1664 * but portable.
1665 */
1666 addr.s_addr = ntohl(pat->addrV4.s_addr);
1667
1668 /* This is out of date in the CIDR world, but some people might
1669 * still rely on it.
1670 */
1671 if (IN_CLASSA(addr.s_addr))
1672 pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET);
1673 else if (IN_CLASSB(addr.s_addr))
1674 pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET);
1675 else
1676 pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET);
1677 }
1678 #endif /* !WIN32 && !WATT32 */
1679
1680 /* initialize an rc4 key. If possible a cryptographically secure random key
1681 is generated using a suitable function (for example win32's RtlGenRandom as
1682 described in
1683 http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
1684 otherwise the code defaults to cross-platform albeit less secure mechanism
1685 using rand
1686 */
randomize_key(unsigned char * key,int key_data_len)1687 static void randomize_key(unsigned char* key,int key_data_len)
1688 {
1689 int randomized = 0;
1690 int counter=0;
1691 #ifdef WIN32
1692 BOOLEAN res;
1693 if (ares_fpSystemFunction036)
1694 {
1695 res = (*ares_fpSystemFunction036) (key, key_data_len);
1696 if (res)
1697 randomized = 1;
1698 }
1699 #else /* !WIN32 */
1700 #ifdef RANDOM_FILE
1701 FILE *f = fopen(RANDOM_FILE, "rb");
1702 if(f) {
1703 counter = aresx_uztosi(fread(key, 1, key_data_len, f));
1704 fclose(f);
1705 }
1706 #endif
1707 #endif /* WIN32 */
1708
1709 if ( !randomized ) {
1710 for (;counter<key_data_len;counter++)
1711 key[counter]=(unsigned char)(rand() % 256);
1712 }
1713 }
1714
init_id_key(rc4_key * key,int key_data_len)1715 static int init_id_key(rc4_key* key,int key_data_len)
1716 {
1717 unsigned char index1;
1718 unsigned char index2;
1719 unsigned char* state;
1720 short counter;
1721 unsigned char *key_data_ptr = 0;
1722
1723 key_data_ptr = calloc(1,key_data_len);
1724 if (!key_data_ptr)
1725 return ARES_ENOMEM;
1726
1727 state = &key->state[0];
1728 for(counter = 0; counter < 256; counter++)
1729 /* unnecessary AND but it keeps some compilers happier */
1730 state[counter] = (unsigned char)(counter & 0xff);
1731 randomize_key(key->state,key_data_len);
1732 key->x = 0;
1733 key->y = 0;
1734 index1 = 0;
1735 index2 = 0;
1736 for(counter = 0; counter < 256; counter++)
1737 {
1738 index2 = (unsigned char)((key_data_ptr[index1] + state[counter] +
1739 index2) % 256);
1740 ARES_SWAP_BYTE(&state[counter], &state[index2]);
1741
1742 index1 = (unsigned char)((index1 + 1) % key_data_len);
1743 }
1744 free(key_data_ptr);
1745 return ARES_SUCCESS;
1746 }
1747
ares__generate_new_id(rc4_key * key)1748 unsigned short ares__generate_new_id(rc4_key* key)
1749 {
1750 unsigned short r=0;
1751 ares__rc4(key, (unsigned char *)&r, sizeof(r));
1752 return r;
1753 }
1754
ares_set_local_ip4(ares_channel channel,unsigned int local_ip)1755 void ares_set_local_ip4(ares_channel channel, unsigned int local_ip)
1756 {
1757 channel->local_ip4 = local_ip;
1758 }
1759
1760 /* local_ip6 should be 16 bytes in length */
ares_set_local_ip6(ares_channel channel,const unsigned char * local_ip6)1761 void ares_set_local_ip6(ares_channel channel,
1762 const unsigned char* local_ip6)
1763 {
1764 memcpy(&channel->local_ip6, local_ip6, sizeof(channel->local_ip6));
1765 }
1766
1767 /* local_dev_name should be null terminated. */
ares_set_local_dev(ares_channel channel,const char * local_dev_name)1768 void ares_set_local_dev(ares_channel channel,
1769 const char* local_dev_name)
1770 {
1771 strncpy(channel->local_dev_name, local_dev_name,
1772 sizeof(channel->local_dev_name));
1773 channel->local_dev_name[sizeof(channel->local_dev_name) - 1] = 0;
1774 }
1775
1776
ares_set_socket_callback(ares_channel channel,ares_sock_create_callback cb,void * data)1777 void ares_set_socket_callback(ares_channel channel,
1778 ares_sock_create_callback cb,
1779 void *data)
1780 {
1781 channel->sock_create_cb = cb;
1782 channel->sock_create_cb_data = data;
1783 }
1784
ares__init_servers_state(ares_channel channel)1785 void ares__init_servers_state(ares_channel channel)
1786 {
1787 struct server_state *server;
1788 int i;
1789
1790 for (i = 0; i < channel->nservers; i++)
1791 {
1792 server = &channel->servers[i];
1793 server->udp_socket = ARES_SOCKET_BAD;
1794 server->tcp_socket = ARES_SOCKET_BAD;
1795 server->tcp_connection_generation = ++channel->tcp_connection_generation;
1796 server->tcp_lenbuf_pos = 0;
1797 server->tcp_buffer_pos = 0;
1798 server->tcp_buffer = NULL;
1799 server->tcp_length = 0;
1800 server->qhead = NULL;
1801 server->qtail = NULL;
1802 ares__init_list_head(&server->queries_to_server);
1803 server->channel = channel;
1804 server->is_broken = 0;
1805 }
1806 }
1807