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