]> git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/gethostbydns.c
Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / StdLib / BsdSocketLib / gethostbydns.c
1 /*
2 * ++Copyright++ 1985, 1988, 1993
3 * -
4 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
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.
22 *
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.
36 *
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.
43 *
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--
54 */
55
56 /*
57 * Portions copyright (c) 1999, 2000
58 * Intel Corporation.
59 * All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 *
65 * 1. Redistributions of source code must retain the above copyright
66 * notice, this list of conditions and the following disclaimer.
67 *
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in the
70 * documentation and/or other materials provided with the distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this software
73 * must display the following acknowledgement:
74 *
75 * This product includes software developed by Intel Corporation and
76 * its contributors.
77 *
78 * 4. Neither the name of Intel Corporation or its contributors may be
79 * used to endorse or promote products derived from this software
80 * without specific prior written permission.
81 *
82 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
83 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85 * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
86 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
87 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
88 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
89 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
90 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
91 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
92 * THE POSSIBILITY OF SUCH DAMAGE.
93 *
94 */
95
96 #if defined(LIBC_SCCS) && !defined(lint)
97 static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
98 static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
99 static char rcsid[] = "$Id: gethostbydns.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
100 #endif /* LIBC_SCCS and not lint */
101
102 #include <sys/types.h>
103 #include <sys/param.h>
104 #include <sys/socket.h>
105 #include <netinet/in.h>
106 #include <arpa/inet.h>
107 #include <arpa/nameser.h>
108
109 #include <stdio.h>
110 #include <unistd.h>
111 #include <string.h>
112 #include <netdb.h>
113 #include <resolv.h>
114 #include <ctype.h>
115 #include <errno.h>
116 #ifdef _ORG_FREEBSD_
117 #include <syslog.h>
118 #else
119 #include <stdlib.h>
120 u_int32_t _getlong(const u_char *src);
121 u_int16_t _getshort(const u_char *src);
122 #endif
123
124 #include "res_config.h"
125 #include "Socklib_internals.h"
126
127 #define SPRINTF(x) ((size_t)sprintf x)
128
129 #define MAXALIASES 35
130 #define MAXADDRS 35
131
132 static const char AskedForGot[] =
133 "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
134
135 static char *h_addr_ptrs[MAXADDRS + 1];
136
137 static struct hostent host;
138 static char *host_aliases[MAXALIASES];
139 static char hostbuf[8*1024];
140 static u_char host_addr[16]; /* IPv4 or IPv6 */
141
142 #ifdef RESOLVSORT
143 static void addrsort(char **, int);
144 #endif
145
146 #if PACKETSZ > 1024
147 #define MAXPACKET PACKETSZ
148 #else
149 #define MAXPACKET 1024
150 #endif
151
152 typedef union {
153 HEADER hdr;
154 u_char buf[MAXPACKET];
155 } querybuf;
156
157 typedef union {
158 int32_t al;
159 char ac;
160 } align;
161
162 extern int h_errno;
163 int _dns_ttl_;
164
165 #ifdef DEBUG_RES
166 static void
167 dprintf(char *msg, int num)
168 {
169 if (_res.options & RES_DEBUG) {
170 int save = errno;
171
172 printf(msg, num);
173 errno = save;
174 }
175 }
176 #else
177 # define dprintf(msg, num) /*nada*/
178 #endif
179
180 #define BOUNDED_INCR(x) \
181 do { \
182 cp += x; \
183 if (cp > eom) { \
184 h_errno = NO_RECOVERY; \
185 return (NULL); \
186 } \
187 } while (0)
188
189 #define BOUNDS_CHECK(ptr, count) \
190 do { \
191 if ((ptr) + (count) > eom) { \
192 h_errno = NO_RECOVERY; \
193 return (NULL); \
194 } \
195 } while (0)
196
197 static struct hostent *
198 gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
199 {
200 register const HEADER *hp;
201 register const u_char *cp;
202 register int n;
203 const u_char *eom, *erdata;
204 char *bp, **ap, **hap;
205 int type, class, buflen, ancount, qdcount;
206 int haveanswer, had_error;
207 int toobig = 0;
208 char tbuf[MAXDNAME];
209 const char *tname;
210 int (*name_ok)(const char *);
211
212 tname = qname;
213 host.h_name = NULL;
214 eom = answer->buf + anslen;
215 switch (qtype) {
216 case T_A:
217 case T_AAAA:
218 name_ok = res_hnok;
219 break;
220 case T_PTR:
221 name_ok = res_dnok;
222 break;
223 default:
224 h_errno = NO_RECOVERY;
225 return (NULL); /* XXX should be abort(); */
226 }
227 /*
228 * find first satisfactory answer
229 */
230 hp = &answer->hdr;
231 ancount = ntohs(hp->ancount);
232 qdcount = ntohs(hp->qdcount);
233 bp = hostbuf;
234 buflen = sizeof hostbuf;
235 cp = answer->buf;
236 BOUNDED_INCR(HFIXEDSZ);
237 if (qdcount != 1) {
238 h_errno = NO_RECOVERY;
239 return (NULL);
240 }
241 n = dn_expand(answer->buf, eom, cp, bp, buflen);
242 if ((n < 0) || !(*name_ok)(bp)) {
243 h_errno = NO_RECOVERY;
244 return (NULL);
245 }
246 BOUNDED_INCR(n + QFIXEDSZ);
247 if (qtype == T_A || qtype == T_AAAA) {
248 /* res_send() has already verified that the query name is the
249 * same as the one we sent; this just gets the expanded name
250 * (i.e., with the succeeding search-domain tacked on).
251 */
252 n = (int)strlen(bp) + 1; /* for the \0 */
253 if (n >= MAXHOSTNAMELEN) {
254 h_errno = NO_RECOVERY;
255 return (NULL);
256 }
257 host.h_name = bp;
258 bp += n;
259 buflen -= n;
260 /* The qname can be abbreviated, but h_name is now absolute. */
261 qname = host.h_name;
262 }
263 ap = host_aliases;
264 *ap = NULL;
265 host.h_aliases = host_aliases;
266 hap = h_addr_ptrs;
267 *hap = NULL;
268 host.h_addr_list = h_addr_ptrs;
269 haveanswer = 0;
270 had_error = 0;
271 _dns_ttl_ = -1;
272 while (ancount-- > 0 && cp < eom && !had_error) {
273 n = dn_expand(answer->buf, eom, cp, bp, buflen);
274 if ((n < 0) || !(*name_ok)(bp)) {
275 had_error++;
276 continue;
277 }
278 cp += n; /* name */
279 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
280 type = _getshort(cp);
281 cp += INT16SZ; /* type */
282 class = _getshort(cp);
283 cp += INT16SZ; /* class */
284 if (qtype == T_A && type == T_A)
285 _dns_ttl_ = _getlong(cp);
286 cp += INT32SZ; /* TTL */
287 n = _getshort(cp);
288 cp += INT16SZ; /* len */
289 BOUNDS_CHECK(cp, n);
290 erdata = cp + n;
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 if (cp != erdata) {
306 h_errno = NO_RECOVERY;
307 return (NULL);
308 }
309 /* Store alias. */
310 *ap++ = bp;
311 n = (int)strlen(bp) + 1; /* for the \0 */
312 if (n >= MAXHOSTNAMELEN) {
313 had_error++;
314 continue;
315 }
316 bp += n;
317 buflen -= n;
318 /* Get canonical name. */
319 n = (int)strlen(tbuf) + 1; /* for the \0 */
320 if (n > buflen || n >= MAXHOSTNAMELEN) {
321 had_error++;
322 continue;
323 }
324 strcpy(bp, tbuf);
325 host.h_name = bp;
326 bp += n;
327 buflen -= n;
328 continue;
329 }
330 if (qtype == T_PTR && type == T_CNAME) {
331 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
332 if (n < 0 || !res_dnok(tbuf)) {
333 had_error++;
334 continue;
335 }
336 cp += n;
337 if (cp != erdata) {
338 h_errno = NO_RECOVERY;
339 return (NULL);
340 }
341 /* Get canonical name. */
342 n = (int)strlen(tbuf) + 1; /* for the \0 */
343 if (n > buflen || n >= MAXHOSTNAMELEN) {
344 had_error++;
345 continue;
346 }
347 strcpy(bp, tbuf);
348 tname = bp;
349 bp += n;
350 buflen -= n;
351 continue;
352 }
353 if (type != qtype) {
354 #ifdef _ORG_FREEBSD_
355 syslog(LOG_NOTICE|LOG_AUTH,
356 "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
357 qname, p_class(C_IN), p_type(qtype),
358 p_type(type));
359 #endif
360 cp += n;
361 continue; /* XXX - had_error++ ? */
362 }
363 switch (type) {
364 case T_PTR:
365 if (strcasecmp(tname, bp) != 0) {
366 #ifdef _ORG_FREEBSD_
367 syslog(LOG_NOTICE|LOG_AUTH,
368 AskedForGot, qname, bp);
369 #endif
370 cp += n;
371 continue; /* XXX - had_error++ ? */
372 }
373 n = dn_expand(answer->buf, eom, cp, bp, buflen);
374 if ((n < 0) || !res_hnok(bp)) {
375 had_error++;
376 break;
377 }
378 #if MULTI_PTRS_ARE_ALIASES
379 cp += n;
380 if (cp != erdata) {
381 h_errno = NO_RECOVERY;
382 return (NULL);
383 }
384 if (!haveanswer)
385 host.h_name = bp;
386 else if (ap < &host_aliases[MAXALIASES-1])
387 *ap++ = bp;
388 else
389 n = -1;
390 if (n != -1) {
391 n = (int)strlen(bp) + 1; /* for the \0 */
392 if (n >= MAXHOSTNAMELEN) {
393 had_error++;
394 break;
395 }
396 bp += n;
397 buflen -= n;
398 }
399 break;
400 #else
401 host.h_name = bp;
402 if (_res.options & RES_USE_INET6) {
403 n = strlen(bp) + 1; /* for the \0 */
404 if (n >= MAXHOSTNAMELEN) {
405 had_error++;
406 break;
407 }
408 bp += n;
409 buflen -= n;
410 _map_v4v6_hostent(&host, &bp, &buflen);
411 }
412 h_errno = NETDB_SUCCESS;
413 return (&host);
414 #endif
415 case T_A:
416 case T_AAAA:
417 if (strcasecmp(host.h_name, bp) != 0) {
418 #ifdef _ORG_FREEBSD_
419 syslog(LOG_NOTICE|LOG_AUTH,
420 AskedForGot, host.h_name, bp);
421 #endif
422 cp += n;
423 continue; /* XXX - had_error++ ? */
424 }
425 if (n != host.h_length) {
426 cp += n;
427 continue;
428 }
429 if (!haveanswer) {
430 register int nn;
431
432 host.h_name = bp;
433 nn = (int)strlen(bp) + 1; /* for the \0 */
434 bp += nn;
435 buflen -= nn;
436 }
437
438 bp += sizeof(align) - ((size_t)bp % sizeof(align));
439
440 if (bp + n >= &hostbuf[sizeof hostbuf]) {
441 dprintf("size (%d) too big\n", n);
442 had_error++;
443 continue;
444 }
445 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
446 if (!toobig++)
447 dprintf("Too many addresses (%d)\n",
448 MAXADDRS);
449 cp += n;
450 continue;
451 }
452 *hap++ = bp;
453 bcopy(cp, bp, n);
454 bp += n;
455 buflen -= n;
456 cp += n;
457 if (cp != erdata) {
458 h_errno = NO_RECOVERY;
459 return (NULL);
460 }
461 break;
462 default:
463 dprintf("Impossible condition (type=%d)\n", type);
464 h_errno = NO_RECOVERY;
465 return (NULL);
466 /* BIND has abort() here, too risky on bad data */
467 }
468 if (!had_error)
469 haveanswer++;
470 }
471 if (haveanswer) {
472 *ap = NULL;
473 *hap = NULL;
474 # if defined(RESOLVSORT)
475 /*
476 * Note: we sort even if host can take only one address
477 * in its return structures - should give it the "best"
478 * address in that case, not some random one
479 */
480 if (_res.nsort && haveanswer > 1 && qtype == T_A)
481 addrsort(h_addr_ptrs, haveanswer);
482 # endif /*RESOLVSORT*/
483 if (!host.h_name) {
484 n = (int)strlen(qname) + 1; /* for the \0 */
485 if (n > buflen || n >= MAXHOSTNAMELEN)
486 goto no_recovery;
487 strcpy(bp, qname);
488 host.h_name = bp;
489 bp += n;
490 buflen -= n;
491 }
492 if (_res.options & RES_USE_INET6)
493 _map_v4v6_hostent(&host, &bp, &buflen);
494 h_errno = NETDB_SUCCESS;
495 return (&host);
496 }
497 no_recovery:
498 h_errno = NO_RECOVERY;
499 return (NULL);
500 }
501
502 struct hostent *
503 __dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
504 {
505 switch(qtype) {
506 case T_AAAA:
507 host.h_addrtype = AF_INET6;
508 host.h_length = IN6ADDRSZ;
509 break;
510 case T_A:
511 default:
512 host.h_addrtype = AF_INET;
513 host.h_length = INADDRSZ;
514 break;
515 }
516
517 return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
518 }
519
520 struct hostent *
521 _gethostbydnsname(const char *name, int af)
522 {
523 querybuf buf;
524 register const char *cp;
525 char *bp;
526 int n, size, type, len;
527
528 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
529 h_errno = NETDB_INTERNAL;
530 return (NULL);
531 }
532
533 switch (af) {
534 case AF_INET:
535 size = INADDRSZ;
536 type = T_A;
537 break;
538 case AF_INET6:
539 size = IN6ADDRSZ;
540 type = T_AAAA;
541 break;
542 default:
543 h_errno = NETDB_INTERNAL;
544 errno = EAFNOSUPPORT;
545 return (NULL);
546 }
547
548 host.h_addrtype = af;
549 host.h_length = size;
550
551 /*
552 * if there aren't any dots, it could be a user-level alias.
553 * this is also done in res_query() since we are not the only
554 * function that looks up host names.
555 */
556 if (!strchr(name, '.') && ( NULL != (cp = __hostalias(name))))
557 name = cp;
558
559 /*
560 * disallow names consisting only of digits/dots, unless
561 * they end in a dot.
562 */
563 if (isdigit(name[0]))
564 for (cp = name;; ++cp) {
565 if (!*cp) {
566 if (*--cp == '.')
567 break;
568 /*
569 * All-numeric, no dot at the end.
570 * Fake up a hostent as if we'd actually
571 * done a lookup.
572 */
573 if (inet_pton(af, name, host_addr) <= 0) {
574 h_errno = HOST_NOT_FOUND;
575 return (NULL);
576 }
577 strncpy(hostbuf, name, MAXDNAME);
578 hostbuf[MAXDNAME] = '\0';
579 bp = hostbuf + MAXDNAME;
580 len = sizeof hostbuf - MAXDNAME;
581 host.h_name = hostbuf;
582 host.h_aliases = host_aliases;
583 host_aliases[0] = NULL;
584 h_addr_ptrs[0] = (char *)host_addr;
585 h_addr_ptrs[1] = NULL;
586 host.h_addr_list = h_addr_ptrs;
587 if (_res.options & RES_USE_INET6)
588 _map_v4v6_hostent(&host, &bp, &len);
589 h_errno = NETDB_SUCCESS;
590 return (&host);
591 }
592 if (!isdigit(*cp) && *cp != '.')
593 break;
594 }
595 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
596 name[0] == ':')
597 for (cp = name;; ++cp) {
598 if (!*cp) {
599 if (*--cp == '.')
600 break;
601 /*
602 * All-IPv6-legal, no dot at the end.
603 * Fake up a hostent as if we'd actually
604 * done a lookup.
605 */
606 if (inet_pton(af, name, host_addr) <= 0) {
607 h_errno = HOST_NOT_FOUND;
608 return (NULL);
609 }
610 strncpy(hostbuf, name, MAXDNAME);
611 hostbuf[MAXDNAME] = '\0';
612 bp = hostbuf + MAXDNAME;
613 len = sizeof hostbuf - MAXDNAME;
614 host.h_name = hostbuf;
615 host.h_aliases = host_aliases;
616 host_aliases[0] = NULL;
617 h_addr_ptrs[0] = (char *)host_addr;
618 h_addr_ptrs[1] = NULL;
619 host.h_addr_list = h_addr_ptrs;
620 h_errno = NETDB_SUCCESS;
621 return (&host);
622 }
623 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
624 break;
625 }
626
627 if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
628 dprintf("res_search failed (%d)\n", n);
629 return (NULL);
630 }
631 return (gethostanswer(&buf, n, name, type));
632 }
633
634 struct hostent *
635 _gethostbydnsaddr(const char *addr, int len, int af)
636 {
637 const u_char *uaddr = (const u_char *)addr;
638 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
639 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
640 int n, size;
641 querybuf buf;
642 register struct hostent *hp;
643 char qbuf[MAXDNAME+1], *qp;
644 #ifdef SUNSECURITY
645 register struct hostent *rhp;
646 char **haddr;
647 u_long old_options;
648 char hname2[MAXDNAME+1];
649 #endif /*SUNSECURITY*/
650
651 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
652 h_errno = NETDB_INTERNAL;
653 return (NULL);
654 }
655 if (af == AF_INET6 && len == IN6ADDRSZ &&
656 (!bcmp(uaddr, mapped, sizeof mapped) ||
657 !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
658 /* Unmap. */
659 addr += sizeof mapped;
660 uaddr += sizeof mapped;
661 af = AF_INET;
662 len = INADDRSZ;
663 }
664 switch (af) {
665 case AF_INET:
666 size = INADDRSZ;
667 break;
668 case AF_INET6:
669 size = IN6ADDRSZ;
670 break;
671 default:
672 errno = EAFNOSUPPORT;
673 h_errno = NETDB_INTERNAL;
674 return (NULL);
675 }
676 if (size != len) {
677 errno = EINVAL;
678 h_errno = NETDB_INTERNAL;
679 return (NULL);
680 }
681 switch (af) {
682 case AF_INET:
683 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
684 (uaddr[3] & 0xff),
685 (uaddr[2] & 0xff),
686 (uaddr[1] & 0xff),
687 (uaddr[0] & 0xff));
688 break;
689 case AF_INET6:
690 qp = qbuf;
691 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
692 qp += SPRINTF((qp, "%x.%x.",
693 uaddr[n] & 0xf,
694 (uaddr[n] >> 4) & 0xf));
695 }
696 strcpy(qp, "ip6.int");
697 break;
698 default:
699 abort();
700 }
701 n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
702 if (n < 0) {
703 dprintf("res_query failed (%d)\n", n);
704 return (NULL);
705 }
706 if ( NULL == (hp = gethostanswer(&buf, n, qbuf, T_PTR)))
707 return (NULL); /* h_errno was set by gethostanswer() */
708 #ifdef SUNSECURITY
709 if (af == AF_INET) {
710 /*
711 * turn off search as the name should be absolute,
712 * 'localhost' should be matched by defnames
713 */
714 strncpy(hname2, hp->h_name, MAXDNAME);
715 hname2[MAXDNAME] = '\0';
716 old_options = _res.options;
717 _res.options &= ~RES_DNSRCH;
718 _res.options |= RES_DEFNAMES;
719 if (!(rhp = gethostbyname(hname2))) {
720 #ifdef _ORG_FREEBSD_
721 syslog(LOG_NOTICE|LOG_AUTH,
722 "gethostbyaddr: No A record for %s (verifying [%s])",
723 hname2, inet_ntoa(*((struct in_addr *)addr)));
724 #endif
725 _res.options = old_options;
726 h_errno = HOST_NOT_FOUND;
727 return (NULL);
728 }
729 _res.options = old_options;
730 for (haddr = rhp->h_addr_list; *haddr; haddr++)
731 if (!memcmp(*haddr, addr, INADDRSZ))
732 break;
733 if (!*haddr) {
734 #ifdef _ORG_FREEBSD_
735 syslog(LOG_NOTICE|LOG_AUTH,
736 "gethostbyaddr: A record of %s != PTR record [%s]",
737 hname2, inet_ntoa(*((struct in_addr *)addr)));
738 #endif
739 h_errno = HOST_NOT_FOUND;
740 return (NULL);
741 }
742 }
743 #endif /*SUNSECURITY*/
744 hp->h_addrtype = af;
745 hp->h_length = len;
746 bcopy(addr, host_addr, len);
747 h_addr_ptrs[0] = (char *)host_addr;
748 h_addr_ptrs[1] = NULL;
749 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
750 _map_v4v6_address((char*)host_addr, (char*)host_addr);
751 hp->h_addrtype = AF_INET6;
752 hp->h_length = IN6ADDRSZ;
753 }
754 h_errno = NETDB_SUCCESS;
755 return (hp);
756 }
757
758 #ifdef RESOLVSORT
759 static void
760 addrsort(char **ap, int num)
761 {
762 short i, j;
763 char **p;
764 short aval[MAXADDRS];
765 short needsort = 0;
766
767 p = ap;
768 for (i = 0; i < num; i++, p++) {
769 for (j = 0 ; (unsigned)j < _res.nsort; j++)
770 if (_res.sort_list[j].addr.s_addr ==
771 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
772 break;
773 aval[i] = j;
774 if (needsort == 0 && i > 0 && j < aval[i-1])
775 needsort = i;
776 }
777 if (!needsort)
778 return;
779
780 while (needsort < num) {
781 for (j = needsort - 1; j >= 0; j--) {
782 if (aval[j] > aval[j+1]) {
783 char *hp;
784
785 i = aval[j];
786 aval[j] = aval[j+1];
787 aval[j+1] = i;
788
789 hp = ap[j];
790 ap[j] = ap[j+1];
791 ap[j+1] = hp;
792
793 } else
794 break;
795 }
796 needsort++;
797 }
798 }
799 #endif
800 void
801 _sethostdnsent(int stayopen)
802 {
803 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
804 return;
805 if (stayopen)
806 _res.options |= RES_STAYOPEN | RES_USEVC;
807 }
808
809 void
810 _endhostdnsent()
811 {
812 _res.options &= ~(RES_STAYOPEN | RES_USEVC);
813 res_close();
814 }