]> git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/gethostbydns.c
ShellPkg/for: Fix potential null pointer deference
[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 #ifdef _ORG_FREEBSD_
133 static const char AskedForGot[] =
134 "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
135 #endif
136
137 static char *h_addr_ptrs[MAXADDRS + 1];
138
139 static struct hostent host;
140 static char *host_aliases[MAXALIASES];
141 static char hostbuf[8*1024];
142 static u_char host_addr[16]; /* IPv4 or IPv6 */
143
144 #ifdef RESOLVSORT
145 static void addrsort(char **, int);
146 #endif
147
148 #if PACKETSZ > 1024
149 #define MAXPACKET PACKETSZ
150 #else
151 #define MAXPACKET 1024
152 #endif
153
154 typedef union {
155 HEADER hdr;
156 u_char buf[MAXPACKET];
157 } querybuf;
158
159 typedef union {
160 int32_t al;
161 char ac;
162 } align;
163
164 extern int h_errno;
165 int _dns_ttl_;
166
167 #ifdef DEBUG_RES
168 static void
169 dprintf(char *msg, int num)
170 {
171 if (_res.options & RES_DEBUG) {
172 int save = errno;
173
174 printf(msg, num);
175 errno = save;
176 }
177 }
178 #else
179 # define dprintf(msg, num) /*nada*/
180 #endif
181
182 #define BOUNDED_INCR(x) \
183 do { \
184 cp += x; \
185 if (cp > eom) { \
186 h_errno = NO_RECOVERY; \
187 return (NULL); \
188 } \
189 } while (0)
190
191 #define BOUNDS_CHECK(ptr, count) \
192 do { \
193 if ((ptr) + (count) > eom) { \
194 h_errno = NO_RECOVERY; \
195 return (NULL); \
196 } \
197 } while (0)
198
199 static struct hostent *
200 gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
201 {
202 register const HEADER *hp;
203 register const u_char *cp;
204 register int n;
205 const u_char *eom, *erdata;
206 char *bp, **ap, **hap;
207 int type, class, buflen, ancount, qdcount;
208 int haveanswer, had_error;
209 int toobig = 0;
210 char tbuf[MAXDNAME];
211 const char *tname;
212 int (*name_ok)(const char *);
213
214 tname = qname;
215 host.h_name = NULL;
216 eom = answer->buf + anslen;
217 switch (qtype) {
218 case T_A:
219 case T_AAAA:
220 name_ok = res_hnok;
221 break;
222 case T_PTR:
223 name_ok = res_dnok;
224 break;
225 default:
226 h_errno = NO_RECOVERY;
227 return (NULL); /* XXX should be abort(); */
228 }
229 /*
230 * find first satisfactory answer
231 */
232 hp = &answer->hdr;
233 ancount = ntohs(hp->ancount);
234 qdcount = ntohs(hp->qdcount);
235 bp = hostbuf;
236 buflen = sizeof hostbuf;
237 cp = answer->buf;
238 BOUNDED_INCR(HFIXEDSZ);
239 if (qdcount != 1) {
240 h_errno = NO_RECOVERY;
241 return (NULL);
242 }
243 n = dn_expand(answer->buf, eom, cp, bp, buflen);
244 if ((n < 0) || !(*name_ok)(bp)) {
245 h_errno = NO_RECOVERY;
246 return (NULL);
247 }
248 BOUNDED_INCR(n + QFIXEDSZ);
249 if (qtype == T_A || qtype == T_AAAA) {
250 /* res_send() has already verified that the query name is the
251 * same as the one we sent; this just gets the expanded name
252 * (i.e., with the succeeding search-domain tacked on).
253 */
254 n = (int)strlen(bp) + 1; /* for the \0 */
255 if (n >= MAXHOSTNAMELEN) {
256 h_errno = NO_RECOVERY;
257 return (NULL);
258 }
259 host.h_name = bp;
260 bp += n;
261 buflen -= n;
262 /* The qname can be abbreviated, but h_name is now absolute. */
263 qname = host.h_name;
264 }
265 ap = host_aliases;
266 *ap = NULL;
267 host.h_aliases = host_aliases;
268 hap = h_addr_ptrs;
269 *hap = NULL;
270 host.h_addr_list = h_addr_ptrs;
271 haveanswer = 0;
272 had_error = 0;
273 _dns_ttl_ = -1;
274 while (ancount-- > 0 && cp < eom && !had_error) {
275 n = dn_expand(answer->buf, eom, cp, bp, buflen);
276 if ((n < 0) || !(*name_ok)(bp)) {
277 had_error++;
278 continue;
279 }
280 cp += n; /* name */
281 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
282 type = _getshort(cp);
283 cp += INT16SZ; /* type */
284 class = _getshort(cp);
285 cp += INT16SZ; /* class */
286 if (qtype == T_A && type == T_A)
287 _dns_ttl_ = _getlong(cp);
288 cp += INT32SZ; /* TTL */
289 n = _getshort(cp);
290 cp += INT16SZ; /* len */
291 BOUNDS_CHECK(cp, n);
292 erdata = cp + n;
293 if (class != C_IN) {
294 /* XXX - debug? syslog? */
295 cp += n;
296 continue; /* XXX - had_error++ ? */
297 }
298 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
299 if (ap >= &host_aliases[MAXALIASES-1])
300 continue;
301 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
302 if ((n < 0) || !(*name_ok)(tbuf)) {
303 had_error++;
304 continue;
305 }
306 cp += n;
307 if (cp != erdata) {
308 h_errno = NO_RECOVERY;
309 return (NULL);
310 }
311 /* Store alias. */
312 *ap++ = bp;
313 n = (int)strlen(bp) + 1; /* for the \0 */
314 if (n >= MAXHOSTNAMELEN) {
315 had_error++;
316 continue;
317 }
318 bp += n;
319 buflen -= n;
320 /* Get canonical name. */
321 n = (int)strlen(tbuf) + 1; /* for the \0 */
322 if (n > buflen || n >= MAXHOSTNAMELEN) {
323 had_error++;
324 continue;
325 }
326 strcpy(bp, tbuf);
327 host.h_name = bp;
328 bp += n;
329 buflen -= n;
330 continue;
331 }
332 if (qtype == T_PTR && type == T_CNAME) {
333 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
334 if (n < 0 || !res_dnok(tbuf)) {
335 had_error++;
336 continue;
337 }
338 cp += n;
339 if (cp != erdata) {
340 h_errno = NO_RECOVERY;
341 return (NULL);
342 }
343 /* Get canonical name. */
344 n = (int)strlen(tbuf) + 1; /* for the \0 */
345 if (n > buflen || n >= MAXHOSTNAMELEN) {
346 had_error++;
347 continue;
348 }
349 strcpy(bp, tbuf);
350 tname = bp;
351 bp += n;
352 buflen -= n;
353 continue;
354 }
355 if (type != qtype) {
356 #ifdef _ORG_FREEBSD_
357 syslog(LOG_NOTICE|LOG_AUTH,
358 "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
359 qname, p_class(C_IN), p_type(qtype),
360 p_type(type));
361 #endif
362 cp += n;
363 continue; /* XXX - had_error++ ? */
364 }
365 switch (type) {
366 case T_PTR:
367 if (strcasecmp(tname, bp) != 0) {
368 #ifdef _ORG_FREEBSD_
369 syslog(LOG_NOTICE|LOG_AUTH,
370 AskedForGot, qname, bp);
371 #endif
372 cp += n;
373 continue; /* XXX - had_error++ ? */
374 }
375 n = dn_expand(answer->buf, eom, cp, bp, buflen);
376 if ((n < 0) || !res_hnok(bp)) {
377 had_error++;
378 break;
379 }
380 #if MULTI_PTRS_ARE_ALIASES
381 cp += n;
382 if (cp != erdata) {
383 h_errno = NO_RECOVERY;
384 return (NULL);
385 }
386 if (!haveanswer)
387 host.h_name = bp;
388 else if (ap < &host_aliases[MAXALIASES-1])
389 *ap++ = bp;
390 else
391 n = -1;
392 if (n != -1) {
393 n = (int)strlen(bp) + 1; /* for the \0 */
394 if (n >= MAXHOSTNAMELEN) {
395 had_error++;
396 break;
397 }
398 bp += n;
399 buflen -= n;
400 }
401 break;
402 #else
403 host.h_name = bp;
404 if (_res.options & RES_USE_INET6) {
405 n = strlen(bp) + 1; /* for the \0 */
406 if (n >= MAXHOSTNAMELEN) {
407 had_error++;
408 break;
409 }
410 bp += n;
411 buflen -= n;
412 _map_v4v6_hostent(&host, &bp, &buflen);
413 }
414 h_errno = NETDB_SUCCESS;
415 return (&host);
416 #endif
417 case T_A:
418 case T_AAAA:
419 if (strcasecmp(host.h_name, bp) != 0) {
420 #ifdef _ORG_FREEBSD_
421 syslog(LOG_NOTICE|LOG_AUTH,
422 AskedForGot, host.h_name, bp);
423 #endif
424 cp += n;
425 continue; /* XXX - had_error++ ? */
426 }
427 if (n != host.h_length) {
428 cp += n;
429 continue;
430 }
431 if (!haveanswer) {
432 register int nn;
433
434 host.h_name = bp;
435 nn = (int)strlen(bp) + 1; /* for the \0 */
436 bp += nn;
437 buflen -= nn;
438 }
439
440 bp += sizeof(align) - ((size_t)bp % sizeof(align));
441
442 if (bp + n >= &hostbuf[sizeof hostbuf]) {
443 dprintf("size (%d) too big\n", n);
444 had_error++;
445 continue;
446 }
447 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
448 if (!toobig++)
449 dprintf("Too many addresses (%d)\n",
450 MAXADDRS);
451 cp += n;
452 continue;
453 }
454 *hap++ = bp;
455 bcopy(cp, bp, n);
456 bp += n;
457 buflen -= n;
458 cp += n;
459 if (cp != erdata) {
460 h_errno = NO_RECOVERY;
461 return (NULL);
462 }
463 break;
464 default:
465 dprintf("Impossible condition (type=%d)\n", type);
466 h_errno = NO_RECOVERY;
467 return (NULL);
468 /* BIND has abort() here, too risky on bad data */
469 }
470 if (!had_error)
471 haveanswer++;
472 }
473 if (haveanswer) {
474 *ap = NULL;
475 *hap = NULL;
476 # if defined(RESOLVSORT)
477 /*
478 * Note: we sort even if host can take only one address
479 * in its return structures - should give it the "best"
480 * address in that case, not some random one
481 */
482 if (_res.nsort && haveanswer > 1 && qtype == T_A)
483 addrsort(h_addr_ptrs, haveanswer);
484 # endif /*RESOLVSORT*/
485 if (!host.h_name) {
486 n = (int)strlen(qname) + 1; /* for the \0 */
487 if (n > buflen || n >= MAXHOSTNAMELEN)
488 goto no_recovery;
489 strcpy(bp, qname);
490 host.h_name = bp;
491 bp += n;
492 buflen -= n;
493 }
494 if (_res.options & RES_USE_INET6)
495 _map_v4v6_hostent(&host, &bp, &buflen);
496 h_errno = NETDB_SUCCESS;
497 return (&host);
498 }
499 no_recovery:
500 h_errno = NO_RECOVERY;
501 return (NULL);
502 }
503
504 struct hostent *
505 __dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
506 {
507 switch(qtype) {
508 case T_AAAA:
509 host.h_addrtype = AF_INET6;
510 host.h_length = IN6ADDRSZ;
511 break;
512 case T_A:
513 default:
514 host.h_addrtype = AF_INET;
515 host.h_length = INADDRSZ;
516 break;
517 }
518
519 return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
520 }
521
522 struct hostent *
523 _gethostbydnsname(const char *name, int af)
524 {
525 querybuf buf;
526 register const char *cp;
527 char *bp;
528 int n, size, type, len;
529
530 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
531 h_errno = NETDB_INTERNAL;
532 return (NULL);
533 }
534
535 switch (af) {
536 case AF_INET:
537 size = INADDRSZ;
538 type = T_A;
539 break;
540 case AF_INET6:
541 size = IN6ADDRSZ;
542 type = T_AAAA;
543 break;
544 default:
545 h_errno = NETDB_INTERNAL;
546 errno = EAFNOSUPPORT;
547 return (NULL);
548 }
549
550 host.h_addrtype = af;
551 host.h_length = size;
552
553 /*
554 * if there aren't any dots, it could be a user-level alias.
555 * this is also done in res_query() since we are not the only
556 * function that looks up host names.
557 */
558 if (!strchr(name, '.') && ( NULL != (cp = __hostalias(name))))
559 name = cp;
560
561 /*
562 * disallow names consisting only of digits/dots, unless
563 * they end in a dot.
564 */
565 if (isdigit(name[0]))
566 for (cp = name;; ++cp) {
567 if (!*cp) {
568 if (*--cp == '.')
569 break;
570 /*
571 * All-numeric, 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 len = sizeof hostbuf - MAXDNAME;
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 if (_res.options & RES_USE_INET6)
590 _map_v4v6_hostent(&host, &bp, &len);
591 h_errno = NETDB_SUCCESS;
592 return (&host);
593 }
594 if (!isdigit(*cp) && *cp != '.')
595 break;
596 }
597 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
598 name[0] == ':')
599 for (cp = name;; ++cp) {
600 if (!*cp) {
601 if (*--cp == '.')
602 break;
603 /*
604 * All-IPv6-legal, no dot at the end.
605 * Fake up a hostent as if we'd actually
606 * done a lookup.
607 */
608 if (inet_pton(af, name, host_addr) <= 0) {
609 h_errno = HOST_NOT_FOUND;
610 return (NULL);
611 }
612 strncpy(hostbuf, name, MAXDNAME);
613 hostbuf[MAXDNAME] = '\0';
614 bp = hostbuf + MAXDNAME;
615 len = sizeof hostbuf - MAXDNAME;
616 host.h_name = hostbuf;
617 host.h_aliases = host_aliases;
618 host_aliases[0] = NULL;
619 h_addr_ptrs[0] = (char *)host_addr;
620 h_addr_ptrs[1] = NULL;
621 host.h_addr_list = h_addr_ptrs;
622 h_errno = NETDB_SUCCESS;
623 return (&host);
624 }
625 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
626 break;
627 }
628
629 if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
630 dprintf("res_search failed (%d)\n", n);
631 return (NULL);
632 }
633 return (gethostanswer(&buf, n, name, type));
634 }
635
636 struct hostent *
637 _gethostbydnsaddr(const char *addr, int len, int af)
638 {
639 const u_char *uaddr = (const u_char *)addr;
640 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
641 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
642 int n, size;
643 querybuf buf;
644 register struct hostent *hp;
645 char qbuf[MAXDNAME+1], *qp;
646 #ifdef SUNSECURITY
647 register struct hostent *rhp;
648 char **haddr;
649 u_long old_options;
650 char hname2[MAXDNAME+1];
651 #endif /*SUNSECURITY*/
652
653 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
654 h_errno = NETDB_INTERNAL;
655 return (NULL);
656 }
657 if (af == AF_INET6 && len == IN6ADDRSZ &&
658 (!bcmp(uaddr, mapped, sizeof mapped) ||
659 !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
660 /* Unmap. */
661 addr += sizeof mapped;
662 uaddr += sizeof mapped;
663 af = AF_INET;
664 len = INADDRSZ;
665 }
666 switch (af) {
667 case AF_INET:
668 size = INADDRSZ;
669 break;
670 case AF_INET6:
671 size = IN6ADDRSZ;
672 break;
673 default:
674 errno = EAFNOSUPPORT;
675 h_errno = NETDB_INTERNAL;
676 return (NULL);
677 }
678 if (size != len) {
679 errno = EINVAL;
680 h_errno = NETDB_INTERNAL;
681 return (NULL);
682 }
683 switch (af) {
684 case AF_INET:
685 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
686 (uaddr[3] & 0xff),
687 (uaddr[2] & 0xff),
688 (uaddr[1] & 0xff),
689 (uaddr[0] & 0xff));
690 break;
691 case AF_INET6:
692 qp = qbuf;
693 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
694 qp += SPRINTF((qp, "%x.%x.",
695 uaddr[n] & 0xf,
696 (uaddr[n] >> 4) & 0xf));
697 }
698 strcpy(qp, "ip6.int");
699 break;
700 default:
701 abort();
702 }
703 n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
704 if (n < 0) {
705 dprintf("res_query failed (%d)\n", n);
706 return (NULL);
707 }
708 if ( NULL == (hp = gethostanswer(&buf, n, qbuf, T_PTR)))
709 return (NULL); /* h_errno was set by gethostanswer() */
710 #ifdef SUNSECURITY
711 if (af == AF_INET) {
712 /*
713 * turn off search as the name should be absolute,
714 * 'localhost' should be matched by defnames
715 */
716 strncpy(hname2, hp->h_name, MAXDNAME);
717 hname2[MAXDNAME] = '\0';
718 old_options = _res.options;
719 _res.options &= ~RES_DNSRCH;
720 _res.options |= RES_DEFNAMES;
721 if (!(rhp = gethostbyname(hname2))) {
722 #ifdef _ORG_FREEBSD_
723 syslog(LOG_NOTICE|LOG_AUTH,
724 "gethostbyaddr: No A record for %s (verifying [%s])",
725 hname2, inet_ntoa(*((struct in_addr *)addr)));
726 #endif
727 _res.options = old_options;
728 h_errno = HOST_NOT_FOUND;
729 return (NULL);
730 }
731 _res.options = old_options;
732 for (haddr = rhp->h_addr_list; *haddr; haddr++)
733 if (!memcmp(*haddr, addr, INADDRSZ))
734 break;
735 if (!*haddr) {
736 #ifdef _ORG_FREEBSD_
737 syslog(LOG_NOTICE|LOG_AUTH,
738 "gethostbyaddr: A record of %s != PTR record [%s]",
739 hname2, inet_ntoa(*((struct in_addr *)addr)));
740 #endif
741 h_errno = HOST_NOT_FOUND;
742 return (NULL);
743 }
744 }
745 #endif /*SUNSECURITY*/
746 hp->h_addrtype = af;
747 hp->h_length = len;
748 bcopy(addr, host_addr, len);
749 h_addr_ptrs[0] = (char *)host_addr;
750 h_addr_ptrs[1] = NULL;
751 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
752 _map_v4v6_address((char*)host_addr, (char*)host_addr);
753 hp->h_addrtype = AF_INET6;
754 hp->h_length = IN6ADDRSZ;
755 }
756 h_errno = NETDB_SUCCESS;
757 return (hp);
758 }
759
760 #ifdef RESOLVSORT
761 static void
762 addrsort(char **ap, int num)
763 {
764 short i, j;
765 char **p;
766 short aval[MAXADDRS];
767 short needsort = 0;
768
769 p = ap;
770 for (i = 0; i < num; i++, p++) {
771 for (j = 0 ; (unsigned)j < _res.nsort; j++)
772 if (_res.sort_list[j].addr.s_addr ==
773 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
774 break;
775 aval[i] = j;
776 if (needsort == 0 && i > 0 && j < aval[i-1])
777 needsort = i;
778 }
779 if (!needsort)
780 return;
781
782 while (needsort < num) {
783 for (j = needsort - 1; j >= 0; j--) {
784 if (aval[j] > aval[j+1]) {
785 char *hp;
786
787 i = aval[j];
788 aval[j] = aval[j+1];
789 aval[j+1] = i;
790
791 hp = ap[j];
792 ap[j] = ap[j+1];
793 ap[j+1] = hp;
794
795 } else
796 break;
797 }
798 needsort++;
799 }
800 }
801 #endif
802 void
803 _sethostdnsent(int stayopen)
804 {
805 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
806 return;
807 if (stayopen)
808 _res.options |= RES_STAYOPEN | RES_USEVC;
809 }
810
811 void
812 _endhostdnsent()
813 {
814 _res.options &= ~(RES_STAYOPEN | RES_USEVC);
815 res_close();
816 }