gethnamaddr.c revision 1.14.2.2 1 /* $NetBSD: gethnamaddr.c,v 1.14.2.2 2000/08/04 15:21: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.2 2000/08/04 15:21: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 **, int *));
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;
215 int type, class, buflen, 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 buflen = 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, buflen);
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 buflen -= n;
268 /* The qname can be abbreviated, but h_name is now absolute. */
269 qname = host.h_name;
270 }
271 ap = host_aliases;
272 *ap = NULL;
273 host.h_aliases = host_aliases;
274 hap = h_addr_ptrs;
275 *hap = NULL;
276 host.h_addr_list = h_addr_ptrs;
277 haveanswer = 0;
278 had_error = 0;
279 while (ancount-- > 0 && cp < eom && !had_error) {
280 n = dn_expand(answer->buf, eom, cp, bp, buflen);
281 if ((n < 0) || !(*name_ok)(bp)) {
282 had_error++;
283 continue;
284 }
285 cp += n; /* name */
286 type = _getshort(cp);
287 cp += INT16SZ; /* type */
288 class = _getshort(cp);
289 cp += INT16SZ + INT32SZ; /* class, TTL */
290 n = _getshort(cp);
291 cp += INT16SZ; /* len */
292 if (class != C_IN) {
293 /* XXX - debug? syslog? */
294 cp += n;
295 continue; /* XXX - had_error++ ? */
296 }
297 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
298 if (ap >= &host_aliases[MAXALIASES-1])
299 continue;
300 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
301 if ((n < 0) || !(*name_ok)(tbuf)) {
302 had_error++;
303 continue;
304 }
305 cp += n;
306 /* Store alias. */
307 *ap++ = bp;
308 n = strlen(bp) + 1; /* for the \0 */
309 if (n >= MAXHOSTNAMELEN) {
310 had_error++;
311 continue;
312 }
313 bp += n;
314 buflen -= n;
315 /* Get canonical name. */
316 n = strlen(tbuf) + 1; /* for the \0 */
317 if (n > buflen || n >= MAXHOSTNAMELEN) {
318 had_error++;
319 continue;
320 }
321 strcpy(bp, tbuf);
322 host.h_name = bp;
323 bp += n;
324 buflen -= n;
325 continue;
326 }
327 if (qtype == T_PTR && type == T_CNAME) {
328 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
329 if (n < 0 || !res_dnok(tbuf)) {
330 had_error++;
331 continue;
332 }
333 cp += n;
334 /* Get canonical name. */
335 n = strlen(tbuf) + 1; /* for the \0 */
336 if (n > buflen || n >= MAXHOSTNAMELEN) {
337 had_error++;
338 continue;
339 }
340 strcpy(bp, tbuf);
341 tname = bp;
342 bp += n;
343 buflen -= n;
344 continue;
345 }
346 if (type != qtype) {
347 if (type != T_KEY && type != T_SIG)
348 syslog(LOG_NOTICE|LOG_AUTH,
349 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
350 qname, p_class(C_IN), p_type(qtype),
351 p_type(type));
352 cp += n;
353 continue; /* XXX - had_error++ ? */
354 }
355 switch (type) {
356 case T_PTR:
357 if (strcasecmp(tname, bp) != 0) {
358 syslog(LOG_NOTICE|LOG_AUTH,
359 AskedForGot, qname, bp);
360 cp += n;
361 continue; /* XXX - had_error++ ? */
362 }
363 n = dn_expand(answer->buf, eom, cp, bp, buflen);
364 if ((n < 0) || !res_hnok(bp)) {
365 had_error++;
366 break;
367 }
368 #if MULTI_PTRS_ARE_ALIASES
369 cp += n;
370 if (!haveanswer)
371 host.h_name = bp;
372 else if (ap < &host_aliases[MAXALIASES-1])
373 *ap++ = bp;
374 else
375 n = -1;
376 if (n != -1) {
377 n = strlen(bp) + 1; /* for the \0 */
378 if (n >= MAXHOSTNAMELEN) {
379 had_error++;
380 break;
381 }
382 bp += n;
383 buflen -= n;
384 }
385 break;
386 #else
387 host.h_name = bp;
388 if (_res.options & RES_USE_INET6) {
389 n = strlen(bp) + 1; /* for the \0 */
390 if (n >= MAXHOSTNAMELEN) {
391 had_error++;
392 break;
393 }
394 bp += n;
395 buflen -= n;
396 map_v4v6_hostent(&host, &bp, &buflen);
397 }
398 h_errno = NETDB_SUCCESS;
399 return (&host);
400 #endif
401 case T_A:
402 case T_AAAA:
403 if (strcasecmp(host.h_name, bp) != 0) {
404 syslog(LOG_NOTICE|LOG_AUTH,
405 AskedForGot, host.h_name, bp);
406 cp += n;
407 continue; /* XXX - had_error++ ? */
408 }
409 if (n != host.h_length) {
410 cp += n;
411 continue;
412 }
413 if (!haveanswer) {
414 register int nn;
415
416 host.h_name = bp;
417 nn = strlen(bp) + 1; /* for the \0 */
418 bp += nn;
419 buflen -= nn;
420 }
421
422 bp += sizeof(align) -
423 (size_t)((u_long)bp % sizeof(align));
424
425 if (bp + n >= &hostbuf[sizeof hostbuf]) {
426 dprintf("size (%d) too big\n", n);
427 had_error++;
428 continue;
429 }
430 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
431 if (!toobig++)
432 dprintf("Too many addresses (%d)\n",
433 MAXADDRS);
434 cp += n;
435 continue;
436 }
437 (void)memcpy(*hap++ = bp, cp, (size_t)n);
438 bp += n;
439 buflen -= n;
440 cp += n;
441 break;
442 default:
443 abort();
444 }
445 if (!had_error)
446 haveanswer++;
447 }
448 if (haveanswer) {
449 *ap = NULL;
450 *hap = NULL;
451 # if defined(RESOLVSORT)
452 /*
453 * Note: we sort even if host can take only one address
454 * in its return structures - should give it the "best"
455 * address in that case, not some random one
456 */
457 if (_res.nsort && haveanswer > 1 && qtype == T_A)
458 addrsort(h_addr_ptrs, haveanswer);
459 # endif /*RESOLVSORT*/
460 if (!host.h_name) {
461 n = strlen(qname) + 1; /* for the \0 */
462 if (n > buflen || n >= MAXHOSTNAMELEN)
463 goto no_recovery;
464 strcpy(bp, qname);
465 host.h_name = bp;
466 bp += n;
467 buflen -= n;
468 }
469 if (_res.options & RES_USE_INET6)
470 map_v4v6_hostent(&host, &bp, &buflen);
471 h_errno = NETDB_SUCCESS;
472 return (&host);
473 }
474 no_recovery:
475 h_errno = NO_RECOVERY;
476 return (NULL);
477 }
478
479 struct hostent *
480 gethostbyname(name)
481 const char *name;
482 {
483 struct hostent *hp;
484
485 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
486 h_errno = NETDB_INTERNAL;
487 return (NULL);
488 }
489 if (_res.options & RES_USE_INET6) {
490 hp = gethostbyname2(name, AF_INET6);
491 if (hp)
492 return (hp);
493 }
494 return (gethostbyname2(name, AF_INET));
495 }
496
497 struct hostent *
498 gethostbyname2(name, af)
499 const char *name;
500 int af;
501 {
502 const char *cp;
503 char *bp;
504 int size, len;
505 struct hostent *hp;
506 static const ns_dtab dtab[] = {
507 NS_FILES_CB(_gethtbyname, NULL)
508 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
509 NS_NIS_CB(_yp_gethtbyname, NULL)
510 { 0 }
511 };
512
513 switch (af) {
514 case AF_INET:
515 size = INADDRSZ;
516 break;
517 case AF_INET6:
518 size = IN6ADDRSZ;
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 strncpy(hostbuf, name, MAXDNAME);
556 hostbuf[MAXDNAME] = '\0';
557 bp = hostbuf + MAXDNAME;
558 len = sizeof hostbuf - MAXDNAME;
559 host.h_name = hostbuf;
560 host.h_aliases = host_aliases;
561 host_aliases[0] = NULL;
562 h_addr_ptrs[0] = (char *)host_addr;
563 h_addr_ptrs[1] = NULL;
564 host.h_addr_list = h_addr_ptrs;
565 if (_res.options & RES_USE_INET6)
566 map_v4v6_hostent(&host, &bp, &len);
567 h_errno = NETDB_SUCCESS;
568 return (&host);
569 }
570 if (!isdigit(*cp) && *cp != '.')
571 break;
572 }
573 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
574 name[0] == ':')
575 for (cp = name;; ++cp) {
576 if (!*cp) {
577 if (*--cp == '.')
578 break;
579 /*
580 * All-IPv6-legal, no dot at the end.
581 * Fake up a hostent as if we'd actually
582 * done a lookup.
583 */
584 if (inet_pton(af, name, host_addr) <= 0) {
585 h_errno = HOST_NOT_FOUND;
586 return (NULL);
587 }
588 strncpy(hostbuf, name, MAXDNAME);
589 hostbuf[MAXDNAME] = '\0';
590 bp = hostbuf + MAXDNAME;
591 len = sizeof hostbuf - MAXDNAME;
592 host.h_name = hostbuf;
593 host.h_aliases = host_aliases;
594 host_aliases[0] = NULL;
595 h_addr_ptrs[0] = (char *)host_addr;
596 h_addr_ptrs[1] = NULL;
597 host.h_addr_list = h_addr_ptrs;
598 h_errno = NETDB_SUCCESS;
599 return (&host);
600 }
601 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
602 break;
603 }
604
605 hp = (struct hostent *)NULL;
606 h_errno = NETDB_INTERNAL;
607 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname",
608 default_dns_files, name, len, af) != NS_SUCCESS)
609 return (struct hostent *)NULL;
610 h_errno = NETDB_SUCCESS;
611 return (hp);
612 }
613
614 struct hostent *
615 gethostbyaddr(addr, len, af)
616 const char *addr; /* XXX should have been def'd as u_char! */
617 int len, af;
618 {
619 const u_char *uaddr = (const u_char *)addr;
620 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
621 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
622 int size;
623 struct hostent *hp;
624 static const ns_dtab dtab[] = {
625 NS_FILES_CB(_gethtbyaddr, NULL)
626 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
627 NS_NIS_CB(_yp_gethtbyaddr, NULL)
628 { 0 }
629 };
630
631 if (af == AF_INET6 && len == IN6ADDRSZ &&
632 (!memcmp(uaddr, mapped, sizeof mapped) ||
633 !memcmp(uaddr, tunnelled, sizeof tunnelled))) {
634 /* Unmap. */
635 addr += sizeof mapped;
636 uaddr += sizeof mapped;
637 af = AF_INET;
638 len = INADDRSZ;
639 }
640 switch (af) {
641 case AF_INET:
642 size = INADDRSZ;
643 break;
644 case AF_INET6:
645 size = IN6ADDRSZ;
646 break;
647 default:
648 errno = EAFNOSUPPORT;
649 h_errno = NETDB_INTERNAL;
650 return (NULL);
651 }
652 if (size != len) {
653 errno = EINVAL;
654 h_errno = NETDB_INTERNAL;
655 return (NULL);
656 }
657 hp = (struct hostent *)NULL;
658 h_errno = NETDB_INTERNAL;
659 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
660 default_dns_files, uaddr, len, af) != NS_SUCCESS)
661 return (struct hostent *)NULL;
662 h_errno = NETDB_SUCCESS;
663 return (hp);
664 }
665
666 void
667 _sethtent(f)
668 int f;
669 {
670 if (!hostf)
671 hostf = fopen(_PATH_HOSTS, "r" );
672 else
673 rewind(hostf);
674 stayopen = f;
675 }
676
677 void
678 _endhtent()
679 {
680 if (hostf && !stayopen) {
681 (void) fclose(hostf);
682 hostf = NULL;
683 }
684 }
685
686 struct hostent *
687 _gethtent()
688 {
689 char *p;
690 register char *cp, **q;
691 int af, len;
692
693 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
694 h_errno = NETDB_INTERNAL;
695 return (NULL);
696 }
697 again:
698 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
699 h_errno = HOST_NOT_FOUND;
700 return (NULL);
701 }
702 if (*p == '#')
703 goto again;
704 if (!(cp = strpbrk(p, "#\n")))
705 goto again;
706 *cp = '\0';
707 if (!(cp = strpbrk(p, " \t")))
708 goto again;
709 *cp++ = '\0';
710 if (inet_pton(AF_INET6, p, host_addr) > 0) {
711 af = AF_INET6;
712 len = IN6ADDRSZ;
713 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
714 if (_res.options & RES_USE_INET6) {
715 map_v4v6_address((char*)host_addr, (char*)host_addr);
716 af = AF_INET6;
717 len = IN6ADDRSZ;
718 } else {
719 af = AF_INET;
720 len = INADDRSZ;
721 }
722 } else {
723 goto again;
724 }
725 h_addr_ptrs[0] = (char *)host_addr;
726 h_addr_ptrs[1] = NULL;
727 host.h_addr_list = h_addr_ptrs;
728 host.h_length = len;
729 host.h_addrtype = af;
730 while (*cp == ' ' || *cp == '\t')
731 cp++;
732 host.h_name = cp;
733 q = host.h_aliases = host_aliases;
734 if ((cp = strpbrk(cp, " \t")) != NULL)
735 *cp++ = '\0';
736 while (cp && *cp) {
737 if (*cp == ' ' || *cp == '\t') {
738 cp++;
739 continue;
740 }
741 if (q < &host_aliases[MAXALIASES - 1])
742 *q++ = cp;
743 if ((cp = strpbrk(cp, " \t")) != NULL)
744 *cp++ = '\0';
745 }
746 *q = NULL;
747 h_errno = NETDB_SUCCESS;
748 return (&host);
749 }
750
751 /*ARGSUSED*/
752 int
753 _gethtbyname(rv, cb_data, ap)
754 void *rv;
755 void *cb_data;
756 va_list ap;
757 {
758 struct hostent *hp;
759 const char *name;
760 #ifdef notyet
761 int len, af;
762 #endif
763
764 name = va_arg(ap, char *);
765 #ifdef notyet
766 len = va_arg(ap, int);
767 af = va_arg(ap, int);
768 #endif
769
770 hp = NULL;
771 if (_res.options & RES_USE_INET6)
772 hp = _gethtbyname2(name, AF_INET6);
773 if (hp==NULL)
774 hp = _gethtbyname2(name, AF_INET);
775 *((struct hostent **)rv) = hp;
776 if (hp==NULL) {
777 h_errno = HOST_NOT_FOUND;
778 return NS_NOTFOUND;
779 }
780 return NS_SUCCESS;
781 }
782
783 struct hostent *
784 _gethtbyname2(name, af)
785 const char *name;
786 int af;
787 {
788 register struct hostent *p;
789 register char **cp;
790
791 _sethtent(0);
792 while ((p = _gethtent()) != NULL) {
793 if (p->h_addrtype != af)
794 continue;
795 if (strcasecmp(p->h_name, name) == 0)
796 break;
797 for (cp = p->h_aliases; *cp != 0; cp++)
798 if (strcasecmp(*cp, name) == 0)
799 goto found;
800 }
801 found:
802 _endhtent();
803 return (p);
804 }
805
806 /*ARGSUSED*/
807 int
808 _gethtbyaddr(rv, cb_data, ap)
809 void *rv;
810 void *cb_data;
811 va_list ap;
812 {
813 register struct hostent *p;
814 const unsigned char *addr;
815 int len, af;
816
817 addr = va_arg(ap, unsigned char *);
818 len = va_arg(ap, int);
819 af = va_arg(ap, int);
820
821
822 _sethtent(0);
823 while ((p = _gethtent()) != NULL)
824 if (p->h_addrtype == af && !memcmp(p->h_addr, addr,
825 (size_t)len))
826 break;
827 _endhtent();
828 *((struct hostent **)rv) = p;
829 if (p==NULL) {
830 h_errno = HOST_NOT_FOUND;
831 return NS_NOTFOUND;
832 }
833 return NS_SUCCESS;
834 }
835
836 static void
837 map_v4v6_address(src, dst)
838 const char *src;
839 char *dst;
840 {
841 u_char *p = (u_char *)dst;
842 char tmp[INADDRSZ];
843 int i;
844
845 /* Stash a temporary copy so our caller can update in place. */
846 (void)memcpy(tmp, src, INADDRSZ);
847 /* Mark this ipv6 addr as a mapped ipv4. */
848 for (i = 0; i < 10; i++)
849 *p++ = 0x00;
850 *p++ = 0xff;
851 *p++ = 0xff;
852 /* Retrieve the saved copy and we're done. */
853 (void)memcpy((void *)p, tmp, INADDRSZ);
854 }
855
856 static void
857 map_v4v6_hostent(hp, bpp, lenp)
858 struct hostent *hp;
859 char **bpp;
860 int *lenp;
861 {
862 char **ap;
863
864 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
865 return;
866 hp->h_addrtype = AF_INET6;
867 hp->h_length = IN6ADDRSZ;
868 for (ap = hp->h_addr_list; *ap; ap++) {
869 int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align));
870
871 if (*lenp < (i + IN6ADDRSZ)) {
872 /* Out of memory. Truncate address list here. XXX */
873 *ap = NULL;
874 return;
875 }
876 *bpp += i;
877 *lenp -= i;
878 map_v4v6_address(*ap, *bpp);
879 *ap = *bpp;
880 *bpp += IN6ADDRSZ;
881 *lenp -= IN6ADDRSZ;
882 }
883 }
884
885 #ifdef RESOLVSORT
886 static void
887 addrsort(ap, num)
888 char **ap;
889 int num;
890 {
891 int i, j;
892 char **p;
893 short aval[MAXADDRS];
894 int needsort = 0;
895
896 p = ap;
897 for (i = 0; i < num; i++, p++) {
898 for (j = 0 ; (unsigned)j < _res.nsort; j++)
899 if (_res.sort_list[j].addr.s_addr ==
900 (((struct in_addr *)(void *)(*p))->s_addr &
901 _res.sort_list[j].mask))
902 break;
903 aval[i] = j;
904 if (needsort == 0 && i > 0 && j < aval[i-1])
905 needsort = i;
906 }
907 if (!needsort)
908 return;
909
910 while (needsort < num) {
911 for (j = needsort - 1; j >= 0; j--) {
912 if (aval[j] > aval[j+1]) {
913 char *hp;
914
915 i = aval[j];
916 aval[j] = aval[j+1];
917 aval[j+1] = i;
918
919 hp = ap[j];
920 ap[j] = ap[j+1];
921 ap[j+1] = hp;
922
923 } else
924 break;
925 }
926 needsort++;
927 }
928 }
929 #endif
930
931 #if defined(BSD43_BSD43_NFS) || defined(sun)
932 /* some libc's out there are bound internally to these names (UMIPS) */
933 void
934 ht_sethostent(stayopen)
935 int stayopen;
936 {
937 _sethtent(stayopen);
938 }
939
940 void
941 ht_endhostent()
942 {
943 _endhtent();
944 }
945
946 struct hostent *
947 ht_gethostbyname(name)
948 char *name;
949 {
950 return (_gethtbyname(name));
951 }
952
953 struct hostent *
954 ht_gethostbyaddr(addr, len, af)
955 const char *addr;
956 int len, af;
957 {
958 return (_gethtbyaddr(addr, len, af));
959 }
960
961 struct hostent *
962 gethostent()
963 {
964 return (_gethtent());
965 }
966
967 void
968 dns_service()
969 {
970 return;
971 }
972
973 #undef dn_skipname
974 dn_skipname(comp_dn, eom)
975 const u_char *comp_dn, *eom;
976 {
977 return (__dn_skipname(comp_dn, eom));
978 }
979 #endif /*old-style libc with yp junk in it*/
980
981 /*ARGSUSED*/
982 int
983 _dns_gethtbyname(rv, cb_data, ap)
984 void *rv;
985 void *cb_data;
986 va_list ap;
987 {
988 querybuf buf;
989 int n, type;
990 struct hostent *hp;
991 const char *name;
992 int len, af;
993
994 name = va_arg(ap, char *);
995 len = va_arg(ap, int);
996 #if defined(__GNUC__) || defined(lint) /* to shut up gcc warnings */
997 /*LINTED*/
998 (void)(len ? &len : &len);
999 #endif
1000 af = va_arg(ap, int);
1001
1002 switch (af) {
1003 case AF_INET:
1004 type = T_A;
1005 break;
1006 case AF_INET6:
1007 type = T_AAAA;
1008 break;
1009 default:
1010 return NS_UNAVAIL;
1011 }
1012 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
1013 dprintf("res_search failed (%d)\n", n);
1014 return NS_NOTFOUND;
1015 }
1016 hp = getanswer(&buf, n, name, type);
1017 if (hp == NULL)
1018 switch (h_errno) {
1019 case HOST_NOT_FOUND:
1020 return NS_NOTFOUND;
1021 case TRY_AGAIN:
1022 return NS_TRYAGAIN;
1023 default:
1024 return NS_UNAVAIL;
1025 }
1026 *((struct hostent **)rv) = hp;
1027 return NS_SUCCESS;
1028 }
1029
1030 /*ARGSUSED*/
1031 int
1032 _dns_gethtbyaddr(rv, cb_data, ap)
1033 void *rv;
1034 void *cb_data;
1035 va_list ap;
1036 {
1037 char qbuf[MAXDNAME + 1], *qp;
1038 int n;
1039 querybuf buf;
1040 struct hostent *hp;
1041 const unsigned char *uaddr;
1042 int len, af;
1043
1044 uaddr = va_arg(ap, unsigned char *);
1045 len = va_arg(ap, int);
1046 #ifdef __GNUC__ /* to shut up gcc warnings */
1047 (void)&len;
1048 #endif
1049 af = va_arg(ap, int);
1050
1051 switch (af) {
1052 case AF_INET:
1053 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
1054 (uaddr[3] & 0xff),
1055 (uaddr[2] & 0xff),
1056 (uaddr[1] & 0xff),
1057 (uaddr[0] & 0xff));
1058 break;
1059
1060 case AF_INET6:
1061 qp = qbuf;
1062 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
1063 qp += sprintf(qp, "%x.%x.",
1064 uaddr[n] & 0xf,
1065 ((unsigned int)uaddr[n] >> 4) & 0xf);
1066 }
1067 strcpy(qp, "ip6.int");
1068 break;
1069 default:
1070 abort();
1071 }
1072
1073 n = res_query(qbuf, C_IN, T_PTR, (u_char *)(void *)&buf, sizeof(buf));
1074 if (n < 0) {
1075 dprintf("res_query failed (%d)\n", n);
1076 return NS_NOTFOUND;
1077 }
1078 hp = getanswer(&buf, n, qbuf, T_PTR);
1079 if (hp == NULL)
1080 switch (h_errno) {
1081 case HOST_NOT_FOUND:
1082 return NS_NOTFOUND;
1083 case TRY_AGAIN:
1084 return NS_TRYAGAIN;
1085 default:
1086 return NS_UNAVAIL;
1087 }
1088 hp->h_addrtype = af;
1089 hp->h_length = len;
1090 (void)memcpy(host_addr, uaddr, (size_t)len);
1091 h_addr_ptrs[0] = (char *)&host_addr;
1092 h_addr_ptrs[1] = (char *)0;
1093 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
1094 map_v4v6_address((char*)host_addr, (char*)host_addr);
1095 hp->h_addrtype = AF_INET6;
1096 hp->h_length = IN6ADDRSZ;
1097 }
1098
1099 *((struct hostent **)rv) = hp;
1100 h_errno = NETDB_SUCCESS;
1101 return NS_SUCCESS;
1102 }
1103
1104 #ifdef YP
1105 /*ARGSUSED*/
1106 struct hostent *
1107 _yphostent(line, af)
1108 char *line;
1109 int af;
1110 {
1111 static struct in_addr host_addrs[MAXADDRS];
1112 char *p = line;
1113 char *cp, **q;
1114 char **hap;
1115 struct in_addr *buf;
1116 int more;
1117
1118 host.h_name = NULL;
1119 host.h_addr_list = h_addr_ptrs;
1120 host.h_length = sizeof(u_int32_t);
1121 host.h_addrtype = AF_INET;
1122 hap = h_addr_ptrs;
1123 buf = host_addrs;
1124 q = host.h_aliases = host_aliases;
1125
1126 /*
1127 * XXX: maybe support IPv6 parsing, based on 'af' setting
1128 */
1129 nextline:
1130 /* check for host_addrs overflow */
1131 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
1132 goto done;
1133
1134 more = 0;
1135 cp = strpbrk(p, " \t");
1136 if (cp == NULL)
1137 goto done;
1138 *cp++ = '\0';
1139
1140 *hap++ = (char *)(void *)buf;
1141 (void) inet_aton(p, buf++);
1142
1143 while (*cp == ' ' || *cp == '\t')
1144 cp++;
1145 p = cp;
1146 cp = strpbrk(p, " \t\n");
1147 if (cp != NULL) {
1148 if (*cp == '\n')
1149 more = 1;
1150 *cp++ = '\0';
1151 }
1152 if (!host.h_name)
1153 host.h_name = p;
1154 else if (strcmp(host.h_name, p)==0)
1155 ;
1156 else if (q < &host_aliases[MAXALIASES - 1])
1157 *q++ = p;
1158 p = cp;
1159 if (more)
1160 goto nextline;
1161
1162 while (cp && *cp) {
1163 if (*cp == ' ' || *cp == '\t') {
1164 cp++;
1165 continue;
1166 }
1167 if (*cp == '\n') {
1168 cp++;
1169 goto nextline;
1170 }
1171 if (q < &host_aliases[MAXALIASES - 1])
1172 *q++ = cp;
1173 cp = strpbrk(cp, " \t");
1174 if (cp != NULL)
1175 *cp++ = '\0';
1176 }
1177 done:
1178 if (host.h_name == NULL)
1179 return (NULL);
1180 *q = NULL;
1181 *hap = NULL;
1182 return (&host);
1183 }
1184
1185 /*ARGSUSED*/
1186 int
1187 _yp_gethtbyaddr(rv, cb_data, ap)
1188 void *rv;
1189 void *cb_data;
1190 va_list ap;
1191 {
1192 struct hostent *hp = (struct hostent *)NULL;
1193 static char *__ypcurrent;
1194 int __ypcurrentlen, r;
1195 char name[sizeof("xxx.xxx.xxx.xxx") + 1];
1196 const unsigned char *uaddr;
1197 int len, af;
1198
1199 uaddr = va_arg(ap, unsigned char *);
1200 len = va_arg(ap, int);
1201 #if defined(__GNUC__) || defined(lint) /* to shut up gcc warnings */
1202 /*LINTED*/
1203 (void)(len ? &len : &len);
1204 #endif
1205 af = va_arg(ap, int);
1206
1207 if (!__ypdomain) {
1208 if (_yp_check(&__ypdomain) == 0)
1209 return NS_UNAVAIL;
1210 }
1211 /*
1212 * XXX: based on the value of af, it would be possible to lookup
1213 * IPv6 names in YP, by changing the following snprintf().
1214 * Is it worth it?
1215 */
1216 (void)snprintf(name, sizeof name, "%u.%u.%u.%u",
1217 (uaddr[0] & 0xff),
1218 (uaddr[1] & 0xff),
1219 (uaddr[2] & 0xff),
1220 (uaddr[3] & 0xff));
1221 if (__ypcurrent)
1222 free(__ypcurrent);
1223 __ypcurrent = NULL;
1224 r = yp_match(__ypdomain, "hosts.byaddr", name,
1225 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1226 if (r==0)
1227 hp = _yphostent(__ypcurrent, af);
1228 if (hp==NULL) {
1229 h_errno = HOST_NOT_FOUND;
1230 return NS_NOTFOUND;
1231 }
1232 *((struct hostent **)rv) = hp;
1233 return NS_SUCCESS;
1234 }
1235
1236 /*ARGSUSED*/
1237 int
1238 _yp_gethtbyname(rv, cb_data, ap)
1239 void *rv;
1240 void *cb_data;
1241 va_list ap;
1242 {
1243 struct hostent *hp = (struct hostent *)NULL;
1244 static char *__ypcurrent;
1245 int __ypcurrentlen, r;
1246 const char *name;
1247 int len, af;
1248
1249 name = va_arg(ap, char *);
1250 len = va_arg(ap, int);
1251 #if defined(__GNUC__) || defined(lint) /* to shut up gcc warnings */
1252 /*LINTED*/
1253 (void)(len ? &len : &len);
1254 #endif
1255 af = va_arg(ap, int);
1256
1257 if (!__ypdomain) {
1258 if (_yp_check(&__ypdomain) == 0)
1259 return NS_UNAVAIL;
1260 }
1261 if (__ypcurrent)
1262 free(__ypcurrent);
1263 __ypcurrent = NULL;
1264 r = yp_match(__ypdomain, "hosts.byname", name,
1265 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1266 if (r==0)
1267 hp = _yphostent(__ypcurrent, af);
1268 if (hp==NULL) {
1269 h_errno = HOST_NOT_FOUND;
1270 return NS_NOTFOUND;
1271 }
1272 *((struct hostent **)rv) = hp;
1273 return NS_SUCCESS;
1274 }
1275 #endif
1276