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