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