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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27