/[resiprocate]/main/contrib/ares/ares_init.c
ViewVC logotype

Annotation of /main/contrib/ares/ares_init.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5295 - (hide annotations) (download)
Mon Aug 22 00:30:05 2005 UTC (14 years, 3 months ago) by jason
File MIME type: text/plain
File size: 24118 byte(s)
merged 5270:HEAD from b-directory-reorg
1 ryker 1479 /* 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    
17     #include <sys/types.h>
18     #include <stdio.h>
19     #include <stdlib.h>
20     #include <string.h>
21     #include <ctype.h>
22     #include <time.h>
23 fluffy 1789 #include <assert.h>
24 fluffy 1728
25     #ifndef WIN32
26     #include <sys/time.h>
27     #include <sys/param.h>
28     #include <netinet/in.h>
29     #include <arpa/inet.h>
30 derek 5267 #include <sys/socket.h>
31 adamr 2079 #ifndef __CYGWIN__
32     # include <arpa/nameser.h>
33     #endif
34 fluffy 1728 #include <unistd.h>
35     #include <errno.h>
36     #include <netdb.h>
37 fluffy 1789 #else
38     #include <Winsock2.h>
39 adam 3100 #include <iphlpapi.h>
40 fluffy 1789 #include <io.h>
41     #include <Windns.h>
42 fluffy 1728 #endif
43    
44 ryker 1479 #include "ares.h"
45     #include "ares_private.h"
46    
47     static int init_by_options(ares_channel channel, struct ares_options *options,
48     int optmask);
49     static int init_by_environment(ares_channel channel);
50     static int init_by_resolv_conf(ares_channel channel);
51     static int init_by_defaults(ares_channel channel);
52     static int config_domain(ares_channel channel, char *str);
53     static int config_lookup(ares_channel channel, const char *str);
54     static int config_nameserver(struct server_state **servers, int *nservers,
55     const char *str);
56     static int config_sortlist(struct apattern **sortlist, int *nsort,
57     const char *str);
58     static int set_search(ares_channel channel, const char *str);
59     static int set_options(ares_channel channel, const char *str);
60     static char *try_config(char *s, char *opt);
61     static const char *try_option(const char *p, const char *q, const char *opt);
62     static int ip_addr(const char *s, int len, struct in_addr *addr);
63     static void natural_mask(struct apattern *pat);
64    
65 rohan 3940 static int inet_pton4(const char *src, u_char *dst);
66 derek 5267 #ifdef USE_IPV6
67 rohan 3940 static int inet_pton6(const char *src, u_char *dst);
68     #endif
69    
70 sgodin 3873 #ifdef WIN32
71     char w32hostspath[256];
72     #endif
73    
74 derek 5269
75     int ares_capabilities(int capmask)
76     {
77     #ifdef USE_IPV6
78     static int ares_caps = ARES_CAP_IPV6;
79     #else
80     static int ares_caps = 0;
81     #endif
82     return (capmask & ares_caps);
83     }
84    
85 ryker 1479 int ares_init(ares_channel *channelptr)
86     {
87 derek 5267 return ares_init_options(channelptr, NULL, 0);
88     }
89    
90     int ares_init_options(ares_channel *channelptr, struct ares_options *options,
91     int optmask)
92     {
93 ryker 1479 ares_channel channel;
94     int i, status;
95     struct server_state *server;
96 derek 5268 #ifdef WIN32
97     {
98     HKEY hKey;
99     char hostpath[256];
100     if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
101     {
102     DWORD dwSize = sizeof(hostpath);
103     if(RegQueryValueEx(hKey, "DatabasePath", 0, 0, (LPBYTE)&hostpath, &dwSize) == ERROR_SUCCESS)
104     {
105     hostpath[dwSize] = '\0';
106     ExpandEnvironmentStrings(hostpath, w32hostspath, sizeof(w32hostspath));
107     if(strlen(w32hostspath) < sizeof(w32hostspath) - 6)
108     {
109     strcat(w32hostspath, "\\hosts");
110     }
111     }
112     }
113     }
114     #endif
115     // struct timeval tv;
116 ryker 1479
117     channel = malloc(sizeof(struct ares_channeldata));
118     if (!channel)
119     return ARES_ENOMEM;
120    
121     /* Set everything to distinguished values so we know they haven't
122     * been set yet.
123     */
124     channel->flags = -1;
125     channel->timeout = -1;
126     channel->tries = -1;
127     channel->ndots = -1;
128     channel->udp_port = -1;
129     channel->tcp_port = -1;
130     channel->nservers = -1;
131     channel->ndomains = -1;
132     channel->nsort = -1;
133     channel->lookups = NULL;
134    
135     /* Initialize configuration by each of the four sources, from highest
136     * precedence to lowest.
137     */
138     status = init_by_options(channel, options, optmask);
139     if (status == ARES_SUCCESS)
140     status = init_by_environment(channel);
141     if (status == ARES_SUCCESS)
142     status = init_by_resolv_conf(channel);
143     if (status == ARES_SUCCESS)
144     status = init_by_defaults(channel);
145     if (status != ARES_SUCCESS)
146     {
147     /* Something failed; clean up memory we may have allocated. */
148     if (channel->nservers != -1)
149     free(channel->servers);
150     if (channel->ndomains != -1)
151     {
152     for (i = 0; i < channel->ndomains; i++)
153     free(channel->domains[i]);
154     free(channel->domains);
155     }
156     if (channel->nsort != -1)
157     free(channel->sortlist);
158     free(channel->lookups);
159     free(channel);
160     return status;
161     }
162    
163     /* Trim to one server if ARES_FLAG_PRIMARY is set. */
164     if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
165     channel->nservers = 1;
166    
167     /* Initialize server states. */
168     for (i = 0; i < channel->nservers; i++)
169     {
170     server = &channel->servers[i];
171     server->udp_socket = -1;
172     server->tcp_socket = -1;
173     server->tcp_lenbuf_pos = 0;
174     server->tcp_buffer = NULL;
175     server->qhead = NULL;
176     server->qtail = NULL;
177     }
178    
179     /* Choose a somewhat random query ID. The main point is to avoid
180     * collisions with stale queries. An attacker trying to spoof a DNS
181     * answer also has to guess the query ID, but it's only a 16-bit
182     * field, so there's not much to be done about that.
183     */
184 fluffy 1726 // gettimeofday(&tv, NULL);
185     // channel->next_id = (tv.tv_sec ^ tv.tv_usec ^ getpid()) & 0xffff;
186     {
187 fluffy 1789 static int cjNextID=1;
188 fluffy 1726 channel->next_id = cjNextID++;
189     }
190 ryker 1479
191     channel->queries = NULL;
192    
193     *channelptr = channel;
194     return ARES_SUCCESS;
195     }
196    
197     static int init_by_options(ares_channel channel, struct ares_options *options,
198     int optmask)
199     {
200     int i;
201    
202     /* Easy stuff. */
203     if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
204     channel->flags = options->flags;
205     if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
206     channel->timeout = options->timeout;
207     if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
208     channel->tries = options->tries;
209     if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
210     channel->ndots = options->ndots;
211     if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1)
212 derek 5267 channel->udp_port = options->udp_port;
213 ryker 1479 if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
214 derek 5267 channel->tcp_port = options->tcp_port;
215 ryker 1479
216     /* Copy the servers, if given. */
217     if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
218 derek 5267 {
219     channel->servers =
220     malloc(options->nservers * sizeof(struct server_state));
221     if (!channel->servers && options->nservers != 0)
222     return ARES_ENOMEM;
223     for (i = 0; i < options->nservers; i++)
224     {
225     #ifdef USE_IPV6
226 rohan 3940 channel->servers[i].family = options->servers[i].family;
227     if (options->servers[i].family == AF_INET6)
228     {
229     channel->servers[i].addr6 = options->servers[i].addr6;
230     }
231     else
232     {
233     channel->servers[i].addr = options->servers[i].addr;
234     }
235     #else
236     channel->servers[i].addr = options->servers[i];
237     #endif
238     channel->nservers = options->nservers;
239     }
240 ryker 1479 }
241    
242     /* Copy the domains, if given. Keep channel->ndomains consistent so
243     * we can clean up in case of error.
244     */
245     if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1)
246     {
247     channel->domains = malloc(options->ndomains * sizeof(char *));
248     if (!channel->domains && options->ndomains != 0)
249     return ARES_ENOMEM;
250     for (i = 0; i < options->ndomains; i++)
251     {
252     channel->ndomains = i;
253     channel->domains[i] = strdup(options->domains[i]);
254     if (!channel->domains[i])
255     return ARES_ENOMEM;
256     }
257     channel->ndomains = options->ndomains;
258     }
259    
260     /* Set lookups, if given. */
261     if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups)
262     {
263     channel->lookups = strdup(options->lookups);
264     if (!channel->lookups)
265     return ARES_ENOMEM;
266     }
267    
268     return ARES_SUCCESS;
269     }
270    
271     static int init_by_environment(ares_channel channel)
272     {
273     const char *localdomain, *res_options;
274     int status;
275    
276     localdomain = getenv("LOCALDOMAIN");
277     if (localdomain && channel->ndomains == -1)
278     {
279     status = set_search(channel, localdomain);
280     if (status != ARES_SUCCESS)
281     return status;
282     }
283    
284     res_options = getenv("RES_OPTIONS");
285     if (res_options)
286     {
287     status = set_options(channel, res_options);
288     if (status != ARES_SUCCESS)
289     return status;
290     }
291    
292     return ARES_SUCCESS;
293     }
294    
295     static int init_by_resolv_conf(ares_channel channel)
296     {
297     FILE *fp;
298     char *line = NULL, *p;
299     int linesize, status, nservers = 0, nsort = 0;
300     struct server_state *servers = NULL;
301     struct apattern *sortlist = NULL;
302    
303     fp = fopen(PATH_RESOLV_CONF, "r");
304     if (!fp)
305     return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
306     while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
307     {
308     if ((p = try_config(line, "domain")) && channel->ndomains == -1)
309     status = config_domain(channel, p);
310     else if ((p = try_config(line, "lookup")) && !channel->lookups)
311     status = config_lookup(channel, p);
312     else if ((p = try_config(line, "search")) && channel->ndomains == -1)
313     status = set_search(channel, p);
314     else if ((p = try_config(line, "nameserver")) && channel->nservers == -1)
315     status = config_nameserver(&servers, &nservers, p);
316     else if ((p = try_config(line, "sortlist")) && channel->nsort == -1)
317     status = config_sortlist(&sortlist, &nsort, p);
318     else if ((p = try_config(line, "options")))
319     status = set_options(channel, p);
320     else
321     status = ARES_SUCCESS;
322     if (status != ARES_SUCCESS)
323     break;
324     }
325     free(line);
326     fclose(fp);
327    
328     /* Handle errors. */
329     if (status != ARES_EOF)
330     {
331     free(servers);
332     free(sortlist);
333     return status;
334     }
335    
336     /* If we got any name server entries, fill them in. */
337     if (servers)
338     {
339     channel->servers = servers;
340     channel->nservers = nservers;
341     }
342    
343     /* If we got any sortlist entries, fill them in. */
344     if (sortlist)
345     {
346     channel->sortlist = sortlist;
347     channel->nsort = nsort;
348     }
349    
350     return ARES_SUCCESS;
351     }
352    
353     static int init_by_defaults(ares_channel channel)
354     {
355     char hostname[MAXHOSTNAMELEN + 1];
356    
357     if (channel->flags == -1)
358     channel->flags = 0;
359     if (channel->timeout == -1)
360     channel->timeout = DEFAULT_TIMEOUT;
361     if (channel->tries == -1)
362     channel->tries = DEFAULT_TRIES;
363     if (channel->ndots == -1)
364     channel->ndots = 1;
365     if (channel->udp_port == -1)
366 derek 3444 channel->udp_port = htons(NAMESERVER_PORT);
367 ryker 1479 if (channel->tcp_port == -1)
368 derek 3444 channel->tcp_port = htons(NAMESERVER_PORT);
369 ryker 1479
370     if (channel->nservers == -1)
371     {
372 jason 1821 #ifdef WIN32
373 adam 3100 /*
374     * Way of getting nameservers that should work on all Windows from 98 on.
375     */
376     FIXED_INFO * FixedInfo;
377     ULONG ulOutBufLen;
378     DWORD dwRetVal;
379     IP_ADDR_STRING * pIPAddr;
380     HANDLE hLib;
381 sgodin 3002 int num;
382 adam 3100 DWORD (WINAPI *GetNetworkParams)(FIXED_INFO*, DWORD*);
383 jason 1821
384 derek 3444 hLib = LoadLibraryA("iphlpapi.dll");
385 sgodin 3002 if(!hLib)
386     {
387     return ARES_ENOTIMP;
388     }
389 fluffy 1789
390 sgodin 3002 (void*)GetNetworkParams = GetProcAddress(hLib, "GetNetworkParams");
391     if(!GetNetworkParams)
392     {
393     FreeLibrary(hLib);
394     return ARES_ENOTIMP;
395     }
396 adam 3100 //printf("ARES: figuring out DNS servers\n");
397     FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );
398     ulOutBufLen = sizeof( FIXED_INFO );
399 fluffy 1789
400 adam 3100 if( ERROR_BUFFER_OVERFLOW == (*GetNetworkParams)( FixedInfo, &ulOutBufLen ) )
401     {
402     GlobalFree( FixedInfo );
403     FixedInfo = (FIXED_INFO *)GlobalAlloc( GPTR, ulOutBufLen );
404     }
405 sgodin 3002
406 adam 3100 if ( dwRetVal = (*GetNetworkParams)( FixedInfo, &ulOutBufLen ) )
407     {
408     //printf("ARES: couldn't get network params\n");
409     GlobalFree( FixedInfo );
410 sgodin 3002 FreeLibrary(hLib);
411 adam 3100 return ARES_ENODATA;
412     }
413     else
414     {
415     /**
416     printf( "Host Name: %s\n", FixedInfo -> HostName );
417     printf( "Domain Name: %s\n", FixedInfo -> DomainName );
418     printf( "DNS Servers:\n" );
419     printf( "\t%s\n", FixedInfo -> DnsServerList.IpAddress.String );
420     **/
421    
422     // Count how many nameserver entries we have and allocate memory for them.
423     num = 0;
424     pIPAddr = &FixedInfo->DnsServerList;
425     while ( pIPAddr && strlen(pIPAddr->IpAddress.String) > 0)
426     {
427     num++;
428     pIPAddr = pIPAddr ->Next;
429     }
430 sgodin 3705 if(num>0)
431     {
432     channel->servers = malloc( (num) * sizeof(struct server_state));
433     if (!channel->servers)
434     {
435     GlobalFree( FixedInfo );
436     FreeLibrary(hLib);
437     return ARES_ENOMEM;
438     }
439 fluffy 1789
440 sgodin 3705 channel->nservers = 0;
441     pIPAddr = &FixedInfo->DnsServerList;
442     while ( pIPAddr && strlen(pIPAddr->IpAddress.String) > 0)
443     {
444     // printf( "ARES: %s\n", pIPAddr ->IpAddress.String );
445     channel->servers[ channel->nservers++ ].addr.s_addr = inet_addr(pIPAddr ->IpAddress.String);
446     pIPAddr = pIPAddr ->Next;
447     }
448     //printf("ARES: got all %d nameservers\n",num);
449 adam 3100 }
450 sgodin 3705 else
451     {
452     /* If no specified servers, try a local named. */
453     channel->servers = malloc(sizeof(struct server_state));
454     if (!channel->servers)
455     return ARES_ENOMEM;
456     channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK);
457     channel->nservers = 1;
458     }
459 sgodin 3002
460 adam 3100 GlobalFree( FixedInfo );
461 sgodin 3002 FreeLibrary(hLib);
462     }
463 fluffy 1789 #else
464     /* If nobody specified servers, try a local named. */
465     channel->servers = malloc(sizeof(struct server_state));
466     if (!channel->servers)
467     return ARES_ENOMEM;
468 rohan 3940
469     // need a way to test here if v4 or v6 is running
470     // if v4 is running...
471 fluffy 1789 channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK);
472 rohan 3940 // if v6 is running...
473     // channel->servers[0].addr6.s_addr = htonl6(IN6ADDR_LOOPBACK_INIT);
474     // hard to decide if there is one server or two here
475 fluffy 1789 channel->nservers = 1;
476     #endif
477    
478 ryker 1479 }
479    
480     if (channel->ndomains == -1)
481     {
482     /* Derive a default domain search list from the kernel hostname,
483     * or set it to empty if the hostname isn't helpful.
484     */
485     if (gethostname(hostname, sizeof(hostname)) == -1
486     || !strchr(hostname, '.'))
487     {
488 fluffy 1789 channel->domains = 0; // malloc(0);
489 ryker 1479 channel->ndomains = 0;
490     }
491     else
492     {
493     channel->domains = malloc(sizeof(char *));
494     if (!channel->domains)
495     return ARES_ENOMEM;
496     channel->ndomains = 0;
497     channel->domains[0] = strdup(strchr(hostname, '.') + 1);
498     if (!channel->domains[0])
499     return ARES_ENOMEM;
500     channel->ndomains = 1;
501     }
502     }
503    
504     if (channel->nsort == -1)
505     {
506     channel->sortlist = NULL;
507     channel->nsort = 0;
508     }
509    
510     if (!channel->lookups)
511     {
512     channel->lookups = strdup("bf");
513     if (!channel->lookups)
514     return ARES_ENOMEM;
515     }
516    
517     return ARES_SUCCESS;
518     }
519    
520     static int config_domain(ares_channel channel, char *str)
521     {
522     char *q;
523    
524     /* Set a single search domain. */
525     q = str;
526     while (*q && !isspace((unsigned char)*q))
527     q++;
528     *q = 0;
529     return set_search(channel, str);
530     }
531    
532     static int config_lookup(ares_channel channel, const char *str)
533     {
534     char lookups[3], *l;
535     const char *p;
536    
537     /* Set the lookup order. Only the first letter of each work
538     * is relevant, and it has to be "b" for DNS or "f" for the
539     * host file. Ignore everything else.
540     */
541     l = lookups;
542     p = str;
543     while (*p)
544     {
545     if ((*p == 'b' || *p == 'f') && l < lookups + 2)
546     *l++ = *p;
547     while (*p && !isspace((unsigned char)*p))
548     p++;
549     while (isspace((unsigned char)*p))
550     p++;
551     }
552     *l = 0;
553     channel->lookups = strdup(lookups);
554     return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM;
555     }
556    
557     static int config_nameserver(struct server_state **servers, int *nservers,
558     const char *str)
559     {
560     struct in_addr addr;
561     struct server_state *newserv;
562 derek 5267 #ifdef USE_IPV6
563 rohan 3940 u_int8_t family;
564     struct in6_addr addr6;
565 ryker 1479
566     /* Add a nameserver entry, if this is a valid address. */
567 rohan 3940
568     if (inet_pton4(str, (u_char *) & addr)) /* is it an IPv4 address? */
569     family = AF_INET;
570     else
571     {
572     if (inet_pton6(str, (u_char *) & addr6)) /* how about an IPv6 address? */
573     family = AF_INET6;
574     else
575     return ARES_SUCCESS; /* nope, it was garbage, return early */
576     }
577     #else
578     /* Add a nameserver entry, if this is a valid address. */
579    
580     if (!inet_pton4(str, (u_char *) & addr)) /* is it an IPv4 address? */
581     return ARES_SUCCESS; /* nope, it was garbage, return early */
582     #endif
583    
584 ryker 1479 newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
585     if (!newserv)
586     return ARES_ENOMEM;
587 rohan 3940
588 derek 5267 #ifdef USE_IPV6
589 rohan 3940 newserv[*nservers].family = family;
590     if (family == AF_INET6)
591     newserv[*nservers].addr6 = addr6;
592     else
593     #endif
594     newserv[*nservers].addr = addr;
595    
596 ryker 1479 *servers = newserv;
597     (*nservers)++;
598     return ARES_SUCCESS;
599     }
600    
601     static int config_sortlist(struct apattern **sortlist, int *nsort,
602     const char *str)
603     {
604     struct apattern pat, *newsort;
605     const char *q;
606    
607     /* Add sortlist entries. */
608     while (*str && *str != ';')
609     {
610     q = str;
611     while (*q && *q != '/' && *q != ';' && !isspace((unsigned char)*q))
612     q++;
613     if (ip_addr(str, q - str, &pat.addr) == 0)
614     {
615     /* We have a pattern address; now determine the mask. */
616     if (*q == '/')
617     {
618     str = q + 1;
619     while (*q && *q != ';' && !isspace((unsigned char)*q))
620     q++;
621     if (ip_addr(str, q - str, &pat.mask) != 0)
622     natural_mask(&pat);
623     }
624     else
625     natural_mask(&pat);
626    
627     /* Add this pattern to our list. */
628     newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
629     if (!newsort)
630     return ARES_ENOMEM;
631     newsort[*nsort] = pat;
632     *sortlist = newsort;
633     (*nsort)++;
634     }
635     else
636     {
637     while (*q && *q != ';' && !isspace((unsigned char)*q))
638     q++;
639     }
640     str = q;
641     while (isspace((unsigned char)*str))
642     str++;
643     }
644    
645     return ARES_SUCCESS;
646     }
647    
648     static int set_search(ares_channel channel, const char *str)
649     {
650     int n;
651     const char *p, *q;
652    
653     /* Count the domains given. */
654     n = 0;
655     p = str;
656     while (*p)
657     {
658     while (*p && !isspace((unsigned char)*p))
659     p++;
660     while (isspace((unsigned char)*p))
661     p++;
662     n++;
663     }
664    
665     channel->domains = malloc(n * sizeof(char *));
666     if (!channel->domains && n)
667     return ARES_ENOMEM;
668    
669     /* Now copy the domains. */
670     n = 0;
671     p = str;
672     while (*p)
673     {
674     channel->ndomains = n;
675     q = p;
676     while (*q && !isspace((unsigned char)*q))
677     q++;
678     channel->domains[n] = malloc(q - p + 1);
679     if (!channel->domains[n])
680     return ARES_ENOMEM;
681     memcpy(channel->domains[n], p, q - p);
682     channel->domains[n][q - p] = 0;
683     p = q;
684     while (isspace((unsigned char)*p))
685     p++;
686     n++;
687     }
688     channel->ndomains = n;
689    
690     return ARES_SUCCESS;
691     }
692    
693     static int set_options(ares_channel channel, const char *str)
694     {
695     const char *p, *q, *val;
696    
697     p = str;
698     while (*p)
699     {
700     q = p;
701     while (*q && !isspace((unsigned char)*q))
702     q++;
703     val = try_option(p, q, "ndots:");
704     if (val && channel->ndots == -1)
705     channel->ndots = atoi(val);
706     val = try_option(p, q, "retrans:");
707     if (val && channel->timeout == -1)
708     channel->timeout = atoi(val);
709     val = try_option(p, q, "retry:");
710     if (val && channel->tries == -1)
711     channel->tries = atoi(val);
712     p = q;
713     while (isspace((unsigned char)*p))
714     p++;
715     }
716    
717     return ARES_SUCCESS;
718     }
719    
720     static char *try_config(char *s, char *opt)
721     {
722     int len;
723    
724     len = strlen(opt);
725     if (strncmp(s, opt, len) != 0 || !isspace((unsigned char)s[len]))
726     return NULL;
727     s += len;
728     while (isspace((unsigned char)*s))
729     s++;
730     return s;
731     }
732    
733     static const char *try_option(const char *p, const char *q, const char *opt)
734     {
735     int len;
736    
737     len = strlen(opt);
738     return (q - p > len && strncmp(p, opt, len) == 0) ? p + len : NULL;
739     }
740    
741     static int ip_addr(const char *s, int len, struct in_addr *addr)
742     {
743     char ipbuf[16];
744    
745     /* Four octets and three periods yields at most 15 characters. */
746     if (len > 15)
747     return -1;
748     memcpy(ipbuf, s, len);
749     ipbuf[len] = 0;
750    
751     addr->s_addr = inet_addr(ipbuf);
752     if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
753     return -1;
754     return 0;
755     }
756    
757     static void natural_mask(struct apattern *pat)
758     {
759     struct in_addr addr;
760    
761     /* Store a host-byte-order copy of pat in a struct in_addr. Icky,
762     * but portable.
763     */
764     addr.s_addr = ntohl(pat->addr.s_addr);
765    
766     /* This is out of date in the CIDR world, but some people might
767     * still rely on it.
768     */
769     if (IN_CLASSA(addr.s_addr))
770     pat->mask.s_addr = htonl(IN_CLASSA_NET);
771     else if (IN_CLASSB(addr.s_addr))
772     pat->mask.s_addr = htonl(IN_CLASSB_NET);
773     else
774     pat->mask.s_addr = htonl(IN_CLASSC_NET);
775     }
776 rohan 3940
777     #define NS_INT16SZ 2
778     #define NS_INADDRSZ 4
779     #define NS_IN6ADDRSZ 16
780    
781 derek 5267 #ifdef USE_IPV6
782 rohan 3940 /* int
783     * inet_pton6(src, dst)
784     * convert presentation level address to network order binary form.
785     * return:
786     * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
787     * notice:
788     * (1) does not touch `dst' unless it's returning 1.
789     * (2) :: in a full address is silently ignored.
790     * credit:
791     * inspired by Mark Andrews.
792     * author:
793     * Paul Vixie, 1996.
794     */
795     static int
796     inet_pton6(const char *src, u_char *dst)
797     {
798     static const char xdigits_l[] = "0123456789abcdef",
799     xdigits_u[] = "0123456789ABCDEF";
800     u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
801     const char *xdigits, *curtok;
802     int ch, saw_xdigit;
803     u_int val;
804    
805     memset((tp = tmp), '\0', NS_IN6ADDRSZ);
806     endp = tp + NS_IN6ADDRSZ;
807     colonp = NULL;
808     /* Leading :: requires some special handling. */
809     if (*src == ':')
810     if (*++src != ':')
811     return (0);
812     curtok = src;
813     saw_xdigit = 0;
814     val = 0;
815     while ((ch = *src++) != '\0') {
816     const char *pch;
817    
818     if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
819     pch = strchr((xdigits = xdigits_u), ch);
820     if (pch != NULL) {
821     val <<= 4;
822     val |= (pch - xdigits);
823     if (val > 0xffff)
824     return (0);
825     saw_xdigit = 1;
826     continue;
827     }
828     if (ch == ':') {
829     curtok = src;
830     if (!saw_xdigit) {
831     if (colonp)
832     return (0);
833     colonp = tp;
834     continue;
835     }
836     if (tp + NS_INT16SZ > endp)
837     return (0);
838     *tp++ = (u_char) (val >> 8) & 0xff;
839     *tp++ = (u_char) val & 0xff;
840     saw_xdigit = 0;
841     val = 0;
842     continue;
843     }
844     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
845     inet_pton4(curtok, tp) > 0) {
846     tp += NS_INADDRSZ;
847     saw_xdigit = 0;
848     break; /* '\0' was seen by inet_pton4(). */
849     }
850     return (0);
851     }
852     if (saw_xdigit) {
853     if (tp + NS_INT16SZ > endp)
854     return (0);
855     *tp++ = (u_char) (val >> 8) & 0xff;
856     *tp++ = (u_char) val & 0xff;
857     }
858     if (colonp != NULL) {
859     /*
860     * Since some memmove()'s erroneously fail to handle
861     * overlapping regions, we'll do the shift by hand.
862     */
863     const int n = tp - colonp;
864     int i;
865    
866     for (i = 1; i <= n; i++) {
867     endp[- i] = colonp[n - i];
868     colonp[n - i] = 0;
869     }
870     tp = endp;
871     }
872     if (tp != endp)
873     return (0);
874     memcpy(dst, tmp, NS_IN6ADDRSZ);
875     return (1);
876     }
877    
878     #endif
879    
880     /* int
881     * inet_pton4(src, dst)
882     * like inet_aton() but without all the hexadecimal and shorthand.
883     * return:
884     * 1 if `src' is a valid dotted quad, else 0.
885     * notice:
886     * does not touch `dst' unless it's returning 1.
887     * author:
888     * Paul Vixie, 1996.
889     */
890     static int
891     inet_pton4(const char *src, u_char *dst)
892     {
893     static const char digits[] = "0123456789";
894     int saw_digit, octets, ch;
895     u_char tmp[NS_INADDRSZ], *tp;
896    
897     saw_digit = 0;
898     octets = 0;
899     *(tp = tmp) = 0;
900     while ((ch = *src++) != '\0') {
901     const char *pch;
902    
903     if ((pch = strchr(digits, ch)) != NULL) {
904     u_int newVal = *tp * 10 + (pch - digits);
905    
906     if (newVal > 255)
907     return (0);
908     *tp = newVal;
909     if (! saw_digit) {
910     if (++octets > 4)
911     return (0);
912     saw_digit = 1;
913     }
914     } else if (ch == '.' && saw_digit) {
915     if (octets == 4)
916     return (0);
917     *++tp = 0;
918     saw_digit = 0;
919     } else
920     return (0);
921     }
922     if (octets < 4)
923     return (0);
924    
925     memcpy(dst, tmp, NS_INADDRSZ);
926     return (1);
927 dlb 5080 }

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27