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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5269 - (show annotations) (download)
Thu Aug 18 23:28:40 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: 24118 byte(s)
run detection of ares/resip USE_IPV6 mismatch
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
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 #include <assert.h>
24
25 #ifndef WIN32
26 #include <sys/time.h>
27 #include <sys/param.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 #include <sys/socket.h>
31 #ifndef __CYGWIN__
32 # include <arpa/nameser.h>
33 #endif
34 #include <unistd.h>
35 #include <errno.h>
36 #include <netdb.h>
37 #else
38 #include <Winsock2.h>
39 #include <iphlpapi.h>
40 #include <io.h>
41 #include <Windns.h>
42 #endif
43
44 #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 static int inet_pton4(const char *src, u_char *dst);
66 #ifdef USE_IPV6
67 static int inet_pton6(const char *src, u_char *dst);
68 #endif
69
70 #ifdef WIN32
71 char w32hostspath[256];
72 #endif
73
74
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 int ares_init(ares_channel *channelptr)
86 {
87 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 ares_channel channel;
94 int i, status;
95 struct server_state *server;
96 #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
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 // gettimeofday(&tv, NULL);
185 // channel->next_id = (tv.tv_sec ^ tv.tv_usec ^ getpid()) & 0xffff;
186 {
187 static int cjNextID=1;
188 channel->next_id = cjNextID++;
189 }
190
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 channel->udp_port = options->udp_port;
213 if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
214 channel->tcp_port = options->tcp_port;
215
216 /* Copy the servers, if given. */
217 if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
218 {
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 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 }
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 channel->udp_port = htons(NAMESERVER_PORT);
367 if (channel->tcp_port == -1)
368 channel->tcp_port = htons(NAMESERVER_PORT);
369
370 if (channel->nservers == -1)
371 {
372 #ifdef WIN32
373 /*
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 int num;
382 DWORD (WINAPI *GetNetworkParams)(FIXED_INFO*, DWORD*);
383
384 hLib = LoadLibraryA("iphlpapi.dll");
385 if(!hLib)
386 {
387 return ARES_ENOTIMP;
388 }
389
390 (void*)GetNetworkParams = GetProcAddress(hLib, "GetNetworkParams");
391 if(!GetNetworkParams)
392 {
393 FreeLibrary(hLib);
394 return ARES_ENOTIMP;
395 }
396 //printf("ARES: figuring out DNS servers\n");
397 FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );
398 ulOutBufLen = sizeof( FIXED_INFO );
399
400 if( ERROR_BUFFER_OVERFLOW == (*GetNetworkParams)( FixedInfo, &ulOutBufLen ) )
401 {
402 GlobalFree( FixedInfo );
403 FixedInfo = (FIXED_INFO *)GlobalAlloc( GPTR, ulOutBufLen );
404 }
405
406 if ( dwRetVal = (*GetNetworkParams)( FixedInfo, &ulOutBufLen ) )
407 {
408 //printf("ARES: couldn't get network params\n");
409 GlobalFree( FixedInfo );
410 FreeLibrary(hLib);
411 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 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
440 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 }
450 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
460 GlobalFree( FixedInfo );
461 FreeLibrary(hLib);
462 }
463 #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
469 // need a way to test here if v4 or v6 is running
470 // if v4 is running...
471 channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK);
472 // 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 channel->nservers = 1;
476 #endif
477
478 }
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 channel->domains = 0; // malloc(0);
489 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 #ifdef USE_IPV6
563 u_int8_t family;
564 struct in6_addr addr6;
565
566 /* Add a nameserver entry, if this is a valid address. */
567
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 newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
585 if (!newserv)
586 return ARES_ENOMEM;
587
588 #ifdef USE_IPV6
589 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 *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
777 #define NS_INT16SZ 2
778 #define NS_INADDRSZ 4
779 #define NS_IN6ADDRSZ 16
780
781 #ifdef USE_IPV6
782 /* 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 }

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27