summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/gethostnamadr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/gethostnamadr.c')
-rw-r--r--src/lib/libc/net/gethostnamadr.c1079
1 files changed, 1079 insertions, 0 deletions
diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c
new file mode 100644
index 0000000000..7321225863
--- /dev/null
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -0,0 +1,1079 @@
1/*-
2 * Copyright (c) 1985, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 * -
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.30 1998/03/16 05:06:55 millert Exp $";
56#endif /* LIBC_SCCS and not lint */
57
58#include <sys/param.h>
59#include <sys/socket.h>
60#include <netinet/in.h>
61#include <arpa/inet.h>
62#include <arpa/nameser.h>
63#include <netdb.h>
64#include <resolv.h>
65#include <stdio.h>
66#include <ctype.h>
67#include <errno.h>
68#include <string.h>
69#include <syslog.h>
70#ifdef YP
71#include <rpc/rpc.h>
72#include <rpcsvc/yp.h>
73#include <rpcsvc/ypclnt.h>
74#include "ypinternal.h"
75#endif
76
77#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
78
79#define MAXALIASES 35
80#define MAXADDRS 35
81
82static char *h_addr_ptrs[MAXADDRS + 1];
83
84#ifdef YP
85static char *__ypdomain;
86#endif
87
88static struct hostent host;
89static char *host_aliases[MAXALIASES];
90static char hostbuf[BUFSIZ+1];
91static union {
92 struct in_addr _host_in_addr;
93 u_char _host_addr[16]; /* IPv4 or IPv6 */
94} _host_addr_u;
95#define host_addr _host_addr_u._host_addr
96static FILE *hostf = NULL;
97static int stayopen = 0;
98
99static void map_v4v6_address __P((const char *src, char *dst));
100static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
101
102#ifdef RESOLVSORT
103static void addrsort __P((char **, int));
104#endif
105
106int _hokchar __P((const char *));
107
108static const char AskedForGot[] =
109 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
110
111#if PACKETSZ > 1024
112#define MAXPACKET PACKETSZ
113#else
114#define MAXPACKET 1024
115#endif
116
117typedef union {
118 HEADER hdr;
119 u_char buf[MAXPACKET];
120} querybuf;
121
122typedef union {
123 int32_t al;
124 char ac;
125} align;
126
127static struct hostent *getanswer __P((const querybuf *, int, const char *,
128 int));
129
130extern int h_errno;
131
132int
133_hokchar(p)
134 const char *p;
135{
136 char c;
137
138 /*
139 * Many people do not obey RFC 822 and 1035. The valid
140 * characters are a-z, A-Z, 0-9, '-' and . But the others
141 * tested for below can happen, and we must be more permissive
142 * than the resolver until those idiots clean up their act.
143 * We let '/' through, but not '..'
144 */
145 while ((c = *p++)) {
146 if (('a' <= c && c <= 'z') ||
147 ('A' <= c && c <= 'Z') ||
148 ('0' <= c && c <= '9'))
149 continue;
150 if (strchr("-_/", c))
151 continue;
152 if (c == '.' && *p != '.')
153 continue;
154 return 0;
155 }
156 return 1;
157}
158
159static struct hostent *
160getanswer(answer, anslen, qname, qtype)
161 const querybuf *answer;
162 int anslen;
163 const char *qname;
164 int qtype;
165{
166 register const HEADER *hp;
167 register const u_char *cp;
168 register int n;
169 const u_char *eom;
170 char *bp, **ap, **hap;
171 int type, class, buflen, ancount, qdcount;
172 int haveanswer, had_error;
173 int toobig = 0;
174 char tbuf[MAXDNAME];
175 const char *tname;
176 int (*name_ok) __P((const char *));
177
178 tname = qname;
179 host.h_name = NULL;
180 eom = answer->buf + anslen;
181 switch (qtype) {
182 case T_A:
183 case T_AAAA:
184#ifdef USE_RESOLV_NAME_OK
185 name_ok = res_hnok;
186 break;
187#endif
188 case T_PTR:
189#ifdef USE_RESOLV_NAME_OK
190 name_ok = res_dnok;
191#else
192 name_ok = _hokchar;
193#endif
194 break;
195 default:
196 return (NULL);
197 }
198 /*
199 * find first satisfactory answer
200 */
201 hp = &answer->hdr;
202 ancount = ntohs(hp->ancount);
203 qdcount = ntohs(hp->qdcount);
204 bp = hostbuf;
205 buflen = sizeof hostbuf;
206 cp = answer->buf + HFIXEDSZ;
207 if (qdcount != 1) {
208 h_errno = NO_RECOVERY;
209 return (NULL);
210 }
211 n = dn_expand(answer->buf, eom, cp, bp, buflen);
212 if ((n < 0) || !(*name_ok)(bp)) {
213 h_errno = NO_RECOVERY;
214 return (NULL);
215 }
216 cp += n + QFIXEDSZ;
217 if (qtype == T_A || qtype == T_AAAA) {
218 /* res_send() has already verified that the query name is the
219 * same as the one we sent; this just gets the expanded name
220 * (i.e., with the succeeding search-domain tacked on).
221 */
222 n = strlen(bp) + 1; /* for the \0 */
223 host.h_name = bp;
224 bp += n;
225 buflen -= n;
226 /* The qname can be abbreviated, but h_name is now absolute. */
227 qname = host.h_name;
228 }
229 ap = host_aliases;
230 *ap = NULL;
231 host.h_aliases = host_aliases;
232 hap = h_addr_ptrs;
233 *hap = NULL;
234 host.h_addr_list = h_addr_ptrs;
235 haveanswer = 0;
236 had_error = 0;
237 while (ancount-- > 0 && cp < eom && !had_error) {
238 n = dn_expand(answer->buf, eom, cp, bp, buflen);
239 if ((n < 0) || !(*name_ok)(bp)) {
240 had_error++;
241 continue;
242 }
243 cp += n; /* name */
244 type = _getshort(cp);
245 cp += INT16SZ; /* type */
246 class = _getshort(cp);
247 cp += INT16SZ + INT32SZ; /* class, TTL */
248 n = _getshort(cp);
249 cp += INT16SZ; /* len */
250 if (class != C_IN) {
251 /* XXX - debug? syslog? */
252 cp += n;
253 continue; /* XXX - had_error++ ? */
254 }
255 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
256 if (ap >= &host_aliases[MAXALIASES-1])
257 continue;
258 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
259 if ((n < 0) || !(*name_ok)(tbuf)) {
260 had_error++;
261 continue;
262 }
263 cp += n;
264 /* Store alias. */
265 *ap++ = bp;
266 n = strlen(bp) + 1; /* for the \0 */
267 bp += n;
268 buflen -= n;
269 /* Get canonical name. */
270 n = strlen(tbuf) + 1; /* for the \0 */
271 if (n > buflen) {
272 had_error++;
273 continue;
274 }
275 strcpy(bp, tbuf);
276 host.h_name = bp;
277 bp += n;
278 buflen -= n;
279 continue;
280 }
281 if (qtype == T_PTR && type == T_CNAME) {
282 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
283 if ((n < 0) || !res_hnok(tbuf)) {
284 had_error++;
285 continue;
286 }
287 cp += n;
288 /* Get canonical name. */
289 n = strlen(tbuf) + 1; /* for the \0 */
290 if (n > buflen) {
291 had_error++;
292 continue;
293 }
294 strcpy(bp, tbuf);
295 tname = bp;
296 bp += n;
297 buflen -= n;
298 continue;
299 }
300 if (type != qtype) {
301 syslog(LOG_NOTICE|LOG_AUTH,
302 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
303 qname, p_class(C_IN), p_type(qtype),
304 p_type(type));
305 cp += n;
306 continue; /* XXX - had_error++ ? */
307 }
308 switch (type) {
309 case T_PTR:
310 if (strcasecmp(tname, bp) != 0) {
311 syslog(LOG_NOTICE|LOG_AUTH,
312 AskedForGot, qname, bp);
313 cp += n;
314 continue; /* XXX - had_error++ ? */
315 }
316 n = dn_expand(answer->buf, eom, cp, bp, buflen);
317 if ((n < 0) || !res_hnok(bp)) {
318 had_error++;
319 break;
320 }
321#if MULTI_PTRS_ARE_ALIASES
322 cp += n;
323 if (!haveanswer)
324 host.h_name = bp;
325 else if (ap < &host_aliases[MAXALIASES-1])
326 *ap++ = bp;
327 else
328 n = -1;
329 if (n != -1) {
330 n = strlen(bp) + 1; /* for the \0 */
331 bp += n;
332 buflen -= n;
333 }
334 break;
335#else
336 host.h_name = bp;
337 if (_res.options & RES_USE_INET6) {
338 n = strlen(bp) + 1; /* for the \0 */
339 bp += n;
340 buflen -= n;
341 map_v4v6_hostent(&host, &bp, &buflen);
342 }
343 h_errno = NETDB_SUCCESS;
344 return (&host);
345#endif
346 case T_A:
347 case T_AAAA:
348 if (strcasecmp(host.h_name, bp) != 0) {
349 syslog(LOG_NOTICE|LOG_AUTH,
350 AskedForGot, host.h_name, bp);
351 cp += n;
352 continue; /* XXX - had_error++ ? */
353 }
354 if (n != host.h_length) {
355 cp += n;
356 continue;
357 }
358 if (!haveanswer) {
359 register int nn;
360
361 host.h_name = bp;
362 nn = strlen(bp) + 1; /* for the \0 */
363 bp += nn;
364 buflen -= nn;
365 }
366
367 bp += sizeof(align) - ((u_long)bp % sizeof(align));
368
369 if (bp + n >= &hostbuf[sizeof hostbuf]) {
370#ifdef DEBUG
371 if (_res.options & RES_DEBUG)
372 printf("size (%d) too big\n", n);
373#endif
374 had_error++;
375 continue;
376 }
377 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
378 if (!toobig++)
379#ifdef DEBUG
380 if (_res.options & RES_DEBUG)
381 printf("Too many addresses (%d)\n", MAXADDRS);
382#endif
383 cp += n;
384 continue;
385 }
386 bcopy(cp, *hap++ = bp, n);
387 bp += n;
388 buflen -= n;
389 cp += n;
390 break;
391 }
392 if (!had_error)
393 haveanswer++;
394 }
395 if (haveanswer) {
396 *ap = NULL;
397 *hap = NULL;
398# if defined(RESOLVSORT)
399 /*
400 * Note: we sort even if host can take only one address
401 * in its return structures - should give it the "best"
402 * address in that case, not some random one
403 */
404 if (_res.nsort && haveanswer > 1 && qtype == T_A)
405 addrsort(h_addr_ptrs, haveanswer);
406# endif /*RESOLVSORT*/
407 if (!host.h_name) {
408 n = strlen(qname) + 1; /* for the \0 */
409 if (n > buflen)
410 goto try_again;
411 strcpy(bp, qname);
412 host.h_name = bp;
413 bp += n;
414 buflen -= n;
415 }
416 if (_res.options & RES_USE_INET6)
417 map_v4v6_hostent(&host, &bp, &buflen);
418 h_errno = NETDB_SUCCESS;
419 return (&host);
420 }
421 try_again:
422 h_errno = TRY_AGAIN;
423 return (NULL);
424}
425
426struct hostent *
427gethostbyname(name)
428 const char *name;
429{
430 struct hostent *hp;
431 extern struct hostent *_gethtbyname2();
432
433 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
434 return (_gethtbyname2(name, AF_INET));
435
436 if (_res.options & RES_USE_INET6) {
437 hp = gethostbyname2(name, AF_INET6);
438 if (hp)
439 return (hp);
440 }
441 return (gethostbyname2(name, AF_INET));
442}
443
444struct hostent *
445gethostbyname2(name, af)
446 const char *name;
447 int af;
448{
449 querybuf buf;
450 register const char *cp;
451 char *bp;
452 int n, size, type, len, i;
453 extern struct hostent *_gethtbyname2(), *_yp_gethtbyname();
454 register struct hostent *hp;
455 char lookups[MAXDNSLUS];
456
457 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
458 return (_gethtbyname2(name, af));
459
460 switch (af) {
461 case AF_INET:
462 size = INADDRSZ;
463 type = T_A;
464 break;
465 case AF_INET6:
466 size = IN6ADDRSZ;
467 type = T_AAAA;
468 break;
469 default:
470 h_errno = NETDB_INTERNAL;
471 errno = EAFNOSUPPORT;
472 return (NULL);
473 }
474
475 host.h_addrtype = af;
476 host.h_length = size;
477
478 /*
479 * if there aren't any dots, it could be a user-level alias.
480 * this is also done in res_query() since we are not the only
481 * function that looks up host names.
482 */
483 if (!strchr(name, '.') && (cp = __hostalias(name)))
484 name = cp;
485
486 /*
487 * disallow names consisting only of digits/dots, unless
488 * they end in a dot.
489 */
490 if (isdigit(name[0]))
491 for (cp = name;; ++cp) {
492 if (!*cp) {
493 if (*--cp == '.')
494 break;
495 /*
496 * All-numeric, no dot at the end.
497 * Fake up a hostent as if we'd actually
498 * done a lookup.
499 */
500 if (inet_pton(af, name, host_addr) <= 0) {
501 h_errno = HOST_NOT_FOUND;
502 return (NULL);
503 }
504 strncpy(hostbuf, name, MAXHOSTNAMELEN-1);
505 hostbuf[MAXHOSTNAMELEN-1] = '\0';
506 bp = hostbuf + MAXHOSTNAMELEN;
507 len = sizeof hostbuf - MAXHOSTNAMELEN;
508 host.h_name = hostbuf;
509 host.h_aliases = host_aliases;
510 host_aliases[0] = NULL;
511 h_addr_ptrs[0] = (char *)host_addr;
512 h_addr_ptrs[1] = NULL;
513 host.h_addr_list = h_addr_ptrs;
514 if (_res.options & RES_USE_INET6)
515 map_v4v6_hostent(&host, &bp, &len);
516 h_errno = NETDB_SUCCESS;
517 return (&host);
518 }
519 if (!isdigit(*cp) && *cp != '.')
520 break;
521 }
522 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
523 name[0] == ':')
524 for (cp = name;; ++cp) {
525 if (!*cp) {
526 if (*--cp == '.')
527 break;
528 /*
529 * All-IPv6-legal, no dot at the end.
530 * Fake up a hostent as if we'd actually
531 * done a lookup.
532 */
533 if (inet_pton(af, name, host_addr) <= 0) {
534 h_errno = HOST_NOT_FOUND;
535 return (NULL);
536 }
537 strncpy(hostbuf, name, MAXHOSTNAMELEN-1);
538 hostbuf[MAXHOSTNAMELEN-1] = '\0';
539 bp = hostbuf + MAXHOSTNAMELEN;
540 len = sizeof hostbuf - MAXHOSTNAMELEN;
541 host.h_name = hostbuf;
542 host.h_aliases = host_aliases;
543 host_aliases[0] = NULL;
544 h_addr_ptrs[0] = (char *)host_addr;
545 h_addr_ptrs[1] = NULL;
546 host.h_addr_list = h_addr_ptrs;
547 h_errno = NETDB_SUCCESS;
548 return (&host);
549 }
550 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
551 break;
552 }
553
554 bcopy(_res.lookups, lookups, sizeof lookups);
555 if (lookups[0] == '\0')
556 strncpy(lookups, "bf", sizeof lookups);
557
558 hp = (struct hostent *)NULL;
559 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
560 switch (lookups[i]) {
561#ifdef YP
562 case 'y':
563 /* YP only supports AF_INET. */
564 if (af == AF_INET)
565 hp = _yp_gethtbyname(name);
566 break;
567#endif
568 case 'b':
569 if ((n = res_search(name, C_IN, type, buf.buf,
570 sizeof(buf))) < 0) {
571#ifdef DEBUG
572 if (_res.options & RES_DEBUG)
573 printf("res_search failed\n");
574#endif
575 break;
576 }
577 hp = getanswer(&buf, n, name, type);
578 break;
579 case 'f':
580 hp = _gethtbyname2(name, af);
581 break;
582 }
583 }
584 /* XXX h_errno not correct in all cases... */
585 return (hp);
586}
587
588struct hostent *
589gethostbyaddr(addr, len, af)
590 const char *addr; /* XXX should have been def'd as u_char! */
591 int len, af;
592{
593 const u_char *uaddr = (const u_char *)addr;
594 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
595 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
596 int n, size, i;
597 querybuf buf;
598 register struct hostent *hp;
599 char qbuf[MAXDNAME+1], *qp;
600 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr();
601 char lookups[MAXDNSLUS];
602
603 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
604 return (_gethtbyaddr(addr, len, af));
605
606 if (af == AF_INET6 && len == IN6ADDRSZ &&
607 (!bcmp(uaddr, mapped, sizeof mapped) ||
608 !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
609 /* Unmap. */
610 addr += sizeof mapped;
611 uaddr += sizeof mapped;
612 af = AF_INET;
613 len = INADDRSZ;
614 }
615 switch (af) {
616 case AF_INET:
617 size = INADDRSZ;
618 break;
619 case AF_INET6:
620 size = IN6ADDRSZ;
621 break;
622 default:
623 errno = EAFNOSUPPORT;
624 h_errno = NETDB_INTERNAL;
625 return (NULL);
626 }
627 if (size != len) {
628 errno = EINVAL;
629 h_errno = NETDB_INTERNAL;
630 return (NULL);
631 }
632 switch (af) {
633 case AF_INET:
634 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
635 (uaddr[3] & 0xff),
636 (uaddr[2] & 0xff),
637 (uaddr[1] & 0xff),
638 (uaddr[0] & 0xff));
639 break;
640 case AF_INET6:
641 qp = qbuf;
642 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
643 qp += sprintf(qp, "%x.%x.",
644 uaddr[n] & 0xf,
645 (uaddr[n] >> 4) & 0xf);
646 }
647 strcpy(qp, "ip6.int");
648 break;
649 }
650
651 bcopy(_res.lookups, lookups, sizeof lookups);
652 if (lookups[0] == '\0')
653 strncpy(lookups, "bf", sizeof lookups);
654
655 hp = (struct hostent *)NULL;
656 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
657 switch (lookups[i]) {
658#ifdef YP
659 case 'y':
660 /* YP only supports AF_INET. */
661 if (af == AF_INET)
662 hp = _yp_gethtbyaddr(addr);
663 break;
664#endif
665 case 'b':
666 n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf,
667 sizeof buf.buf);
668 if (n < 0) {
669#ifdef DEBUG
670 if (_res.options & RES_DEBUG)
671 printf("res_query failed\n");
672#endif
673 break;
674 }
675 if (!(hp = getanswer(&buf, n, qbuf, T_PTR)))
676 break;
677 hp->h_addrtype = af;
678 hp->h_length = len;
679 bcopy(addr, host_addr, len);
680 h_addr_ptrs[0] = (char *)host_addr;
681 h_addr_ptrs[1] = NULL;
682 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
683 map_v4v6_address((char*)host_addr,
684 (char*)host_addr);
685 hp->h_addrtype = AF_INET6;
686 hp->h_length = IN6ADDRSZ;
687 }
688 h_errno = NETDB_SUCCESS;
689 break;
690 case 'f':
691 hp = _gethtbyaddr(addr, len, af);
692 break;
693 }
694 }
695 /* XXX h_errno not correct in all cases... */
696 return (hp);
697}
698
699void
700_sethtent(f)
701 int f;
702{
703 if (hostf == NULL)
704 hostf = fopen(_PATH_HOSTS, "r" );
705 else
706 rewind(hostf);
707 stayopen = f;
708}
709
710void
711_endhtent()
712{
713 if (hostf && !stayopen) {
714 (void) fclose(hostf);
715 hostf = NULL;
716 }
717}
718
719struct hostent *
720_gethtent()
721{
722 char *p;
723 register char *cp, **q;
724 int af;
725 size_t len;
726
727 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
728 h_errno = NETDB_INTERNAL;
729 return (NULL);
730 }
731 again:
732 if ((p = fgetln(hostf, &len)) == NULL) {
733 h_errno = HOST_NOT_FOUND;
734 return (NULL);
735 }
736 if (p[len-1] == '\n')
737 len--;
738 if (len >= sizeof(hostbuf) || len == 0)
739 goto again;
740 p = memcpy(hostbuf, p, len);
741 hostbuf[len] = '\0';
742 if (*p == '#')
743 goto again;
744 if ((cp = strchr(p, '#')))
745 *cp = '\0';
746 if (!(cp = strpbrk(p, " \t")))
747 goto again;
748 *cp++ = '\0';
749 if ((_res.options & RES_USE_INET6) &&
750 inet_pton(AF_INET6, p, host_addr) > 0) {
751 af = AF_INET6;
752 len = IN6ADDRSZ;
753 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
754 if (_res.options & RES_USE_INET6) {
755 map_v4v6_address((char*)host_addr, (char*)host_addr);
756 af = AF_INET6;
757 len = IN6ADDRSZ;
758 } else {
759 af = AF_INET;
760 len = INADDRSZ;
761 }
762 } else {
763 goto again;
764 }
765 h_addr_ptrs[0] = (char *)host_addr;
766 h_addr_ptrs[1] = NULL;
767 host.h_addr_list = h_addr_ptrs;
768 host.h_length = len;
769 host.h_addrtype = af;
770 while (*cp == ' ' || *cp == '\t')
771 cp++;
772 host.h_name = cp;
773 q = host.h_aliases = host_aliases;
774 if ((cp = strpbrk(cp, " \t")))
775 *cp++ = '\0';
776 while (cp && *cp) {
777 if (*cp == ' ' || *cp == '\t') {
778 cp++;
779 continue;
780 }
781 if (q < &host_aliases[MAXALIASES - 1])
782 *q++ = cp;
783 if ((cp = strpbrk(cp, " \t")))
784 *cp++ = '\0';
785 }
786 *q = NULL;
787 if (_res.options & RES_USE_INET6) {
788 char *bp = hostbuf;
789 int buflen = sizeof hostbuf;
790
791 map_v4v6_hostent(&host, &bp, &buflen);
792 }
793 h_errno = NETDB_SUCCESS;
794 return (&host);
795}
796
797struct hostent *
798_gethtbyname(name)
799 const char *name;
800{
801 extern struct hostent *_gethtbyname2();
802 struct hostent *hp;
803
804 if (_res.options & RES_USE_INET6) {
805 hp = _gethtbyname2(name, AF_INET6);
806 if (hp)
807 return (hp);
808 }
809 return (_gethtbyname2(name, AF_INET));
810}
811
812struct hostent *
813_gethtbyname2(name, af)
814 const char *name;
815 int af;
816{
817 register struct hostent *p;
818 register char **cp;
819
820 _sethtent(0);
821 while ((p = _gethtent())) {
822 if (p->h_addrtype != af)
823 continue;
824 if (strcasecmp(p->h_name, name) == 0)
825 break;
826 for (cp = p->h_aliases; *cp != 0; cp++)
827 if (strcasecmp(*cp, name) == 0)
828 goto found;
829 }
830 found:
831 _endhtent();
832 return (p);
833}
834
835struct hostent *
836_gethtbyaddr(addr, len, af)
837 const char *addr;
838 int len, af;
839{
840 register struct hostent *p;
841
842 _sethtent(0);
843 while ((p = _gethtent()))
844 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
845 break;
846 _endhtent();
847 return (p);
848}
849
850#ifdef YP
851struct hostent *
852_yphostent(line)
853 char *line;
854{
855 static struct in_addr host_addrs[MAXADDRS];
856 char *p = line;
857 char *cp, **q;
858 char **hap;
859 struct in_addr *buf;
860 int more;
861
862 host.h_name = NULL;
863 host.h_addr_list = h_addr_ptrs;
864 host.h_length = INADDRSZ;
865 host.h_addrtype = AF_INET;
866 hap = h_addr_ptrs;
867 buf = host_addrs;
868 q = host.h_aliases = host_aliases;
869
870nextline:
871 more = 0;
872 cp = strpbrk(p, " \t");
873 if (cp == NULL) {
874 if (host.h_name == NULL)
875 return (NULL);
876 else
877 goto done;
878 }
879 *cp++ = '\0';
880
881 *hap++ = (char *)buf;
882 (void) inet_aton(p, buf++);
883
884 while (*cp == ' ' || *cp == '\t')
885 cp++;
886 p = cp;
887 cp = strpbrk(p, " \t\n");
888 if (cp != NULL) {
889 if (*cp == '\n')
890 more = 1;
891 *cp++ = '\0';
892 }
893 if (!host.h_name)
894 host.h_name = p;
895 else if (strcmp(host.h_name, p)==0)
896 ;
897 else if (q < &host_aliases[MAXALIASES - 1])
898 *q++ = p;
899 p = cp;
900 if (more)
901 goto nextline;
902
903 while (cp && *cp) {
904 if (*cp == ' ' || *cp == '\t') {
905 cp++;
906 continue;
907 }
908 if (*cp == '\n') {
909 cp++;
910 goto nextline;
911 }
912 if (q < &host_aliases[MAXALIASES - 1])
913 *q++ = cp;
914 cp = strpbrk(cp, " \t");
915 if (cp != NULL)
916 *cp++ = '\0';
917 }
918done:
919 *q = NULL;
920 *hap = NULL;
921 return (&host);
922}
923
924struct hostent *
925_yp_gethtbyaddr(addr)
926 const char *addr;
927{
928 struct hostent *hp = (struct hostent *)NULL;
929 static char *__ypcurrent;
930 int __ypcurrentlen, r;
931 char name[sizeof("xxx.xxx.xxx.xxx") + 1];
932
933 if (!__ypdomain) {
934 if (_yp_check(&__ypdomain) == 0)
935 return (hp);
936 }
937 sprintf(name, "%u.%u.%u.%u",
938 ((unsigned)addr[0] & 0xff),
939 ((unsigned)addr[1] & 0xff),
940 ((unsigned)addr[2] & 0xff),
941 ((unsigned)addr[3] & 0xff));
942 if (__ypcurrent)
943 free(__ypcurrent);
944 __ypcurrent = NULL;
945 r = yp_match(__ypdomain, "hosts.byaddr", name,
946 strlen(name), &__ypcurrent, &__ypcurrentlen);
947 if (r==0)
948 hp = _yphostent(__ypcurrent);
949 if (hp==NULL)
950 h_errno = HOST_NOT_FOUND;
951 return (hp);
952}
953
954struct hostent *
955_yp_gethtbyname(name)
956 const char *name;
957{
958 struct hostent *hp = (struct hostent *)NULL;
959 static char *__ypcurrent;
960 int __ypcurrentlen, r;
961
962 if (strlen(name) >= MAXHOSTNAMELEN)
963 return (NULL);
964 if (!__ypdomain) {
965 if (_yp_check(&__ypdomain) == 0)
966 return (hp);
967 }
968 if (__ypcurrent)
969 free(__ypcurrent);
970 __ypcurrent = NULL;
971 r = yp_match(__ypdomain, "hosts.byname", name,
972 strlen(name), &__ypcurrent, &__ypcurrentlen);
973 if (r == 0)
974 hp = _yphostent(__ypcurrent);
975 if (hp == NULL)
976 h_errno = HOST_NOT_FOUND;
977 return (hp);
978}
979#endif
980
981static void
982map_v4v6_address(src, dst)
983 const char *src;
984 char *dst;
985{
986 u_char *p = (u_char *)dst;
987 char tmp[INADDRSZ];
988 int i;
989
990 /* Stash a temporary copy so our caller can update in place. */
991 bcopy(src, tmp, INADDRSZ);
992 /* Mark this ipv6 addr as a mapped ipv4. */
993 for (i = 0; i < 10; i++)
994 *p++ = 0x00;
995 *p++ = 0xff;
996 *p++ = 0xff;
997 /* Retrieve the saved copy and we're done. */
998 bcopy(tmp, (void*)p, INADDRSZ);
999}
1000
1001static void
1002map_v4v6_hostent(hp, bpp, lenp)
1003 struct hostent *hp;
1004 char **bpp;
1005 int *lenp;
1006{
1007 char **ap;
1008
1009 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1010 return;
1011 hp->h_addrtype = AF_INET6;
1012 hp->h_length = IN6ADDRSZ;
1013 for (ap = hp->h_addr_list; *ap; ap++) {
1014 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1015
1016 if (*lenp < (i + IN6ADDRSZ)) {
1017 /* Out of memory. Truncate address list here. XXX */
1018 *ap = NULL;
1019 return;
1020 }
1021 *bpp += i;
1022 *lenp -= i;
1023 map_v4v6_address(*ap, *bpp);
1024 *ap = *bpp;
1025 *bpp += IN6ADDRSZ;
1026 *lenp -= IN6ADDRSZ;
1027 }
1028}
1029
1030struct hostent *
1031gethostent()
1032{
1033 return (_gethtent());
1034}
1035
1036#ifdef RESOLVSORT
1037static void
1038addrsort(ap, num)
1039 char **ap;
1040 int num;
1041{
1042 int i, j;
1043 char **p;
1044 short aval[MAXADDRS];
1045 int needsort = 0;
1046
1047 p = ap;
1048 for (i = 0; i < num; i++, p++) {
1049 for (j = 0 ; (unsigned)j < _res.nsort; j++)
1050 if (_res.sort_list[j].addr.s_addr ==
1051 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
1052 break;
1053 aval[i] = j;
1054 if (needsort == 0 && i > 0 && j < aval[i-1])
1055 needsort = i;
1056 }
1057 if (!needsort)
1058 return;
1059
1060 while (needsort < num) {
1061 for (j = needsort - 1; j >= 0; j--) {
1062 if (aval[j] > aval[j+1]) {
1063 char *hp;
1064
1065 i = aval[j];
1066 aval[j] = aval[j+1];
1067 aval[j+1] = i;
1068
1069 hp = ap[j];
1070 ap[j] = ap[j+1];
1071 ap[j+1] = hp;
1072
1073 } else
1074 break;
1075 }
1076 needsort++;
1077 }
1078}
1079#endif