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