reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ares_init.c
Go to the documentation of this file.
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
14 */
15
16#ifdef HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <sys/types.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <ctype.h>
25#include <time.h>
26#include "rutil/ResipAssert.h"
27
28#ifndef WIN32
29#include <sys/time.h>
30#include <sys/param.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#include <sys/socket.h>
34#ifndef __CYGWIN__
35# include "ares_nameser.h"
36#endif
37#include <unistd.h>
38#include <errno.h>
39#include <netdb.h>
40#else
41#include <Winsock2.h>
42#include <iphlpapi.h>
43#include <io.h>
44#include <Windns.h>
45#endif
46
47#ifdef __ANDROID__
48#include <sys/system_properties.h>
49#endif
50
51#include "ares.h"
52#include "ares_private.h"
53
54#if defined(__APPLE__) || defined(__MACH__)
55#include <TargetConditionals.h>
56#define __CF_USE_FRAMEWORK_INCLUDES__
57#include <SystemConfiguration/SystemConfiguration.h>
58#endif
59
60static int init_by_options(ares_channel channel, struct ares_options *options,
61 int optmask);
62static int init_by_environment(ares_channel channel);
63static int init_by_resolv_conf(ares_channel channel);
64static int init_by_defaults(ares_channel channel);
65static int config_domain(ares_channel channel, char *str);
66static int config_lookup(ares_channel channel, const char *str);
67static int config_nameserver(struct server_state **servers, int *nservers,
68 const char *str);
69static int config_sortlist(struct apattern **sortlist, int *nsort,
70 const char *str);
71static int set_search(ares_channel channel, const char *str);
72static int set_options(ares_channel channel, const char *str);
73static char *try_config(char *s, char *opt);
74static const char *try_option(const char *p, const char *q, const char *opt);
75static int ip_addr(const char *s, int len, struct in_addr *addr);
76static void natural_mask(struct apattern *pat);
77#ifdef WIN32
78static int find_server(struct server_state *servers, int nservers, struct in_addr addr);
79#ifdef USE_IPV6
80static int find_server6(struct server_state *servers, int nservers, struct in6_addr addr);
81#endif
82#endif
83
84static int inet_pton4(const char *src, u_char *dst);
85#ifdef USE_IPV6
86static int inet_pton6(const char *src, u_char *dst);
87#endif
88
89#ifdef WIN32
90char w32hostspath[256];
91#endif
92
93
95{
96#ifdef USE_IPV6
97 static int ares_caps = ARES_CAP_IPV6;
98#else
99 static int ares_caps = 0;
100#endif
101 return (capmask & ares_caps);
102}
103
108
113
119
122{
123 ares_channel channel;
124 int i, status;
125 struct server_state* server;
126#if defined(WIN32) && !defined(_M_ARM)
127 {
128 HKEY hKey;
129 char hostpath[256];
130 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
131 {
132 DWORD dwSize = sizeof(hostpath);
133 if (RegQueryValueEx(hKey, TEXT("DatabasePath"), 0, 0, (LPBYTE)&hostpath, &dwSize) == ERROR_SUCCESS)
134 {
135 hostpath[dwSize] = '\0';
136#if defined(UNDER_CE)
138#else
140#endif
141 if (strlen(w32hostspath) < sizeof(w32hostspath) - 6)
142 {
145 "\\hosts");
146 }
147 }
149 }
150 }
151#endif
152 // struct timeval tv;
153
154 channel = malloc(sizeof(struct ares_channeldata));
155 if (!channel)
156 return ARES_ENOMEM;
157
158 /* Set everything to distinguished values so we know they haven't
159 * been set yet.
160 */
161 channel->socket_function = socketFunc;
162 channel->poll_cb_func = NULL;
163 channel->poll_cb_data = NULL;
164 channel->flags = -1;
165 channel->timeout = -1;
166 channel->tries = -1;
167 channel->ndots = -1;
168 channel->udp_port = -1;
169 channel->tcp_port = -1;
170 channel->nservers = -1;
171 channel->ndomains = -1;
172 channel->nsort = -1;
173 channel->lookups = NULL;
174 channel->servers = NULL;
175
176 /* Initialize configuration by each of the four sources, from highest
177 * precedence to lowest.
178 */
179 status = init_by_options(channel, options, optmask);
180 if (status == ARES_SUCCESS)
181 status = init_by_environment(channel);
182 if (status == ARES_SUCCESS)
183 status = init_by_resolv_conf(channel);
184 if (status == ARES_SUCCESS)
185 status = init_by_defaults(channel);
186 if (status != ARES_SUCCESS)
187 {
188 /* Something failed; clean up memory we may have allocated. */
189 if (channel->nservers != -1)
190 free(channel->servers);
191 if (channel->ndomains != -1)
192 {
193 for (i = 0; i < channel->ndomains; i++)
194 free(channel->domains[i]);
195 free(channel->domains);
196 }
197 if (channel->nsort != -1)
198 free(channel->sortlist);
199 free(channel->lookups);
200 free(channel);
201 return status;
202 }
203
204 /* Trim to one server if ARES_FLAG_PRIMARY is set. */
205 if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
206 channel->nservers = 1;
207
208 /* Initialize server states. */
209 for (i = 0; i < channel->nservers; i++)
210 {
211 server = &channel->servers[i];
212 server->udp_socket = -1;
213 server->tcp_socket = -1;
214 server->tcp_lenbuf_pos = 0;
215 server->tcp_buffer = NULL;
216 server->qhead = NULL;
217 server->qtail = NULL;
218 }
219
220 /* Choose a somewhat random query ID. The main point is to avoid
221 * collisions with stale queries. An attacker trying to spoof a DNS
222 * answer also has to guess the query ID, but it's only a 16-bit
223 * field, so there's not much to be done about that.
224 */
225 // gettimeofday(&tv, NULL);
226 // channel->next_id = (tv.tv_sec ^ tv.tv_usec ^ getpid()) & 0xffff;
227 {
228 static int cjNextID = 1;
229 channel->next_id = cjNextID++;
230 }
231
232 channel->queries = NULL;
233
234 *channelptr = channel;
235 return ARES_SUCCESS;
236}
237
239 int optmask)
240{
241 int i;
242
243 /* Easy stuff. */
244 if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
245 channel->flags = options->flags;
246 if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
247 channel->timeout = options->timeout;
248 if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
249 channel->tries = options->tries;
250 if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
251 channel->ndots = options->ndots;
252 if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
253 channel->udp_port = options->udp_port;
254 if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
255 channel->tcp_port = options->tcp_port;
256
257 /* Copy the servers, if given. */
258 if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1 && options->nservers > 0)
259 {
260 channel->servers = malloc(options->nservers * sizeof(struct server_state));
261 if (channel->servers == NULL)
262 return ARES_ENOMEM;
263 memset(channel->servers, '\0', options->nservers * sizeof(struct server_state));
264 for (i = 0; i < options->nservers; i++)
265 {
266#ifdef USE_IPV6
267 channel->servers[i].family = options->servers[i].family;
268 if (options->servers[i].family == AF_INET6)
269 {
270 channel->servers[i].addr6 = options->servers[i].addr6;
271 }
272 else
273 {
274 resip_assert(channel->servers[i].family == AF_INET);
275 channel->servers[i].addr = options->servers[i].addr;
276 }
277#else
278 channel->servers[i].addr = options->servers[i];
279#endif
280 }
281 channel->nservers = options->nservers;
282 }
283
284 /* Copy the domains, if given. Keep channel->ndomains consistent so
285 * we can clean up in case of error.
286 */
287 if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
288 {
289 channel->domains = malloc(options->ndomains * sizeof(char*));
290 if (!channel->domains && options->ndomains != 0)
291 return ARES_ENOMEM;
292 for (i = 0; i < options->ndomains; i++)
293 {
294 channel->ndomains = i;
295 channel->domains[i] = strdup(options->domains[i]);
296 if (!channel->domains[i])
297 return ARES_ENOMEM;
298 }
299 channel->ndomains = options->ndomains;
300 }
301
302 /* Set lookups, if given. */
303 if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
304 {
305 channel->lookups = strdup(options->lookups);
306 if (!channel->lookups)
307 return ARES_ENOMEM;
308 }
309
310 return ARES_SUCCESS;
311}
312
314{
315 const char* localdomain, * res_options;
316 int status;
317
318#if defined(UNDER_CE)
321#elif defined(_MSC_VER)
322 char localdomainBuf[256] = { 0 };
323 char resoptionsBuf[256] = { 0 };
324 size_t requiredSize = 0;
325
326 getenv_s(&requiredSize, localdomainBuf, sizeof(localdomainBuf), "LOCALDOMAIN");
328
329 requiredSize = 0;
330 getenv_s(&requiredSize, resoptionsBuf, sizeof(resoptionsBuf), "RES_OPTIONS");
332#else
333 localdomain = getenv("LOCALDOMAIN");
334 res_options = getenv("RES_OPTIONS");
335#endif
336
337 if (localdomain && channel->ndomains == -1)
338 {
339 status = set_search(channel, localdomain);
340 if (status != ARES_SUCCESS)
341 return status;
342 }
343
344 if (res_options)
345 {
346 status = set_options(channel, res_options);
347 if (status != ARES_SUCCESS)
348 return status;
349 }
350 return ARES_SUCCESS;
351}
352
354{
355 FILE* fp;
356 char* line = NULL, * p;
357 int linesize, status, nservers = 0, nsort = 0;
358 struct server_state* servers = NULL;
359 struct apattern* sortlist = NULL;
360
361#ifdef WIN32
363#else
364 fp = fopen(PATH_RESOLV_CONF, "r");
365#endif
366#if defined(UNDER_CE)
367 errno = ENOENT;
368#endif
369 if (!fp)
370 return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
371 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
372 {
373 if ((p = try_config(line, "domain")) && channel->ndomains == -1)
374 status = config_domain(channel, p);
375 else if ((p = try_config(line, "lookup")) && !channel->lookups)
376 status = config_lookup(channel, p);
377 else if ((p = try_config(line, "search")) && channel->ndomains == -1)
378 status = set_search(channel, p);
379 else if ((p = try_config(line, "nameserver")) && channel->nservers == -1)
380 status = config_nameserver(&servers, &nservers, p);
381 else if ((p = try_config(line, "sortlist")) && channel->nsort == -1)
382 status = config_sortlist(&sortlist, &nsort, p);
383 else if ((p = try_config(line, "options")))
384 status = set_options(channel, p);
385 else
386 status = ARES_SUCCESS;
387 if (status != ARES_SUCCESS)
388 break;
389 }
390 free(line);
391 fclose(fp);
392
393 /* Handle errors. */
394 if (status != ARES_EOF)
395 {
396 free(servers);
397 free(sortlist);
398 return status;
399 }
400
401 /* If we got any name server entries, fill them in. */
402 if (servers)
403 {
404 channel->servers = servers;
405 channel->nservers = nservers;
406 }
407
408 /* If we got any sortlist entries, fill them in. */
409 if (sortlist)
410 {
411 channel->sortlist = sortlist;
412 channel->nsort = nsort;
413 }
414
415 return ARES_SUCCESS;
416}
417
418#if defined(__APPLE__) || defined(__MACH__)
420{
423
424 channel->nservers = 0;
425 // .amr. iPhone/iOS SDK's don't support SCDynamicStoreCreate so in that case fall back
426 // to the nservers=0 case.
427#if !TARGET_OS_IPHONE
428 store = SCDynamicStoreCreate(NULL, CFSTR("init_by_defaults_apple_nameservers"), NULL, &context);
429
430 if (store)
431 {
432 // kSCDynamicStoreDomainState/kSCCompNetwork/kSCCompGlobal/kSCEntNetDNS
433 CFStringRef key = CFSTR("State:/Network/Global/DNS");
435
436 if (dnsDict)
437 {
439 if (addresses)
440 {
441 //CFShow(addresses);
443 channel->servers = malloc(channel->nservers * sizeof(struct server_state));
444 memset(channel->servers, '\0', channel->nservers * sizeof(struct server_state));
445
446 int i;
447 for (i = 0; i < channel->nservers; i++)
448 {
450 //CFShow(address);
451 const int kBufferSize = 20;
452 char str[kBufferSize];
453
455 inet_pton4(str, (u_char*)&channel->servers[i].addr);
456#ifdef USE_IPV6
457 channel->servers[i].family = AF_INET;
458#endif
459 }
460 }
461
463 }
464
466 }
467#endif // TARGET_OS_IPHONE
468}
469#endif
470
471#if defined(__ANDROID__)
473{
474 int android_prop_found = 0;
475 char props_dns[2][PROP_VALUE_MAX];
477 const char *prop_keys[2] = { "net.dns1", "net.dns2" };
478 int i = 0, j = 0;
479
480 for(i = 0; i < 2; i++)
481 {
484 if(prop != NULL)
485 {
487 if(props_dns[android_prop_found][0] != 0)
489 }
490 }
491 if(android_prop_found > 0)
492 {
493 channel->servers = malloc( (android_prop_found) * sizeof(struct server_state));
494 if (!channel->servers)
495 {
496 return ARES_ENOMEM;
497 }
498 memset(channel->servers, '\0', android_prop_found * sizeof(struct server_state));
499
500 for(i = 0; i < android_prop_found; i++)
501 {
502 int rc = inet_pton(AF_INET, props_dns[i], &channel->servers[j].addr.s_addr);
503 if(rc == 1)
504 {
505#ifdef USE_IPV6
506 channel->servers[j].family = AF_INET;
507#endif
508 j++;
509 }
510#ifdef USE_IPV6
511 else
512 {
513 rc = inet_pton(AF_INET6, props_dns[i], &channel->servers[j].addr6.s6_addr);
514 if(rc == 1)
515 {
516 channel->servers[j].family = AF_INET6;
517 j++;
518 }
519 }
520#endif
521 }
522 // how many really are valid IP addresses?
523 channel->nservers = j;
524 }
525 return ARES_SUCCESS;
526}
527#endif
528
529#ifdef WIN32
531{
533 HANDLE hLib = 0;
535 DWORD dwSize = 0;
536 int trys = 0;
538 int rc = ARES_ENOTFOUND;
539 int loopnum = 0;
540 int numreturned = 0;
541
542 hLib = LoadLibrary(TEXT("iphlpapi.dll"));
543 if (!hLib)
544 {
545 return ARES_ENOTIMP;
546 }
547
548 (void*)GetAdaptersAddressesProc = GetProcAddress(hLib, TEXT("GetAdaptersAddresses"));
550 {
552 goto cleanup;
553 }
554
555 // Allocate 15kb of buffer to avoid calling twice - recommended in MSDN
556 dwSize = 15 * 1024;
559 {
560 rc = ARES_ENOMEM;
561 goto cleanup;
562 }
563
565 {
568 {
569 rc = ARES_ENOMEM;
570 goto cleanup;
571 }
572 }
573 if( dwRet != 0)
574 {
576 goto cleanup;
577 }
578
579 // We have some data - process it
580 // We walk the data twice - the first time is to figure out how many DNS servers there are so that we can allocate
581 // the channel memory. Note: If there are duplicates we may end up allocating more memory than we use - but that is fine.
582 // The seconds walk through the data we add the actual DNS servers to the channel structure
583 while(++loopnum <= 2)
584 {
586
587 // If this is the 2nd lap through the loop we now know the amount of memory to allocate:
588 // enough for numreturned dns servers
589 if(loopnum == 2)
590 {
591 if(numreturned == 0)
592 {
594 goto cleanup;
595 }
596
597 channel->servers = malloc( (numreturned) * sizeof(struct server_state));
598 if (!channel->servers)
599 {
600 rc = ARES_ENOMEM;
601 goto cleanup;
602 }
603 memset(channel->servers, '\0', numreturned * sizeof(struct server_state));
604 channel->nservers = 0;
605 }
606
607 // Process each adapter
608 for (AI = pAdapterAddresses; AI != NULL; AI = AI->Next)
609 {
610 PIP_ADAPTER_DNS_SERVER_ADDRESS dnsServers = AI->FirstDnsServerAddress;
611
612 //printf("ARES Interface: Name=%s(%S), Type=%d, Status=%d\n", AI->AdapterName, AI->FriendlyName, AI->IfType, AI->OperStatus);
613 if(AI->IfType == IF_TYPE_TUNNEL || AI->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
614 {
615 // Don't process TUNNEL or LOOPBACK adapters
616 continue;
617 }
618
619 // Process each DNS server for the adapter
620 for (; dnsServers; dnsServers = dnsServers->Next)
621 {
622 // Safety check for null sockaddr - shouldn't happen
623 if (! dnsServers->Address.lpSockaddr)
624 {
625 continue;
626 }
627
628 if (dnsServers->Address.lpSockaddr->sa_family == AF_INET)
629 {
630 struct sockaddr_in *sa4 = (struct sockaddr_in *)dnsServers->Address.lpSockaddr;
631 if((sa4->sin_addr.S_un.S_addr != INADDR_ANY) && (sa4->sin_addr.S_un.S_addr != INADDR_NONE))
632 {
633 if(loopnum == 1)
634 {
635 numreturned++;
636 }
637 else
638 {
639 // add v4 server if it doesn't exist already
640 if (find_server(channel->servers, channel->nservers, sa4->sin_addr) == -1)
641 {
642 //printf( " ARES: %d.%d.%d.%d\n", sa4->sin_addr.S_un.S_un_b.s_b1, sa4->sin_addr.S_un.S_un_b.s_b2, sa4->sin_addr.S_un.S_un_b.s_b3, sa4->sin_addr.S_un.S_un_b.s_b4 );
643#ifdef USE_IPV6
644 channel->servers[ channel->nservers ].family = AF_INET;
645#endif
646 channel->servers[channel->nservers].addr = sa4->sin_addr;
647
648 // Copy over physical address for use in ARES_FLAG_TRY_NEXT_SERVER_ON_RCODE3 mode
649 if (AI->PhysicalAddressLength <= sizeof(channel->servers[channel->nservers].physical_addr))
650 {
651 channel->servers[channel->nservers].physical_addr_len = AI->PhysicalAddressLength;
652 memcpy(channel->servers[channel->nservers].physical_addr, &AI->PhysicalAddress[0], AI->PhysicalAddressLength);
653 }
654 channel->nservers++;
655 }
656 }
657 }
658 }
659#ifdef USE_IPV6
660 else if(dnsServers->Address.lpSockaddr->sa_family == AF_INET6)
661 {
662 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)dnsServers->Address.lpSockaddr;
663
664 // Source: http://comments.gmane.org/gmane.network.dns.c-ares/1090
665 // Windows implements a draft RFC from 2001
666 // (http://tools.ietf.org/id/draft-ietf-ipngwg-dns-discovery-03.txt) that
667 // suggests that DNS resolvers try a couple of fixed "site-local" IPv6
668 // addresses (fec0:0:0:ffff::1, fec0:0:0:ffff::2 and fec0:0:0:ffff::3), which
669 // would allow the networking stack to find DNS servers without any
670 // configuration.
671
672 // The whole concept of site-local addresses is now considered problematic and
673 // the use of the fec0::/10 address range has been officially deprecated in RFC
674 // 3879 (http://www.ietf.org/rfc/rfc3879.txt) so it seems unlikely that this
675 // way of setting up DNS on a network will become popular in the future.
676
677 // Skip v6 address if inaddr_any or if site local (see above)
678 if (memcmp(&sa6->sin6_addr, &in6addr_any, sizeof(sa6->sin6_addr)) != 0 &&
679 ntohs(sa6->sin6_addr.u.Word[0]) != 0xfec0) // Addresses starting with 0xfec0 are site local addresses
680 {
681 if(loopnum == 1)
682 {
683 numreturned++;
684 }
685 else
686 {
687 // add v6 server if it doesn't exist already
688 if (find_server6(channel->servers, channel->nservers, sa6->sin6_addr) == -1)
689 {
690 //printf( " ARES: %.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:\n",
691 // ntohs(sa6->sin6_addr.u.Word[0]), ntohs(sa6->sin6_addr.u.Word[1]), ntohs(sa6->sin6_addr.u.Word[2]), ntohs(sa6->sin6_addr.u.Word[3]),
692 // ntohs(sa6->sin6_addr.u.Word[4]), ntohs(sa6->sin6_addr.u.Word[5]), ntohs(sa6->sin6_addr.u.Word[6]), ntohs(sa6->sin6_addr.u.Word[7]));
693 channel->servers[ channel->nservers ].family = AF_INET6;
694 memcpy(&channel->servers[channel->nservers].addr6, &sa6->sin6_addr, sizeof(channel->servers[channel->nservers].addr6));
695
696 // Copy over physical address for use in ARES_FLAG_TRY_NEXT_SERVER_ON_RCODE3 mode
697 if (AI->PhysicalAddressLength <= sizeof(channel->servers[channel->nservers].physical_addr))
698 {
699 channel->servers[channel->nservers].physical_addr_len = AI->PhysicalAddressLength;
700 memcpy(channel->servers[channel->nservers].physical_addr, &AI->PhysicalAddress[0], AI->PhysicalAddressLength);
701 }
702 channel->nservers++;
703 }
704 }
705 }
706 }
707#endif
708 }
709 }
710 }
711
712cleanup:
714 {
716 }
717 if (hLib)
718 {
720 }
721 return rc;
722}
723
725{
726 /*
727 * Way of getting nameservers that should work on all Windows from 98 / Server 2000 and on. Doesn't support IPv6 nameservers.
728 */
730 ULONG ulOutBufLen = 0;
733 HANDLE hLib;
734 int num;
735 int trys = 0;
737
738 hLib = LoadLibrary(TEXT("iphlpapi.dll"));
739 if(!hLib)
740 {
741 return ARES_ENOTIMP;
742 }
743
744 (void*)GetNetworkParamsProc = GetProcAddress(hLib, TEXT("GetNetworkParams"));
746 {
748 return ARES_ENOTIMP;
749 }
750 //printf("ARES: figuring out DNS servers\n");
752 {
753 if(FixedInfo != NULL)
754 {
756 }
758 }
759 if( dwRetVal != 0)
760 {
761 //printf("ARES: couldn't get network params, dwRet=0x%x\n", dwRetVal);
762 if(FixedInfo != NULL)
763 {
765 }
767 return ARES_ENODATA;
768 }
769
777 // Count how many nameserver entries we have and allocate memory for them.
778 num = 0;
779 pIPAddr = &FixedInfo->DnsServerList;
780 while ( pIPAddr && strlen(pIPAddr->IpAddress.String) > 0)
781 {
782 num++;
783 pIPAddr = pIPAddr ->Next;
784 }
785 //if(num == 0)
786 //{
787 // printf("ARES: no nameservers! size=%d\n", ulOutBufLen);
788 //}
789 //else
790 //{
791 // printf("ARES: num nameservers: %d, size=%d\n", num, ulOutBufLen);
792 //}
793 if(num>0)
794 {
795 channel->servers = malloc( (num) * sizeof(struct server_state));
796 if (!channel->servers)
797 {
800 return ARES_ENOMEM;
801 }
802 memset(channel->servers, '\0', num * sizeof(struct server_state));
803
804 channel->nservers = 0;
805 pIPAddr = &FixedInfo->DnsServerList;
806 while ( pIPAddr && strlen(pIPAddr->IpAddress.String) > 0)
807 {
808 struct in_addr addr;
809 /* TODO - add support for DNS servers specificied by v6 addresses */
810#if defined(_MSC_VER) && _MSC_VER >= 1800 /* removing compilation warning in VS2013+ */
811 inet_pton(AF_INET, pIPAddr->IpAddress.String, &addr.s_addr);
812#else
813 addr.s_addr = inet_addr(pIPAddr->IpAddress.String);
814#endif
815 // append unique only
816 if (find_server(channel->servers, channel->nservers, addr) == -1)
817 {
818 // printf( "ARES: %s\n", pIPAddr ->IpAddress.String );
819#ifdef USE_IPV6
820 channel->servers[ channel->nservers ].family = AF_INET;
821#endif
822 channel->servers[channel->nservers].addr = addr;
823 channel->nservers++;
824 }
825
826 pIPAddr = pIPAddr ->Next;
827 }
828 //printf("ARES: got all %d nameservers\n",num);
829 }
830
833
834 return ARES_SUCCESS;
835}
836#endif
837
839{
840 char hostname[MAXHOSTNAMELEN + 1];
841
842 if (channel->flags == -1)
843 channel->flags = 0;
844 if (channel->timeout == -1)
845 channel->timeout = DEFAULT_TIMEOUT;
846 if (channel->tries == -1)
847 channel->tries = DEFAULT_TRIES;
848 if (channel->ndots == -1)
849 channel->ndots = 1;
850 if (channel->udp_port == -1)
851 channel->udp_port = htons(NAMESERVER_PORT);
852 if (channel->tcp_port == -1)
853 channel->tcp_port = htons(NAMESERVER_PORT);
854
855 if (channel->nservers == -1)
856 {
857 // OS Specific Inits for nameservers
858#ifdef WIN32
860 {
861 return ARES_ENOMEM;
862 }
863 if (channel->nservers <= 0)
864 {
865 // If GetAdaptersAddresses approach didn't work then try GetNetworkParams (non IPv6 compatible)
867 {
868 return ARES_ENOMEM;
869 }
870 }
871#elif defined(__APPLE__) || defined(__MACH__)
873#elif defined(__ANDROID__)
875 {
876 return ARES_ENOMEM;
877 }
878#endif
879
880 /* If no specified servers, try a local named. */
881 if (channel->nservers <= 0)
882 {
883 channel->servers = malloc(sizeof(struct server_state));
884 if (!channel->servers)
885 return ARES_ENOMEM;
886 memset(channel->servers, '\0', sizeof(struct server_state));
887
888#ifdef USE_IPV6
889 channel->servers[0].family = AF_INET;
890#endif
891
892 channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK);
893 channel->servers[0].default_localhost_server = 1;
894 channel->nservers = 1;
895
896 // if v6 is running...
897 // channel->servers[0].family = AF_INET6;
898 // channel->servers[0].addr6.s_addr = htonl6(IN6ADDR_LOOPBACK_INIT);
899 // hard to decide if there is one server or two here
900 }
901 }
902
903 if (channel->ndomains == -1)
904 {
905 /* Derive a default domain search list from the kernel hostname,
906 * or set it to empty if the hostname isn't helpful.
907 */
908 if (gethostname(hostname, sizeof(hostname)) == -1 || !strchr(hostname, '.'))
909 {
910 channel->domains = 0; // malloc(0);
911 channel->ndomains = 0;
912 }
913 else
914 {
915 channel->domains = malloc(sizeof(char *));
916 if (!channel->domains)
917 return ARES_ENOMEM;
918 channel->ndomains = 0;
919 channel->domains[0] = strdup(strchr(hostname, '.') + 1);
920 if (!channel->domains[0])
921 return ARES_ENOMEM;
922 channel->ndomains = 1;
923 }
924 }
925
926 if (channel->nsort == -1)
927 {
928 channel->sortlist = NULL;
929 channel->nsort = 0;
930 }
931
932 if (!channel->lookups)
933 {
934 channel->lookups = strdup("bf");
935 if (!channel->lookups)
936 return ARES_ENOMEM;
937 }
938
939 return ARES_SUCCESS;
940}
941
942static int config_domain(ares_channel channel, char *str)
943{
944 char *q;
945
946 /* Set a single search domain. */
947 q = str;
948 while (*q && !isspace((unsigned char)*q))
949 q++;
950 *q = 0;
951 return set_search(channel, str);
952}
953
954static int config_lookup(ares_channel channel, const char *str)
955{
956 char lookups[3], *l;
957 const char *p;
958
959 /* Set the lookup order. Only the first letter of each work
960 * is relevant, and it has to be "b" for DNS or "f" for the
961 * host file. Ignore everything else.
962 */
963 l = lookups;
964 p = str;
965 while (*p)
966 {
967 if ((*p == 'b' || *p == 'f') && l < lookups + 2)
968 *l++ = *p;
969 while (*p && !isspace((unsigned char)*p))
970 p++;
971 while (isspace((unsigned char)*p))
972 p++;
973 }
974 *l = 0;
975 channel->lookups = strdup(lookups);
976 return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
977}
978
979static int config_nameserver(struct server_state **servers, int *nservers,
980 const char *str)
981{
982 struct in_addr addr;
983 struct server_state *newserv;
984#ifdef USE_IPV6
986 struct in6_addr addr6;
987
988 /* Add a nameserver entry, if this is a valid address. */
989
990 if (inet_pton4(str, (u_char *) & addr)) /* is it an IPv4 address? */
991 family = AF_INET;
992 else
993 {
994 if (inet_pton6(str, (u_char *) & addr6)) /* how about an IPv6 address? */
995 family = AF_INET6;
996 else
997 return ARES_SUCCESS; /* nope, it was garbage, return early */
998 }
999#else
1000 /* Add a nameserver entry, if this is a valid address. */
1001
1002 if (!inet_pton4(str, (u_char *) & addr)) /* is it an IPv4 address? */
1003 return ARES_SUCCESS; /* nope, it was garbage, return early */
1004#endif
1005
1006 newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
1007 if (!newserv)
1008 return ARES_ENOMEM;
1009 memset(&newserv[*nservers], '\0', sizeof(struct server_state)); // clear *new* memory only
1010
1011#ifdef USE_IPV6
1012 newserv[*nservers].family = family;
1013 if (family == AF_INET6)
1014 newserv[*nservers].addr6 = addr6;
1015 else
1016#endif
1017 newserv[*nservers].addr = addr;
1018
1019 *servers = newserv;
1020 (*nservers)++;
1021 return ARES_SUCCESS;
1022}
1023
1024static int config_sortlist(struct apattern **sortlist, int *nsort,
1025 const char *str)
1026{
1027 struct apattern pat, *newsort;
1028 const char *q;
1029
1030 /* Add sortlist entries. */
1031 while (*str && *str != ';')
1032 {
1033 q = str;
1034 while (*q && *q != '/' && *q != ';' && !isspace((unsigned char)*q))
1035 q++;
1036 if (ip_addr(str, (int)(q - str), &pat.addr) == 0)
1037 {
1038 /* We have a pattern address; now determine the mask. */
1039 if (*q == '/')
1040 {
1041 str = q + 1;
1042 while (*q && *q != ';' && !isspace((unsigned char)*q))
1043 q++;
1044 if (ip_addr(str, (int)(q - str), &pat.mask) != 0)
1045 natural_mask(&pat);
1046 }
1047 else
1048 natural_mask(&pat);
1049
1050 /* Add this pattern to our list. */
1051 newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
1052 if (!newsort)
1053 return ARES_ENOMEM;
1054 newsort[*nsort] = pat;
1055 *sortlist = newsort;
1056 (*nsort)++;
1057 }
1058 else
1059 {
1060 while (*q && *q != ';' && !isspace((unsigned char)*q))
1061 q++;
1062 }
1063 str = q;
1064 while (isspace((unsigned char)*str))
1065 str++;
1066 }
1067
1068 return ARES_SUCCESS;
1069}
1070
1071static int set_search(ares_channel channel, const char *str)
1072{
1073 int n;
1074 const char *p, *q;
1075
1076 /* Count the domains given. */
1077 n = 0;
1078 p = str;
1079 while (*p)
1080 {
1081 while (*p && !isspace((unsigned char)*p))
1082 p++;
1083 while (isspace((unsigned char)*p))
1084 p++;
1085 n++;
1086 }
1087
1088 channel->domains = malloc(n * sizeof(char *));
1089 if (!channel->domains && n)
1090 return ARES_ENOMEM;
1091
1092 /* Now copy the domains. */
1093 n = 0;
1094 p = str;
1095 while (*p)
1096 {
1097 channel->ndomains = n;
1098 q = p;
1099 while (*q && !isspace((unsigned char)*q))
1100 q++;
1101 channel->domains[n] = malloc(q - p + 1);
1102 if (!channel->domains[n])
1103 return ARES_ENOMEM;
1104 memcpy(channel->domains[n], p, q - p);
1105 channel->domains[n][q - p] = 0;
1106 p = q;
1107 while (isspace((unsigned char)*p))
1108 p++;
1109 n++;
1110 }
1111 channel->ndomains = n;
1112
1113 return ARES_SUCCESS;
1114}
1115
1116static int set_options(ares_channel channel, const char *str)
1117{
1118 const char *p, *q, *val;
1119
1120 p = str;
1121 while (*p)
1122 {
1123 q = p;
1124 while (*q && !isspace((unsigned char)*q))
1125 q++;
1126 val = try_option(p, q, "ndots:");
1127 if (val && channel->ndots == -1)
1128 channel->ndots = atoi(val);
1129 val = try_option(p, q, "retrans:");
1130 if (val && channel->timeout == -1)
1131 channel->timeout = atoi(val);
1132 val = try_option(p, q, "retry:");
1133 if (val && channel->tries == -1)
1134 channel->tries = atoi(val);
1135 p = q;
1136 while (isspace((unsigned char)*p))
1137 p++;
1138 }
1139
1140 return ARES_SUCCESS;
1141}
1142
1143static char *try_config(char *s, char *opt)
1144{
1145 int len;
1146
1147 len = (int)strlen(opt);
1148 if (strncmp(s, opt, len) != 0 || !isspace((unsigned char)s[len]))
1149 return NULL;
1150 s += len;
1151 while (isspace((unsigned char)*s))
1152 s++;
1153 return s;
1154}
1155
1156static const char *try_option(const char *p, const char *q, const char *opt)
1157{
1158 int len;
1159
1160 len = (int)strlen(opt);
1161 return (q - p > len && strncmp(p, opt, len) == 0) ? p + len : NULL;
1162}
1163
1164static int ip_addr(const char *s, int len, struct in_addr *addr)
1165{
1166 char ipbuf[16];
1167
1168 /* Four octets and three periods yields at most 15 characters. */
1169 if (len > 15)
1170 return -1;
1171 memcpy(ipbuf, s, len);
1172 ipbuf[len] = 0;
1173
1174#if defined(_MSC_VER) && _MSC_VER >= 1800 /* removing compilation warning in VS2013+ */
1175 inet_pton(AF_INET, ipbuf, &addr->s_addr);
1176#else
1177 addr->s_addr = inet_addr(ipbuf);
1178#endif
1179
1180 if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
1181 return -1;
1182 return 0;
1183}
1184
1185static void natural_mask(struct apattern *pat)
1186{
1187 struct in_addr addr;
1188
1189 /* Store a host-byte-order copy of pat in a struct in_addr. Icky,
1190 * but portable.
1191 */
1192 addr.s_addr = ntohl(pat->addr.s_addr);
1193
1194 /* This is out of date in the CIDR world, but some people might
1195 * still rely on it.
1196 */
1197 if (IN_CLASSA(addr.s_addr))
1198 pat->mask.s_addr = htonl(IN_CLASSA_NET);
1199 else if (IN_CLASSB(addr.s_addr))
1200 pat->mask.s_addr = htonl(IN_CLASSB_NET);
1201 else
1202 pat->mask.s_addr = htonl(IN_CLASSC_NET);
1203}
1204
1205#ifdef WIN32
1206/*
1207 * Finds a V4 addr in list of servers.
1208 * return:
1209 * index i of servers whose servers[i].addr == addr
1210 * else -1, failed to find
1211 */
1212static int find_server(struct server_state *servers, int nservers, struct in_addr addr)
1213{
1214 int i = 0;
1215
1216 if (nservers == 0)
1217 {
1218 return -1;
1219 }
1220
1221 for (; i < nservers; i++)
1222 {
1223 if (servers[i].addr.s_addr == addr.s_addr)
1224 {
1225 break;
1226 }
1227 }
1228 return (i < nservers ? i : -1);
1229}
1230
1231#ifdef USE_IPV6
1232/*
1233 * Finds a V6 addr in list of servers.
1234 * return:
1235 * index i of servers whose servers[i].addr6 == addr
1236 * else -1, failed to find
1237 */
1238static int find_server6(struct server_state *servers, int nservers, struct in6_addr addr)
1239{
1240 int i = 0;
1241
1242 if (nservers == 0)
1243 {
1244 return -1;
1245 }
1246
1247 for (; i < nservers; i++)
1248 {
1249 if (memcmp(&servers[i].addr6, &addr, sizeof(addr)) == 0)
1250 {
1251 break;
1252 }
1253 }
1254 return (i < nservers ? i : -1);
1255}
1256#endif
1257#endif
1258
1259#define NS_INT16SZ 2
1260#define NS_INADDRSZ 4
1261#define NS_IN6ADDRSZ 16
1262
1263#ifdef USE_IPV6
1264/* int
1265 * inet_pton6(src, dst)
1266 * convert presentation level address to network order binary form.
1267 * return:
1268 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1269 * notice:
1270 * (1) does not touch `dst' unless it's returning 1.
1271 * (2) :: in a full address is silently ignored.
1272 * credit:
1273 * inspired by Mark Andrews.
1274 * author:
1275 * Paul Vixie, 1996.
1276 */
1277static int
1278inet_pton6(const char *src, u_char *dst)
1279{
1280 static const char xdigits_l[] = "0123456789abcdef",
1281 xdigits_u[] = "0123456789ABCDEF";
1283 const char *xdigits, *curtok;
1284 int ch, saw_xdigit;
1285 u_int val;
1286
1287 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
1288 endp = tp + NS_IN6ADDRSZ;
1289 colonp = NULL;
1290 /* Leading :: requires some special handling. */
1291 if (*src == ':')
1292 if (*++src != ':')
1293 return (0);
1294 curtok = src;
1295 saw_xdigit = 0;
1296 val = 0;
1297 while ((ch = *src++) != '\0') {
1298 const char *pch;
1299
1300 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
1301 pch = strchr((xdigits = xdigits_u), ch);
1302 if (pch != NULL) {
1303 val <<= 4;
1304 val |= (pch - xdigits);
1305 if (val > 0xffff)
1306 return (0);
1307 saw_xdigit = 1;
1308 continue;
1309 }
1310 if (ch == ':') {
1311 curtok = src;
1312 if (!saw_xdigit) {
1313 if (colonp)
1314 return (0);
1315 colonp = tp;
1316 continue;
1317 }
1318 if (tp + NS_INT16SZ > endp)
1319 return (0);
1320 *tp++ = (u_char) (val >> 8) & 0xff;
1321 *tp++ = (u_char) val & 0xff;
1322 saw_xdigit = 0;
1323 val = 0;
1324 continue;
1325 }
1326 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
1327 inet_pton4(curtok, tp) > 0) {
1328 tp += NS_INADDRSZ;
1329 saw_xdigit = 0;
1330 break; /* '\0' was seen by inet_pton4(). */
1331 }
1332 return (0);
1333 }
1334 if (saw_xdigit) {
1335 if (tp + NS_INT16SZ > endp)
1336 return (0);
1337 *tp++ = (u_char) (val >> 8) & 0xff;
1338 *tp++ = (u_char) val & 0xff;
1339 }
1340 if (colonp != NULL) {
1341 /*
1342 * Since some memmove()'s erroneously fail to handle
1343 * overlapping regions, we'll do the shift by hand.
1344 */
1345 const int n = (int)(tp - colonp);
1346 int i;
1347
1348 for (i = 1; i <= n; i++) {
1349 endp[- i] = colonp[n - i];
1350 colonp[n - i] = 0;
1351 }
1352 tp = endp;
1353 }
1354 if (tp != endp)
1355 return (0);
1357 return (1);
1358}
1359
1360#endif
1361
1362/* int
1363 * inet_pton4(src, dst)
1364 * like inet_aton() but without all the hexadecimal and shorthand.
1365 * return:
1366 * 1 if `src' is a valid dotted quad, else 0.
1367 * notice:
1368 * does not touch `dst' unless it's returning 1.
1369 * author:
1370 * Paul Vixie, 1996.
1371 */
1372static int
1373inet_pton4(const char *src, u_char *dst)
1374{
1375 static const char digits[] = "0123456789";
1376 int saw_digit, octets, ch;
1378
1379 saw_digit = 0;
1380 octets = 0;
1381 *(tp = tmp) = 0;
1382 while ((ch = *src++) != '\0') {
1383 const char *pch;
1384
1385 if ((pch = strchr(digits, ch)) != NULL) {
1386 u_int newVal = (u_int)(*tp * 10 + (pch - digits));
1387
1388 if (newVal > 255)
1389 return (0);
1390 *tp = newVal;
1391 if (! saw_digit) {
1392 if (++octets > 4)
1393 return (0);
1394 saw_digit = 1;
1395 }
1396 } else if (ch == '.' && saw_digit) {
1397 if (octets == 4)
1398 return (0);
1399 *++tp = 0;
1400 saw_digit = 0;
1401 } else
1402 return (0);
1403 }
1404 if (octets < 4)
1405 return (0);
1406
1408 return (1);
1409}
1410
1411/*
1412 * vi: set shiftwidth=3 expandtab:
1413 */
#define MAXHOSTNAMELEN
Definition DnsUtil.cxx:34
#define resip_assert(x)
This file needs to work for both C and C++ code.
#define INADDR_NONE
Definition adig.c:51
#define ARES_SUCCESS
Definition ares.h:79
#define ARES_ENOMEM
Definition ares.h:98
#define ARES_OPT_LOOKUPS
Definition ares.h:121
#define ARES_ENODATA
Definition ares.h:82
#define ARES_OPT_DOMAINS
Definition ares.h:120
#define ARES_EOF
Definition ares.h:96
#define ARES_FLAG_PRIMARY
Definition ares.h:103
#define ARES_ENOTFOUND
Definition ares.h:85
#define ARES_OPT_UDP_PORT
Definition ares.h:117
#define ARES_CAP_IPV6
Definition ares.h:125
#define ARES_OPT_TIMEOUT
Definition ares.h:114
#define ARES_OPT_SERVERS
Definition ares.h:119
#define ARES_OPT_NDOTS
Definition ares.h:116
#define ARES_OPT_TCP_PORT
Definition ares.h:118
#define ARES_ENOTIMP
Definition ares.h:86
#define ARES_OPT_FLAGS
Definition ares.h:113
#define ARES_EFILE
Definition ares.h:97
#define ARES_OPT_TRIES
Definition ares.h:115
int ares__read_line(FILE *fp, char **buf, int *bufsize)
static const char * try_option(const char *p, const char *q, const char *opt)
Definition ares_init.c:1156
static int init_by_environment(ares_channel channel)
Definition ares_init.c:313
static int init_by_options(ares_channel channel, struct ares_options *options, int optmask)
Definition ares_init.c:238
static int config_nameserver(struct server_state **servers, int *nservers, const char *str)
Definition ares_init.c:979
int ares_capabilities(int capmask)
Definition ares_init.c:94
static int inet_pton6(const char *src, u_char *dst)
Definition ares_init.c:1278
static int set_options(ares_channel channel, const char *str)
Definition ares_init.c:1116
int ares_init(ares_channel *channelptr)
Definition ares_init.c:104
static int init_by_resolv_conf(ares_channel channel)
Definition ares_init.c:353
static int ip_addr(const char *s, int len, struct in_addr *addr)
Definition ares_init.c:1164
static int init_by_defaults(ares_channel channel)
Definition ares_init.c:838
static int config_domain(ares_channel channel, char *str)
Definition ares_init.c:942
#define NS_IN6ADDRSZ
Definition ares_init.c:1261
#define NS_INT16SZ
Definition ares_init.c:1259
static int inet_pton4(const char *src, u_char *dst)
Definition ares_init.c:1373
int ares_init_with_socket_function(ares_channel *channelptr, socket_function_ptr socketFunc)
Definition ares_init.c:109
static char * try_config(char *s, char *opt)
Definition ares_init.c:1143
int ares_init_options_with_socket_function(ares_channel *channelptr, struct ares_options *options, int optmask, socket_function_ptr socketFunc)
Definition ares_init.c:120
static int set_search(ares_channel channel, const char *str)
Definition ares_init.c:1071
static void natural_mask(struct apattern *pat)
Definition ares_init.c:1185
int ares_init_options(ares_channel *channelptr, struct ares_options *options, int optmask)
Definition ares_init.c:114
static int config_sortlist(struct apattern **sortlist, int *nsort, const char *str)
Definition ares_init.c:1024
#define NS_INADDRSZ
Definition ares_init.c:1260
static int config_lookup(ares_channel channel, const char *str)
Definition ares_init.c:954
#define NAMESERVER_PORT
#define DEFAULT_TRIES
#define DEFAULT_TIMEOUT
#define PATH_RESOLV_CONF
void(* socket_function_ptr)(Socket s, int transportType, const char *file, int line)
struct in_addr addr
struct apattern * sortlist
ares_poll_cb_func * poll_cb_func
struct query * queries
unsigned short next_id
socket_function_ptr socket_function
struct server_state * servers
int physical_addr_len
u_int8_t family
struct send_request * qhead
struct in6_addr addr6
int default_localhost_server
struct send_request * qtail
unsigned char * tcp_buffer
struct in_addr addr
unsigned char physical_addr[MAX_ADAPTER_ADDRESS_LENGTH]
void list()
Definition userAdmin.cxx:66