* elf/dl-reloc.c: Include "dynamic-link.h" at file scope.
[glibc.git] / resolv / gethnamaddr.c
blobd3c45d044615b3d5091f32b2ffb1712183908726
1 /*
2 * ++Copyright++ 1985, 1988, 1993
3 * -
4 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 * -
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51 * SOFTWARE.
52 * -
53 * --Copyright--
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
58 static char rcsid[] = "$Id$";
59 #endif /* LIBC_SCCS and not lint */
61 #include <sys/param.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <arpa/nameser.h>
67 #include <stdio.h>
68 #include <netdb.h>
69 #include <resolv.h>
70 #include <ctype.h>
71 #include <errno.h>
72 #include <syslog.h>
74 #ifndef LOG_AUTH
75 # define LOG_AUTH 0
76 #endif
78 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
80 #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
81 # include <string.h>
82 #else
83 # include "../conf/portability.h"
84 #endif
85 #if defined(USE_OPTIONS_H)
86 # include <../conf/options.h>
87 #endif
89 #ifdef SPRINTF_CHAR
90 # define SPRINTF(x) strlen(sprintf/**/x)
91 #else
92 # define SPRINTF(x) sprintf x
93 #endif
95 #define MAXALIASES 35
96 #define MAXADDRS 35
98 static const char AskedForGot[] =
99 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
101 static char *h_addr_ptrs[MAXADDRS + 1];
102 static struct hostent *gethostbyname_ipv4 __P((const char *));
104 static struct hostent host;
105 static char *host_aliases[MAXALIASES];
106 static char hostbuf[8*1024];
107 static u_char host_addr[16]; /* IPv4 or IPv6 */
108 static FILE *hostf = NULL;
109 static int stayopen = 0;
111 static void map_v4v6_address __P((const char *src, char *dst));
112 static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
114 #ifdef RESOLVSORT
115 static void addrsort __P((char **, int));
116 #endif
118 #if PACKETSZ > 1024
119 #define MAXPACKET PACKETSZ
120 #else
121 #define MAXPACKET 1024
122 #endif
124 typedef union {
125 HEADER hdr;
126 u_char buf[MAXPACKET];
127 } querybuf;
129 typedef union {
130 int32_t al;
131 char ac;
132 } align;
134 extern int h_errno;
136 #ifdef DEBUG
137 static void
138 dprintf(msg, num)
139 char *msg;
140 int num;
142 if (_res.options & RES_DEBUG) {
143 int save = errno;
145 printf(msg, num);
146 errno = save;
149 #else
150 # define dprintf(msg, num) /*nada*/
151 #endif
153 static struct hostent *
154 getanswer(answer, anslen, qname, qtype)
155 const querybuf *answer;
156 int anslen;
157 const char *qname;
158 int qtype;
160 register const HEADER *hp;
161 register const u_char *cp;
162 register int n;
163 const u_char *eom;
164 char *bp, **ap, **hap;
165 int type, class, buflen, ancount, qdcount;
166 int haveanswer, had_error;
167 int toobig = 0;
168 char tbuf[MAXDNAME+1];
169 const char *tname;
170 int (*name_ok) __P((const char *));
172 tname = qname;
173 host.h_name = NULL;
174 eom = answer->buf + anslen;
175 switch (qtype) {
176 case T_A:
177 case T_AAAA:
178 name_ok = res_hnok;
179 break;
180 case T_PTR:
181 name_ok = res_dnok;
182 break;
183 default:
184 return (NULL); /* XXX should be abort(); */
187 * find first satisfactory answer
189 hp = &answer->hdr;
190 ancount = ntohs(hp->ancount);
191 qdcount = ntohs(hp->qdcount);
192 bp = hostbuf;
193 buflen = sizeof hostbuf;
194 cp = answer->buf + HFIXEDSZ;
195 if (qdcount != 1) {
196 h_errno = NO_RECOVERY;
197 return (NULL);
199 n = dn_expand(answer->buf, eom, cp, bp, buflen);
200 if ((n < 0) || !(*name_ok)(bp)) {
201 h_errno = NO_RECOVERY;
202 return (NULL);
204 cp += n + QFIXEDSZ;
205 if (qtype == T_A || qtype == T_AAAA) {
206 /* res_send() has already verified that the query name is the
207 * same as the one we sent; this just gets the expanded name
208 * (i.e., with the succeeding search-domain tacked on).
210 n = strlen(bp) + 1; /* for the \0 */
211 host.h_name = bp;
212 bp += n;
213 buflen -= n;
214 /* The qname can be abbreviated, but h_name is now absolute. */
215 qname = host.h_name;
217 ap = host_aliases;
218 *ap = NULL;
219 host.h_aliases = host_aliases;
220 hap = h_addr_ptrs;
221 *hap = NULL;
222 host.h_addr_list = h_addr_ptrs;
223 haveanswer = 0;
224 had_error = 0;
225 while (ancount-- > 0 && cp < eom && !had_error) {
226 n = dn_expand(answer->buf, eom, cp, bp, buflen);
227 if ((n < 0) || !(*name_ok)(bp)) {
228 had_error++;
229 continue;
231 cp += n; /* name */
232 type = _getshort(cp);
233 cp += INT16SZ; /* type */
234 class = _getshort(cp);
235 cp += INT16SZ + INT32SZ; /* class, TTL */
236 n = _getshort(cp);
237 cp += INT16SZ; /* len */
238 if (class != C_IN) {
239 /* XXX - debug? syslog? */
240 cp += n;
241 continue; /* XXX - had_error++ ? */
243 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
244 if (ap >= &host_aliases[MAXALIASES-1])
245 continue;
246 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
247 if ((n < 0) || !(*name_ok)(tbuf)) {
248 had_error++;
249 continue;
251 cp += n;
252 /* Store alias. */
253 *ap++ = bp;
254 n = strlen(bp) + 1; /* for the \0 */
255 bp += n;
256 buflen -= n;
257 /* Get canonical name. */
258 n = strlen(tbuf) + 1; /* for the \0 */
259 if (n > buflen) {
260 had_error++;
261 continue;
263 strcpy(bp, tbuf);
264 host.h_name = bp;
265 bp += n;
266 buflen -= n;
267 continue;
269 if (qtype == T_PTR && type == T_CNAME) {
270 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
271 if ((n < 0) || !res_hnok(tbuf)) {
272 had_error++;
273 continue;
275 cp += n;
276 /* Get canonical name. */
277 n = strlen(tbuf) + 1; /* for the \0 */
278 if (n > buflen) {
279 had_error++;
280 continue;
282 strcpy(bp, tbuf);
283 tname = bp;
284 bp += n;
285 buflen -= n;
286 continue;
288 if (type != qtype) {
289 syslog(LOG_NOTICE|LOG_AUTH,
290 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
291 qname, p_class(C_IN), p_type(qtype),
292 p_type(type));
293 cp += n;
294 continue; /* XXX - had_error++ ? */
296 switch (type) {
297 case T_PTR:
298 if (strcasecmp(tname, bp) != 0) {
299 syslog(LOG_NOTICE|LOG_AUTH,
300 AskedForGot, qname, bp);
301 cp += n;
302 continue; /* XXX - had_error++ ? */
304 n = dn_expand(answer->buf, eom, cp, bp, buflen);
305 if ((n < 0) || !res_hnok(bp)) {
306 had_error++;
307 break;
309 #if MULTI_PTRS_ARE_ALIASES
310 cp += n;
311 if (!haveanswer)
312 host.h_name = bp;
313 else if (ap < &host_aliases[MAXALIASES-1])
314 *ap++ = bp;
315 else
316 n = -1;
317 if (n != -1) {
318 n = strlen(bp) + 1; /* for the \0 */
319 bp += n;
320 buflen -= n;
322 break;
323 #else
324 host.h_name = bp;
325 if (_res.options & RES_USE_INET6) {
326 n = strlen(bp) + 1; /* for the \0 */
327 bp += n;
328 buflen -= n;
329 map_v4v6_hostent(&host, &bp, &buflen);
331 h_errno = NETDB_SUCCESS;
332 return (&host);
333 #endif
334 case T_A:
335 case T_AAAA:
336 if (strcasecmp(host.h_name, bp) != 0) {
337 syslog(LOG_NOTICE|LOG_AUTH,
338 AskedForGot, host.h_name, bp);
339 cp += n;
340 continue; /* XXX - had_error++ ? */
342 if (haveanswer) {
343 if (n != host.h_length) {
344 cp += n;
345 continue;
347 } else {
348 register int nn;
350 host.h_name = bp;
351 nn = strlen(bp) + 1; /* for the \0 */
352 bp += nn;
353 buflen -= nn;
356 bp += sizeof(align) - ((u_long)bp % sizeof(align));
358 if (bp + n >= &hostbuf[sizeof hostbuf]) {
359 dprintf("size (%d) too big\n", n);
360 had_error++;
361 continue;
363 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
364 if (!toobig++)
365 dprintf("Too many addresses (%d)\n",
366 MAXADDRS);
367 cp += n;
368 continue;
370 bcopy(cp, *hap++ = bp, n);
371 bp += n;
372 cp += n;
373 break;
374 default:
375 abort();
377 if (!had_error)
378 haveanswer++;
380 if (haveanswer) {
381 *ap = NULL;
382 *hap = NULL;
383 # if defined(RESOLVSORT)
385 * Note: we sort even if host can take only one address
386 * in its return structures - should give it the "best"
387 * address in that case, not some random one
389 if (_res.nsort && haveanswer > 1 && qtype == T_A)
390 addrsort(h_addr_ptrs, haveanswer);
391 # endif /*RESOLVSORT*/
392 if (!host.h_name) {
393 n = strlen(qname) + 1; /* for the \0 */
394 if (n > buflen)
395 goto try_again;
396 strcpy(bp, qname);
397 host.h_name = bp;
398 bp += n;
399 buflen -= n;
401 if (_res.options & RES_USE_INET6)
402 map_v4v6_hostent(&host, &bp, &buflen);
403 h_errno = NETDB_SUCCESS;
404 return (&host);
406 try_again:
407 h_errno = TRY_AGAIN;
408 return (NULL);
411 struct hostent *
412 gethostbyname(name)
413 const char *name;
415 struct hostent *hp;
417 if (_res.options & RES_USE_INET6) {
418 hp = gethostbyname2(name, AF_INET6);
419 if (hp)
420 return (hp);
422 return (gethostbyname2(name, AF_INET));
425 struct hostent *
426 gethostbyname2(name, af)
427 const char *name;
428 int af;
430 querybuf buf;
431 register const char *cp;
432 char *bp;
433 int n, size, type, len;
434 extern struct hostent *_gethtbyname2();
436 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
437 h_errno = NETDB_INTERNAL;
438 return (NULL);
441 switch (af) {
442 case AF_INET:
443 size = INADDRSZ;
444 type = T_A;
445 break;
446 case AF_INET6:
447 size = IN6ADDRSZ;
448 type = T_AAAA;
449 break;
450 default:
451 h_errno = NETDB_INTERNAL;
452 errno = EAFNOSUPPORT;
453 return (NULL);
456 host.h_addrtype = af;
457 host.h_length = size;
460 * if there aren't any dots, it could be a user-level alias.
461 * this is also done in res_query() since we are not the only
462 * function that looks up host names.
464 if (!strchr(name, '.') && (cp = __hostalias(name)))
465 name = cp;
468 * disallow names consisting only of digits/dots, unless
469 * they end in a dot.
471 if (isdigit(name[0]))
472 for (cp = name;; ++cp) {
473 if (!*cp) {
474 if (*--cp == '.')
475 break;
477 * All-numeric, no dot at the end.
478 * Fake up a hostent as if we'd actually
479 * done a lookup.
481 if (inet_pton(af, name, host_addr) <= 0) {
482 h_errno = HOST_NOT_FOUND;
483 return (NULL);
485 strncpy(hostbuf, name, MAXDNAME);
486 hostbuf[MAXDNAME] = '\0';
487 bp = hostbuf + MAXDNAME;
488 len = sizeof hostbuf - MAXDNAME;
489 host.h_name = hostbuf;
490 host.h_aliases = host_aliases;
491 host_aliases[0] = NULL;
492 h_addr_ptrs[0] = (char *)host_addr;
493 h_addr_ptrs[1] = NULL;
494 host.h_addr_list = h_addr_ptrs;
495 if (_res.options & RES_USE_INET6)
496 map_v4v6_hostent(&host, &bp, &len);
497 h_errno = NETDB_SUCCESS;
498 return (&host);
500 if (!isdigit(*cp) && *cp != '.')
501 break;
504 if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
505 dprintf("res_search failed (%d)\n", n);
506 if (errno == ECONNREFUSED)
507 return (_gethtbyname2(name, af));
508 return (NULL);
510 return (getanswer(&buf, n, name, type));
513 struct hostent *
514 gethostbyaddr(addr, len, af)
515 const char *addr; /* XXX should have been def'd as u_char! */
516 int len, af;
518 const u_char *uaddr = (const u_char *)addr;
519 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
520 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
521 int n, size;
522 querybuf buf;
523 register struct hostent *hp;
524 char qbuf[MAXDNAME+1], *qp;
525 #ifdef SUNSECURITY
526 register struct hostent *rhp;
527 char **haddr;
528 u_long old_options;
529 char hname2[MAXDNAME+1];
530 #endif /*SUNSECURITY*/
531 extern struct hostent *_gethtbyaddr();
533 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
534 h_errno = NETDB_INTERNAL;
535 return (NULL);
537 if (af == AF_INET6 && len == IN6ADDRSZ &&
538 (!bcmp(uaddr, mapped, sizeof mapped) ||
539 !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
540 /* Unmap. */
541 addr += sizeof mapped;
542 uaddr += sizeof mapped;
543 af = AF_INET;
544 len = INADDRSZ;
546 switch (af) {
547 case AF_INET:
548 size = INADDRSZ;
549 break;
550 case AF_INET6:
551 size = IN6ADDRSZ;
552 break;
553 default:
554 errno = EAFNOSUPPORT;
555 h_errno = NETDB_INTERNAL;
556 return (NULL);
558 if (size != len) {
559 errno = EINVAL;
560 h_errno = NETDB_INTERNAL;
561 return (NULL);
563 switch (af) {
564 case AF_INET:
565 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
566 (uaddr[3] & 0xff),
567 (uaddr[2] & 0xff),
568 (uaddr[1] & 0xff),
569 (uaddr[0] & 0xff));
570 break;
571 case AF_INET6:
572 qp = qbuf;
573 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
574 qp += SPRINTF((qp, "%x.%x.",
575 uaddr[n] & 0xf,
576 (uaddr[n] >> 4) & 0xf));
578 strcpy(qp, "ip6.int");
579 break;
580 default:
581 abort();
583 n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
584 if (n < 0) {
585 dprintf("res_query failed (%d)\n", n);
586 if (errno == ECONNREFUSED)
587 return (_gethtbyaddr(addr, len, af));
588 return (NULL);
590 if (!(hp = getanswer(&buf, n, qbuf, T_PTR)))
591 return (NULL); /* h_errno was set by getanswer() */
592 #ifdef SUNSECURITY
593 if (af == AF_INET) {
595 * turn off search as the name should be absolute,
596 * 'localhost' should be matched by defnames
598 strncpy(hname2, hp->h_name, MAXDNAME);
599 hname2[MAXDNAME] = '\0';
600 old_options = _res.options;
601 _res.options &= ~RES_DNSRCH;
602 _res.options |= RES_DEFNAMES;
603 if (!(rhp = gethostbyname(hname2))) {
604 syslog(LOG_NOTICE|LOG_AUTH,
605 "gethostbyaddr: No A record for %s (verifying [%s])",
606 hname2, inet_ntoa(*((struct in_addr *)addr)));
607 _res.options = old_options;
608 h_errno = HOST_NOT_FOUND;
609 return (NULL);
611 _res.options = old_options;
612 for (haddr = rhp->h_addr_list; *haddr; haddr++)
613 if (!memcmp(*haddr, addr, INADDRSZ))
614 break;
615 if (!*haddr) {
616 syslog(LOG_NOTICE|LOG_AUTH,
617 "gethostbyaddr: A record of %s != PTR record [%s]",
618 hname2, inet_ntoa(*((struct in_addr *)addr)));
619 h_errno = HOST_NOT_FOUND;
620 return (NULL);
623 #endif /*SUNSECURITY*/
624 hp->h_addrtype = af;
625 hp->h_length = len;
626 bcopy(addr, host_addr, len);
627 h_addr_ptrs[0] = (char *)host_addr;
628 h_addr_ptrs[1] = NULL;
629 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
630 map_v4v6_address((char*)host_addr, (char*)host_addr);
631 hp->h_addrtype = AF_INET6;
632 hp->h_length = IN6ADDRSZ;
634 h_errno = NETDB_SUCCESS;
635 return (hp);
638 void
639 _sethtent(f)
640 int f;
642 if (!hostf)
643 hostf = fopen(_PATH_HOSTS, "r" );
644 else
645 rewind(hostf);
646 stayopen = f;
649 void
650 _endhtent()
652 if (hostf && !stayopen) {
653 (void) fclose(hostf);
654 hostf = NULL;
658 struct hostent *
659 _gethtent()
661 char *p;
662 register char *cp, **q;
663 int af, len;
665 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
666 h_errno = NETDB_INTERNAL;
667 return (NULL);
669 again:
670 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
671 h_errno = HOST_NOT_FOUND;
672 return (NULL);
674 if (*p == '#')
675 goto again;
676 if (!(cp = strpbrk(p, "#\n")))
677 goto again;
678 *cp = '\0';
679 if (!(cp = strpbrk(p, " \t")))
680 goto again;
681 *cp++ = '\0';
682 if ((_res.options & RES_USE_INET6) &&
683 inet_pton(AF_INET6, p, host_addr) > 0) {
684 af = AF_INET6;
685 len = IN6ADDRSZ;
686 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
687 if (_res.options & RES_USE_INET6) {
688 map_v4v6_address((char*)host_addr, (char*)host_addr);
689 af = AF_INET6;
690 len = IN6ADDRSZ;
691 } else {
692 af = AF_INET;
693 len = INADDRSZ;
695 } else {
696 goto again;
698 h_addr_ptrs[0] = (char *)host_addr;
699 h_addr_ptrs[1] = NULL;
700 host.h_addr_list = h_addr_ptrs;
701 host.h_length = len;
702 host.h_addrtype = af;
703 while (*cp == ' ' || *cp == '\t')
704 cp++;
705 host.h_name = cp;
706 q = host.h_aliases = host_aliases;
707 if (cp = strpbrk(cp, " \t"))
708 *cp++ = '\0';
709 while (cp && *cp) {
710 if (*cp == ' ' || *cp == '\t') {
711 cp++;
712 continue;
714 if (q < &host_aliases[MAXALIASES - 1])
715 *q++ = cp;
716 if (cp = strpbrk(cp, " \t"))
717 *cp++ = '\0';
719 *q = NULL;
720 if (_res.options & RES_USE_INET6) {
721 char *bp = hostbuf;
722 int buflen = sizeof hostbuf;
724 map_v4v6_hostent(&host, &bp, &buflen);
726 h_errno = NETDB_SUCCESS;
727 return (&host);
730 struct hostent *
731 _gethtbyname(name)
732 const char *name;
734 extern struct hostent *_gethtbyname2();
735 struct hostent *hp;
737 if (_res.options & RES_USE_INET6) {
738 hp = _gethtbyname2(name, AF_INET6);
739 if (hp)
740 return (hp);
742 return (_gethtbyname2(name, AF_INET));
745 struct hostent *
746 _gethtbyname2(name, af)
747 const char *name;
748 int af;
750 register struct hostent *p;
751 register char **cp;
753 _sethtent(0);
754 while (p = _gethtent()) {
755 if (p->h_addrtype != af)
756 continue;
757 if (strcasecmp(p->h_name, name) == 0)
758 break;
759 for (cp = p->h_aliases; *cp != 0; cp++)
760 if (strcasecmp(*cp, name) == 0)
761 goto found;
763 found:
764 _endhtent();
765 return (p);
768 struct hostent *
769 _gethtbyaddr(addr, len, af)
770 const char *addr;
771 int len, af;
773 register struct hostent *p;
775 _sethtent(0);
776 while (p = _gethtent())
777 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
778 break;
779 _endhtent();
780 return (p);
783 static void
784 map_v4v6_address(src, dst)
785 const char *src;
786 char *dst;
788 u_char *p = (u_char *)dst;
789 char tmp[INADDRSZ];
790 int i;
792 /* Stash a temporary copy so our caller can update in place. */
793 bcopy(src, tmp, INADDRSZ);
794 /* Mark this ipv6 addr as a mapped ipv4. */
795 for (i = 0; i < 10; i++)
796 *p++ = 0x00;
797 *p++ = 0xff;
798 *p++ = 0xff;
799 /* Retrieve the saved copy and we're done. */
800 bcopy(tmp, (void*)p, INADDRSZ);
803 static void
804 map_v4v6_hostent(hp, bpp, lenp)
805 struct hostent *hp;
806 char **bpp;
807 int *lenp;
809 char **ap;
811 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
812 return;
813 hp->h_addrtype = AF_INET6;
814 hp->h_length = IN6ADDRSZ;
815 for (ap = hp->h_addr_list; *ap; ap++) {
816 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
818 if (*lenp < (i + IN6ADDRSZ)) {
819 /* Out of memory. Truncate address list here. XXX */
820 *ap = NULL;
821 return;
823 *bpp += i;
824 *lenp -= i;
825 map_v4v6_address(*ap, *bpp);
826 *ap = *bpp;
827 *bpp += IN6ADDRSZ;
828 *lenp -= IN6ADDRSZ;
832 #ifdef RESOLVSORT
833 static void
834 addrsort(ap, num)
835 char **ap;
836 int num;
838 int i, j;
839 char **p;
840 short aval[MAXADDRS];
841 int needsort = 0;
843 p = ap;
844 for (i = 0; i < num; i++, p++) {
845 for (j = 0 ; (unsigned)j < _res.nsort; j++)
846 if (_res.sort_list[j].addr.s_addr ==
847 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
848 break;
849 aval[i] = j;
850 if (needsort == 0 && i > 0 && j < aval[i-1])
851 needsort = i;
853 if (!needsort)
854 return;
856 while (needsort < num) {
857 for (j = needsort - 1; j >= 0; j--) {
858 if (aval[j] > aval[j+1]) {
859 char *hp;
861 i = aval[j];
862 aval[j] = aval[j+1];
863 aval[j+1] = i;
865 hp = ap[j];
866 ap[j] = ap[j+1];
867 ap[j+1] = hp;
869 } else
870 break;
872 needsort++;
875 #endif
877 #if defined(BSD43_BSD43_NFS) || defined(sun)
878 /* some libc's out there are bound internally to these names (UMIPS) */
879 void
880 ht_sethostent(stayopen)
881 int stayopen;
883 _sethtent(stayopen);
886 void
887 ht_endhostent()
889 _endhtent();
892 struct hostent *
893 ht_gethostbyname(name)
894 char *name;
896 return (_gethtbyname(name));
899 struct hostent *
900 ht_gethostbyaddr(addr, len, af)
901 const char *addr;
902 int len, af;
904 return (_gethtbyaddr(addr, len, af));
907 struct hostent *
908 gethostent()
910 return (_gethtent());
913 void
914 dns_service()
916 return;
919 #undef dn_skipname
920 dn_skipname(comp_dn, eom)
921 const u_char *comp_dn, *eom;
923 return (__dn_skipname(comp_dn, eom));
925 #endif /*old-style libc with yp junk in it*/