gethnamaddr.c revision 1.14.2.3 1 /* $NetBSD: gethnamaddr.c,v 1.14.2.3 2002/06/26 21:54:27 he 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.14.2.3 2002/06/26 21:54:27 he Exp $");
65 #endif
66 #endif /* LIBC_SCCS and not lint */
67
68 #if defined(_LIBC)
69 #include "namespace.h"
70 #endif
71 #include <sys/types.h>
72 #include <sys/param.h>
73 #include <sys/socket.h>
74 #include <netinet/in.h>
75 #include <arpa/inet.h>
76 #include <arpa/nameser.h>
77
78 #include <stdio.h>
79 #include <netdb.h>
80 #include <resolv.h>
81 #include <ctype.h>
82 #include <errno.h>
83 #include <syslog.h>
84
85 #ifndef LOG_AUTH
86 # define LOG_AUTH 0
87 #endif
88
89 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
90
91 #include <nsswitch.h>
92 #include <stdlib.h>
93 #include <string.h>
94
95 #ifdef YP
96 #include <rpc/rpc.h>
97 #include <rpcsvc/yp_prot.h>
98 #include <rpcsvc/ypclnt.h>
99 #endif
100
101 #if defined(_LIBC) && defined(__weak_alias)
102 __weak_alias(gethostbyaddr,_gethostbyaddr);
103 __weak_alias(gethostbyname,_gethostbyname);
104 #endif
105
106 #define MAXALIASES 35
107 #define MAXADDRS 35
108
109 static const char AskedForGot[] =
110 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
111
112 static char *h_addr_ptrs[MAXADDRS + 1];
113
114 #ifdef YP
115 static char *__ypdomain;
116 #endif
117
118 static struct hostent host;
119 static char *host_aliases[MAXALIASES];
120 static char hostbuf[8*1024];
121 static u_char host_addr[16]; /* IPv4 or IPv6 */
122 static FILE *hostf = NULL;
123 static int stayopen = 0;
124
125
126 #if PACKETSZ > 1024
127 #define MAXPACKET PACKETSZ
128 #else
129 #define MAXPACKET 1024
130 #endif
131
132 typedef union {
133 HEADER hdr;
134 u_char buf[MAXPACKET];
135 } querybuf;
136
137 typedef union {
138 int32_t al;
139 char ac;
140 } align;
141
142 extern int h_errno;
143
144 #ifdef DEBUG
145 static void dprintf __P((char *, int));
146 #endif
147 static struct hostent *getanswer __P((const querybuf *, int,
148 const char *, int));
149 static void map_v4v6_address __P((const char *, char *));
150 static void map_v4v6_hostent __P((struct hostent *, char **, char *));
151 #ifdef RESOLVSORT
152 static void addrsort __P((char **, int));
153 #endif
154
155 struct hostent *gethostbyname __P((const char *));
156 struct hostent *gethostbyname2 __P((const char *, int));
157 struct hostent *gethostbyaddr __P((const char *, int, int ));
158 void _sethtent __P((int));
159 void _endhtent __P((void));
160 struct hostent *_gethtent __P((void));
161 struct hostent *_gethtbyname2 __P((const char *, int));
162 void ht_sethostent __P((int));
163 void ht_endhostent __P((void));
164 struct hostent *ht_gethostbyname __P((char *));
165 struct hostent *ht_gethostbyaddr __P((const char *, int, int ));
166 struct hostent *gethostent __P((void));
167 void dns_service __P((void));
168 int dn_skipname __P((const u_char *, const u_char *));
169 int _gethtbyaddr __P((void *, void *, va_list));
170 int _gethtbyname __P((void *, void *, va_list));
171 int _dns_gethtbyaddr __P((void *, void *, va_list));
172 int _dns_gethtbyname __P((void *, void *, va_list));
173 #ifdef YP
174 struct hostent *_yphostent __P((char *, int));
175 int _yp_gethtbyaddr __P((void *, void *, va_list));
176 int _yp_gethtbyname __P((void *, void *, va_list));
177 #endif
178
179 static const ns_src default_dns_files[] = {
180 { NSSRC_DNS, NS_SUCCESS },
181 { NSSRC_FILES, NS_SUCCESS },
182 { 0 }
183 };
184
185
186 #ifdef DEBUG
187 static void
188 dprintf(msg, num)
189 char *msg;
190 int num;
191 {
192 if (_res.options & RES_DEBUG) {
193 int save = errno;
194
195 printf(msg, num);
196 errno = save;
197 }
198 }
199 #else
200 # define dprintf(msg, num) /*nada*/
201 #endif
202
203 static struct hostent *
204 getanswer(answer, anslen, qname, qtype)
205 const querybuf *answer;
206 int anslen;
207 const char *qname;
208 int qtype;
209 {
210 register const HEADER *hp;
211 register const u_char *cp;
212 register int n;
213 const u_char *eom;
214 char *bp, **ap, **hap, *ep;
215 int type, class, ancount, qdcount;
216 int haveanswer, had_error;
217 int toobig = 0;
218 char tbuf[MAXDNAME];
219 const char *tname;
220 int (*name_ok) __P((const char *));
221
222 tname = qname;
223 host.h_name = NULL;
224 eom = answer->buf + anslen;
225 switch (qtype) {
226 case T_A:
227 case T_AAAA:
228 name_ok = res_hnok;
229 break;
230 case T_PTR:
231 name_ok = res_dnok;
232 break;
233 default:
234 return (NULL); /* XXX should be abort(); */
235 }
236 /*
237 * find first satisfactory answer
238 */
239 hp = &answer->hdr;
240 ancount = ntohs(hp->ancount);
241 qdcount = ntohs(hp->qdcount);
242 bp = hostbuf;
243 ep = hostbuf + sizeof hostbuf;
244 cp = answer->buf + HFIXEDSZ;
245 if (qdcount != 1) {
246 h_errno = NO_RECOVERY;
247 return (NULL);
248 }
249 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
250 if ((n < 0) || !(*name_ok)(bp)) {
251 h_errno = NO_RECOVERY;
252 return (NULL);
253 }
254 cp += n + QFIXEDSZ;
255 if (qtype == T_A || qtype == T_AAAA) {
256 /* res_send() has already verified that the query name is the
257 * same as the one we sent; this just gets the expanded name
258 * (i.e., with the succeeding search-domain tacked on).
259 */
260 n = strlen(bp) + 1; /* for the \0 */
261 if (n >= MAXHOSTNAMELEN) {
262 h_errno = NO_RECOVERY;
263 return (NULL);
264 }
265 host.h_name = bp;
266 bp += n;
267 /* The qname can be abbreviated, but h_name is now absolute. */
268 qname = host.h_name;
269 }
270 ap = host_aliases;
271 *ap = NULL;
272 host.h_aliases = host_aliases;
273 hap = h_addr_ptrs;
274 *hap = NULL;
275 host.h_addr_list = h_addr_ptrs;
276 haveanswer = 0;
277 had_error = 0;
278 while (ancount-- > 0 && cp < eom && !had_error) {
279 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
280 if ((n < 0) || !(*name_ok)(bp)) {
281 had_error++;
282 continue;
283 }
284 cp += n; /* name */
285 type = _getshort(cp);
286 cp += INT16SZ; /* type */
287 class = _getshort(cp);
288 cp += INT16SZ + INT32SZ; /* class, TTL */
289 n = _getshort(cp);
290 cp += INT16SZ; /* len */
291 if (class != C_IN) {
292 /* XXX - debug? syslog? */
293 cp += n;
294 continue; /* XXX - had_error++ ? */
295 }
296 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
297 if (ap >= &host_aliases[MAXALIASES-1])
298 continue;
299 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
300 if ((n < 0) || !(*name_ok)(tbuf)) {
301 had_error++;
302 continue;
303 }
304 cp += n;
305 /* Store alias. */
306 *ap++ = bp;
307 n = strlen(bp) + 1; /* for the \0 */
308 if (n >= MAXHOSTNAMELEN) {
309 had_error++;
310 continue;
311 }
312 bp += n;
313 /* Get canonical name. */
314 n = strlen(tbuf) + 1; /* for the \0 */
315 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
316 had_error++;
317 continue;
318 }
319 strcpy(bp, tbuf);
320 host.h_name = bp;
321 bp += n;
322 continue;
323 }
324 if (qtype == T_PTR && type == T_CNAME) {
325 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
326 if (n < 0 || !res_dnok(tbuf)) {
327 had_error++;
328 continue;
329 }
330 cp += n;
331 /* Get canonical name. */
332 n = strlen(tbuf) + 1; /* for the \0 */
333 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
334 had_error++;
335 continue;
336 }
337 strcpy(bp, tbuf);
338 tname = bp;
339 bp += n;
340 continue;
341 }
342 if (type != qtype) {
343 if (type != T_KEY && type != T_SIG)
344 syslog(LOG_NOTICE|LOG_AUTH,
345 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
346 qname, p_class(C_IN), p_type(qtype),
347 p_type(type));
348 cp += n;
349 continue; /* XXX - had_error++ ? */
350 }
351 switch (type) {
352 case T_PTR:
353 if (strcasecmp(tname, bp) != 0) {
354 syslog(LOG_NOTICE|LOG_AUTH,
355 AskedForGot, qname, bp);
356 cp += n;
357 continue; /* XXX - had_error++ ? */
358 }
359 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
360 if ((n < 0) || !res_hnok(bp)) {
361 had_error++;
362 break;
363 }
364 #if MULTI_PTRS_ARE_ALIASES
365 cp += n;
366 if (!haveanswer)
367 host.h_name = bp;
368 else if (ap < &host_aliases[MAXALIASES-1])
369 *ap++ = bp;
370 else
371 n = -1;
372 if (n != -1) {
373 n = strlen(bp) + 1; /* for the \0 */
374 if (n >= MAXHOSTNAMELEN) {
375 had_error++;
376 break;
377 }
378 bp += n;
379 }
380 break;
381 #else
382 host.h_name = bp;
383 if (_res.options & RES_USE_INET6) {
384 n = strlen(bp) + 1; /* for the \0 */
385 if (n >= MAXHOSTNAMELEN) {
386 had_error++;
387 break;
388 }
389 bp += n;
390 map_v4v6_hostent(&host, &bp, ep);
391 }
392 h_errno = NETDB_SUCCESS;
393 return (&host);
394 #endif
395 case T_A:
396 case T_AAAA:
397 if (strcasecmp(host.h_name, bp) != 0) {
398 syslog(LOG_NOTICE|LOG_AUTH,
399 AskedForGot, host.h_name, bp);
400 cp += n;
401 continue; /* XXX - had_error++ ? */
402 }
403 if (n != host.h_length) {
404 cp += n;
405 continue;
406 }
407 if (!haveanswer) {
408 register int nn;
409
410 host.h_name = bp;
411 nn = strlen(bp) + 1; /* for the \0 */
412 bp += nn;
413 }
414
415 bp += sizeof(align) -
416 (size_t)((u_long)bp % sizeof(align));
417
418 if (bp + n >= &hostbuf[sizeof hostbuf]) {
419 dprintf("size (%d) too big\n", n);
420 had_error++;
421 continue;
422 }
423 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
424 if (!toobig++)
425 dprintf("Too many addresses (%d)\n",
426 MAXADDRS);
427 cp += n;
428 continue;
429 }
430 (void)memcpy(*hap++ = bp, cp, (size_t)n);
431 bp += n;
432 cp += n;
433 break;
434 default:
435 abort();
436 }
437 if (!had_error)
438 haveanswer++;
439 }
440 if (haveanswer) {
441 *ap = NULL;
442 *hap = NULL;
443 # if defined(RESOLVSORT)
444 /*
445 * Note: we sort even if host can take only one address
446 * in its return structures - should give it the "best"
447 * address in that case, not some random one
448 */
449 if (_res.nsort && haveanswer > 1 && qtype == T_A)
450 addrsort(h_addr_ptrs, haveanswer);
451 # endif /*RESOLVSORT*/
452 if (!host.h_name) {
453 n = strlen(qname) + 1; /* for the \0 */
454 if (n > ep - bp || n >= MAXHOSTNAMELEN)
455 goto no_recovery;
456 strcpy(bp, qname);
457 host.h_name = bp;
458 bp += n;
459 }
460 if (_res.options & RES_USE_INET6)
461 map_v4v6_hostent(&host, &bp, ep);
462 h_errno = NETDB_SUCCESS;
463 return (&host);
464 }
465 no_recovery:
466 h_errno = NO_RECOVERY;
467 return (NULL);
468 }
469
470 struct hostent *
471 gethostbyname(name)
472 const char *name;
473 {
474 struct hostent *hp;
475
476 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
477 h_errno = NETDB_INTERNAL;
478 return (NULL);
479 }
480 if (_res.options & RES_USE_INET6) {
481 hp = gethostbyname2(name, AF_INET6);
482 if (hp)
483 return (hp);
484 }
485 return (gethostbyname2(name, AF_INET));
486 }
487
488 struct hostent *
489 gethostbyname2(name, af)
490 const char *name;
491 int af;
492 {
493 const char *cp;
494 char *bp, *ep;
495 int size;
496 struct hostent *hp;
497 static const ns_dtab dtab[] = {
498 NS_FILES_CB(_gethtbyname, NULL)
499 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
500 NS_NIS_CB(_yp_gethtbyname, NULL)
501 { 0 }
502 };
503
504 switch (af) {
505 case AF_INET:
506 size = INADDRSZ;
507 break;
508 case AF_INET6:
509 size = IN6ADDRSZ;
510 break;
511 default:
512 h_errno = NETDB_INTERNAL;
513 errno = EAFNOSUPPORT;
514 return (NULL);
515 }
516
517 host.h_addrtype = af;
518 host.h_length = size;
519
520 /*
521 * if there aren't any dots, it could be a user-level alias.
522 * this is also done in res_query() since we are not the only
523 * function that looks up host names.
524 */
525 if (!strchr(name, '.') && (cp = __hostalias(name)))
526 name = cp;
527
528 /*
529 * disallow names consisting only of digits/dots, unless
530 * they end in a dot.
531 */
532 if (isdigit(name[0]))
533 for (cp = name;; ++cp) {
534 if (!*cp) {
535 if (*--cp == '.')
536 break;
537 /*
538 * All-numeric, no dot at the end.
539 * Fake up a hostent as if we'd actually
540 * done a lookup.
541 */
542 if (inet_pton(af, name, host_addr) <= 0) {
543 h_errno = HOST_NOT_FOUND;
544 return (NULL);
545 }
546 strncpy(hostbuf, name, MAXDNAME);
547 hostbuf[MAXDNAME] = '\0';
548 bp = hostbuf + MAXDNAME;
549 ep = hostbuf + sizeof hostbuf;
550 host.h_name = hostbuf;
551 host.h_aliases = host_aliases;
552 host_aliases[0] = NULL;
553 h_addr_ptrs[0] = (char *)host_addr;
554 h_addr_ptrs[1] = NULL;
555 host.h_addr_list = h_addr_ptrs;
556 if (_res.options & RES_USE_INET6)
557 map_v4v6_hostent(&host, &bp, ep);
558 h_errno = NETDB_SUCCESS;
559 return (&host);
560 }
561 if (!isdigit(*cp) && *cp != '.')
562 break;
563 }
564 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
565 name[0] == ':')
566 for (cp = name;; ++cp) {
567 if (!*cp) {
568 if (*--cp == '.')
569 break;
570 /*
571 * All-IPv6-legal, no dot at the end.
572 * Fake up a hostent as if we'd actually
573 * done a lookup.
574 */
575 if (inet_pton(af, name, host_addr) <= 0) {
576 h_errno = HOST_NOT_FOUND;
577 return (NULL);
578 }
579 strncpy(hostbuf, name, MAXDNAME);
580 hostbuf[MAXDNAME] = '\0';
581 bp = hostbuf + MAXDNAME;
582 ep = hostbuf + sizeof hostbuf;
583 host.h_name = hostbuf;
584 host.h_aliases = host_aliases;
585 host_aliases[0] = NULL;
586 h_addr_ptrs[0] = (char *)host_addr;
587 h_addr_ptrs[1] = NULL;
588 host.h_addr_list = h_addr_ptrs;
589 h_errno = NETDB_SUCCESS;
590 return (&host);
591 }
592 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
593 break;
594 }
595
596 hp = (struct hostent *)NULL;
597 h_errno = NETDB_INTERNAL;
598 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname",
599 default_dns_files, name, strlen(name), af) != NS_SUCCESS)
600 return (struct hostent *)NULL;
601 h_errno = NETDB_SUCCESS;
602 return (hp);
603 }
604
605 struct hostent *
606 gethostbyaddr(addr, len, af)
607 const char *addr; /* XXX should have been def'd as u_char! */
608 int len, af;
609 {
610 const u_char *uaddr = (const u_char *)addr;
611 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
612 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
613 int size;
614 struct hostent *hp;
615 static const ns_dtab dtab[] = {
616 NS_FILES_CB(_gethtbyaddr, NULL)
617 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
618 NS_NIS_CB(_yp_gethtbyaddr, NULL)
619 { 0 }
620 };
621
622 if (af == AF_INET6 && len == IN6ADDRSZ &&
623 (!memcmp(uaddr, mapped, sizeof mapped) ||
624 !memcmp(uaddr, tunnelled, sizeof tunnelled))) {
625 /* Unmap. */
626 addr += sizeof mapped;
627 uaddr += sizeof mapped;
628 af = AF_INET;
629 len = INADDRSZ;
630 }
631 switch (af) {
632 case AF_INET:
633 size = INADDRSZ;
634 break;
635 case AF_INET6:
636 size = IN6ADDRSZ;
637 break;
638 default:
639 errno = EAFNOSUPPORT;
640 h_errno = NETDB_INTERNAL;
641 return (NULL);
642 }
643 if (size != len) {
644 errno = EINVAL;
645 h_errno = NETDB_INTERNAL;
646 return (NULL);
647 }
648 hp = (struct hostent *)NULL;
649 h_errno = NETDB_INTERNAL;
650 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
651 default_dns_files, uaddr, len, af) != NS_SUCCESS)
652 return (struct hostent *)NULL;
653 h_errno = NETDB_SUCCESS;
654 return (hp);
655 }
656
657 void
658 _sethtent(f)
659 int f;
660 {
661 if (!hostf)
662 hostf = fopen(_PATH_HOSTS, "r" );
663 else
664 rewind(hostf);
665 stayopen = f;
666 }
667
668 void
669 _endhtent()
670 {
671 if (hostf && !stayopen) {
672 (void) fclose(hostf);
673 hostf = NULL;
674 }
675 }
676
677 struct hostent *
678 _gethtent()
679 {
680 char *p;
681 register char *cp, **q;
682 int af, len;
683
684 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
685 h_errno = NETDB_INTERNAL;
686 return (NULL);
687 }
688 again:
689 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
690 h_errno = HOST_NOT_FOUND;
691 return (NULL);
692 }
693 if (*p == '#')
694 goto again;
695 if (!(cp = strpbrk(p, "#\n")))
696 goto again;
697 *cp = '\0';
698 if (!(cp = strpbrk(p, " \t")))
699 goto again;
700 *cp++ = '\0';
701 if (inet_pton(AF_INET6, p, host_addr) > 0) {
702 af = AF_INET6;
703 len = IN6ADDRSZ;
704 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
705 if (_res.options & RES_USE_INET6) {
706 map_v4v6_address((char*)host_addr, (char*)host_addr);
707 af = AF_INET6;
708 len = IN6ADDRSZ;
709 } else {
710 af = AF_INET;
711 len = INADDRSZ;
712 }
713 } else {
714 goto again;
715 }
716 h_addr_ptrs[0] = (char *)host_addr;
717 h_addr_ptrs[1] = NULL;
718 host.h_addr_list = h_addr_ptrs;
719 host.h_length = len;
720 host.h_addrtype = af;
721 while (*cp == ' ' || *cp == '\t')
722 cp++;
723 host.h_name = cp;
724 q = host.h_aliases = host_aliases;
725 if ((cp = strpbrk(cp, " \t")) != NULL)
726 *cp++ = '\0';
727 while (cp && *cp) {
728 if (*cp == ' ' || *cp == '\t') {
729 cp++;
730 continue;
731 }
732 if (q < &host_aliases[MAXALIASES - 1])
733 *q++ = cp;
734 if ((cp = strpbrk(cp, " \t")) != NULL)
735 *cp++ = '\0';
736 }
737 *q = NULL;
738 h_errno = NETDB_SUCCESS;
739 return (&host);
740 }
741
742 /*ARGSUSED*/
743 int
744 _gethtbyname(rv, cb_data, ap)
745 void *rv;
746 void *cb_data;
747 va_list ap;
748 {
749 struct hostent *hp;
750 const char *name;
751 #ifdef notyet
752 int len, af;
753 #endif
754
755 name = va_arg(ap, char *);
756 #ifdef notyet
757 len = va_arg(ap, int);
758 af = va_arg(ap, int);
759 #endif
760
761 hp = NULL;
762 if (_res.options & RES_USE_INET6)
763 hp = _gethtbyname2(name, AF_INET6);
764 if (hp==NULL)
765 hp = _gethtbyname2(name, AF_INET);
766 *((struct hostent **)rv) = hp;
767 if (hp==NULL) {
768 h_errno = HOST_NOT_FOUND;
769 return NS_NOTFOUND;
770 }
771 return NS_SUCCESS;
772 }
773
774 struct hostent *
775 _gethtbyname2(name, af)
776 const char *name;
777 int af;
778 {
779 register struct hostent *p;
780 register char **cp;
781
782 _sethtent(0);
783 while ((p = _gethtent()) != NULL) {
784 if (p->h_addrtype != af)
785 continue;
786 if (strcasecmp(p->h_name, name) == 0)
787 break;
788 for (cp = p->h_aliases; *cp != 0; cp++)
789 if (strcasecmp(*cp, name) == 0)
790 goto found;
791 }
792 found:
793 _endhtent();
794 return (p);
795 }
796
797 /*ARGSUSED*/
798 int
799 _gethtbyaddr(rv, cb_data, ap)
800 void *rv;
801 void *cb_data;
802 va_list ap;
803 {
804 register struct hostent *p;
805 const unsigned char *addr;
806 int len, af;
807
808 addr = va_arg(ap, unsigned char *);
809 len = va_arg(ap, int);
810 af = va_arg(ap, int);
811
812
813 _sethtent(0);
814 while ((p = _gethtent()) != NULL)
815 if (p->h_addrtype == af && !memcmp(p->h_addr, addr,
816 (size_t)len))
817 break;
818 _endhtent();
819 *((struct hostent **)rv) = p;
820 if (p==NULL) {
821 h_errno = HOST_NOT_FOUND;
822 return NS_NOTFOUND;
823 }
824 return NS_SUCCESS;
825 }
826
827 static void
828 map_v4v6_address(src, dst)
829 const char *src;
830 char *dst;
831 {
832 u_char *p = (u_char *)dst;
833 char tmp[INADDRSZ];
834 int i;
835
836 /* Stash a temporary copy so our caller can update in place. */
837 (void)memcpy(tmp, src, INADDRSZ);
838 /* Mark this ipv6 addr as a mapped ipv4. */
839 for (i = 0; i < 10; i++)
840 *p++ = 0x00;
841 *p++ = 0xff;
842 *p++ = 0xff;
843 /* Retrieve the saved copy and we're done. */
844 (void)memcpy((void *)p, tmp, INADDRSZ);
845 }
846
847 static void
848 map_v4v6_hostent(hp, bpp, ep)
849 struct hostent *hp;
850 char **bpp;
851 char *ep;
852 {
853 char **ap;
854
855 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
856 return;
857 hp->h_addrtype = AF_INET6;
858 hp->h_length = IN6ADDRSZ;
859 for (ap = hp->h_addr_list; *ap; ap++) {
860 int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align));
861
862 if (ep - *bpp < (i + IN6ADDRSZ)) {
863 /* Out of memory. Truncate address list here. XXX */
864 *ap = NULL;
865 return;
866 }
867 *bpp += i;
868 map_v4v6_address(*ap, *bpp);
869 *ap = *bpp;
870 *bpp += IN6ADDRSZ;
871 }
872 }
873
874 #ifdef RESOLVSORT
875 static void
876 addrsort(ap, num)
877 char **ap;
878 int num;
879 {
880 int i, j;
881 char **p;
882 short aval[MAXADDRS];
883 int needsort = 0;
884
885 p = ap;
886 for (i = 0; i < num; i++, p++) {
887 for (j = 0 ; (unsigned)j < _res.nsort; j++)
888 if (_res.sort_list[j].addr.s_addr ==
889 (((struct in_addr *)(void *)(*p))->s_addr &
890 _res.sort_list[j].mask))
891 break;
892 aval[i] = j;
893 if (needsort == 0 && i > 0 && j < aval[i-1])
894 needsort = i;
895 }
896 if (!needsort)
897 return;
898
899 while (needsort < num) {
900 for (j = needsort - 1; j >= 0; j--) {
901 if (aval[j] > aval[j+1]) {
902 char *hp;
903
904 i = aval[j];
905 aval[j] = aval[j+1];
906 aval[j+1] = i;
907
908 hp = ap[j];
909 ap[j] = ap[j+1];
910 ap[j+1] = hp;
911
912 } else
913 break;
914 }
915 needsort++;
916 }
917 }
918 #endif
919
920 #if defined(BSD43_BSD43_NFS) || defined(sun)
921 /* some libc's out there are bound internally to these names (UMIPS) */
922 void
923 ht_sethostent(stayopen)
924 int stayopen;
925 {
926 _sethtent(stayopen);
927 }
928
929 void
930 ht_endhostent()
931 {
932 _endhtent();
933 }
934
935 struct hostent *
936 ht_gethostbyname(name)
937 char *name;
938 {
939 return (_gethtbyname(name));
940 }
941
942 struct hostent *
943 ht_gethostbyaddr(addr, len, af)
944 const char *addr;
945 int len, af;
946 {
947 return (_gethtbyaddr(addr, len, af));
948 }
949
950 struct hostent *
951 gethostent()
952 {
953 return (_gethtent());
954 }
955
956 void
957 dns_service()
958 {
959 return;
960 }
961
962 #undef dn_skipname
963 dn_skipname(comp_dn, eom)
964 const u_char *comp_dn, *eom;
965 {
966 return (__dn_skipname(comp_dn, eom));
967 }
968 #endif /*old-style libc with yp junk in it*/
969
970 /*ARGSUSED*/
971 int
972 _dns_gethtbyname(rv, cb_data, ap)
973 void *rv;
974 void *cb_data;
975 va_list ap;
976 {
977 querybuf buf;
978 int n, type;
979 struct hostent *hp;
980 const char *name;
981 int len, af;
982
983 name = va_arg(ap, char *);
984 len = va_arg(ap, int);
985 #if defined(__GNUC__) || defined(lint) /* to shut up gcc warnings */
986 /*LINTED*/
987 (void)(len ? &len : &len);
988 #endif
989 af = va_arg(ap, int);
990
991 switch (af) {
992 case AF_INET:
993 type = T_A;
994 break;
995 case AF_INET6:
996 type = T_AAAA;
997 break;
998 default:
999 return NS_UNAVAIL;
1000 }
1001 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
1002 dprintf("res_search failed (%d)\n", n);
1003 return NS_NOTFOUND;
1004 }
1005 hp = getanswer(&buf, n, name, type);
1006 if (hp == NULL)
1007 switch (h_errno) {
1008 case HOST_NOT_FOUND:
1009 return NS_NOTFOUND;
1010 case TRY_AGAIN:
1011 return NS_TRYAGAIN;
1012 default:
1013 return NS_UNAVAIL;
1014 }
1015 *((struct hostent **)rv) = hp;
1016 return NS_SUCCESS;
1017 }
1018
1019 /*ARGSUSED*/
1020 int
1021 _dns_gethtbyaddr(rv, cb_data, ap)
1022 void *rv;
1023 void *cb_data;
1024 va_list ap;
1025 {
1026 char qbuf[MAXDNAME + 1], *qp;
1027 int n;
1028 querybuf buf;
1029 struct hostent *hp;
1030 const unsigned char *uaddr;
1031 int len, af;
1032
1033 uaddr = va_arg(ap, unsigned char *);
1034 len = va_arg(ap, int);
1035 #ifdef __GNUC__ /* to shut up gcc warnings */
1036 (void)&len;
1037 #endif
1038 af = va_arg(ap, int);
1039
1040 switch (af) {
1041 case AF_INET:
1042 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
1043 (uaddr[3] & 0xff),
1044 (uaddr[2] & 0xff),
1045 (uaddr[1] & 0xff),
1046 (uaddr[0] & 0xff));
1047 break;
1048
1049 case AF_INET6:
1050 qp = qbuf;
1051 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
1052 qp += sprintf(qp, "%x.%x.",
1053 uaddr[n] & 0xf,
1054 ((unsigned int)uaddr[n] >> 4) & 0xf);
1055 }
1056 strcpy(qp, "ip6.int");
1057 break;
1058 default:
1059 abort();
1060 }
1061
1062 n = res_query(qbuf, C_IN, T_PTR, (u_char *)(void *)&buf, sizeof(buf));
1063 if (n < 0) {
1064 dprintf("res_query failed (%d)\n", n);
1065 return NS_NOTFOUND;
1066 }
1067 hp = getanswer(&buf, n, qbuf, T_PTR);
1068 if (hp == NULL)
1069 switch (h_errno) {
1070 case HOST_NOT_FOUND:
1071 return NS_NOTFOUND;
1072 case TRY_AGAIN:
1073 return NS_TRYAGAIN;
1074 default:
1075 return NS_UNAVAIL;
1076 }
1077 hp->h_addrtype = af;
1078 hp->h_length = len;
1079 (void)memcpy(host_addr, uaddr, (size_t)len);
1080 h_addr_ptrs[0] = (char *)&host_addr;
1081 h_addr_ptrs[1] = (char *)0;
1082 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
1083 map_v4v6_address((char*)host_addr, (char*)host_addr);
1084 hp->h_addrtype = AF_INET6;
1085 hp->h_length = IN6ADDRSZ;
1086 }
1087
1088 *((struct hostent **)rv) = hp;
1089 h_errno = NETDB_SUCCESS;
1090 return NS_SUCCESS;
1091 }
1092
1093 #ifdef YP
1094 /*ARGSUSED*/
1095 struct hostent *
1096 _yphostent(line, af)
1097 char *line;
1098 int af;
1099 {
1100 static struct in_addr host_addrs[MAXADDRS];
1101 char *p = line;
1102 char *cp, **q;
1103 char **hap;
1104 struct in_addr *buf;
1105 int more;
1106
1107 host.h_name = NULL;
1108 host.h_addr_list = h_addr_ptrs;
1109 host.h_length = sizeof(u_int32_t);
1110 host.h_addrtype = AF_INET;
1111 hap = h_addr_ptrs;
1112 buf = host_addrs;
1113 q = host.h_aliases = host_aliases;
1114
1115 /*
1116 * XXX: maybe support IPv6 parsing, based on 'af' setting
1117 */
1118 nextline:
1119 /* check for host_addrs overflow */
1120 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
1121 goto done;
1122
1123 more = 0;
1124 cp = strpbrk(p, " \t");
1125 if (cp == NULL)
1126 goto done;
1127 *cp++ = '\0';
1128
1129 *hap++ = (char *)(void *)buf;
1130 (void) inet_aton(p, buf++);
1131
1132 while (*cp == ' ' || *cp == '\t')
1133 cp++;
1134 p = cp;
1135 cp = strpbrk(p, " \t\n");
1136 if (cp != NULL) {
1137 if (*cp == '\n')
1138 more = 1;
1139 *cp++ = '\0';
1140 }
1141 if (!host.h_name)
1142 host.h_name = p;
1143 else if (strcmp(host.h_name, p)==0)
1144 ;
1145 else if (q < &host_aliases[MAXALIASES - 1])
1146 *q++ = p;
1147 p = cp;
1148 if (more)
1149 goto nextline;
1150
1151 while (cp && *cp) {
1152 if (*cp == ' ' || *cp == '\t') {
1153 cp++;
1154 continue;
1155 }
1156 if (*cp == '\n') {
1157 cp++;
1158 goto nextline;
1159 }
1160 if (q < &host_aliases[MAXALIASES - 1])
1161 *q++ = cp;
1162 cp = strpbrk(cp, " \t");
1163 if (cp != NULL)
1164 *cp++ = '\0';
1165 }
1166 done:
1167 if (host.h_name == NULL)
1168 return (NULL);
1169 *q = NULL;
1170 *hap = NULL;
1171 return (&host);
1172 }
1173
1174 /*ARGSUSED*/
1175 int
1176 _yp_gethtbyaddr(rv, cb_data, ap)
1177 void *rv;
1178 void *cb_data;
1179 va_list ap;
1180 {
1181 struct hostent *hp = (struct hostent *)NULL;
1182 static char *__ypcurrent;
1183 int __ypcurrentlen, r;
1184 char name[sizeof("xxx.xxx.xxx.xxx") + 1];
1185 const unsigned char *uaddr;
1186 int len, af;
1187
1188 uaddr = va_arg(ap, unsigned char *);
1189 len = va_arg(ap, int);
1190 #if defined(__GNUC__) || defined(lint) /* to shut up gcc warnings */
1191 /*LINTED*/
1192 (void)(len ? &len : &len);
1193 #endif
1194 af = va_arg(ap, int);
1195
1196 if (!__ypdomain) {
1197 if (_yp_check(&__ypdomain) == 0)
1198 return NS_UNAVAIL;
1199 }
1200 /*
1201 * XXX: based on the value of af, it would be possible to lookup
1202 * IPv6 names in YP, by changing the following snprintf().
1203 * Is it worth it?
1204 */
1205 (void)snprintf(name, sizeof name, "%u.%u.%u.%u",
1206 (uaddr[0] & 0xff),
1207 (uaddr[1] & 0xff),
1208 (uaddr[2] & 0xff),
1209 (uaddr[3] & 0xff));
1210 if (__ypcurrent)
1211 free(__ypcurrent);
1212 __ypcurrent = NULL;
1213 r = yp_match(__ypdomain, "hosts.byaddr", name,
1214 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1215 if (r==0)
1216 hp = _yphostent(__ypcurrent, af);
1217 if (hp==NULL) {
1218 h_errno = HOST_NOT_FOUND;
1219 return NS_NOTFOUND;
1220 }
1221 *((struct hostent **)rv) = hp;
1222 return NS_SUCCESS;
1223 }
1224
1225 /*ARGSUSED*/
1226 int
1227 _yp_gethtbyname(rv, cb_data, ap)
1228 void *rv;
1229 void *cb_data;
1230 va_list ap;
1231 {
1232 struct hostent *hp = (struct hostent *)NULL;
1233 static char *__ypcurrent;
1234 int __ypcurrentlen, r;
1235 const char *name;
1236 int len, af;
1237
1238 name = va_arg(ap, char *);
1239 len = va_arg(ap, int);
1240 #if defined(__GNUC__) || defined(lint) /* to shut up gcc warnings */
1241 /*LINTED*/
1242 (void)(len ? &len : &len);
1243 #endif
1244 af = va_arg(ap, int);
1245
1246 if (!__ypdomain) {
1247 if (_yp_check(&__ypdomain) == 0)
1248 return NS_UNAVAIL;
1249 }
1250 if (__ypcurrent)
1251 free(__ypcurrent);
1252 __ypcurrent = NULL;
1253 r = yp_match(__ypdomain, "hosts.byname", name,
1254 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1255 if (r==0)
1256 hp = _yphostent(__ypcurrent, af);
1257 if (hp==NULL) {
1258 h_errno = HOST_NOT_FOUND;
1259 return NS_NOTFOUND;
1260 }
1261 *((struct hostent **)rv) = hp;
1262 return NS_SUCCESS;
1263 }
1264 #endif
1265