1*52799bbfSchristos /* $NetBSD: res_query.c,v 1.16 2015/02/24 17:56:20 christos Exp $ */
259a755a4Schristos
359a755a4Schristos /*
459a755a4Schristos * Portions Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
559a755a4Schristos * Portions Copyright (C) 1996-2001, 2003 Internet Software Consortium.
659a755a4Schristos *
759a755a4Schristos * Permission to use, copy, modify, and/or distribute this software for any
859a755a4Schristos * purpose with or without fee is hereby granted, provided that the above
959a755a4Schristos * copyright notice and this permission notice appear in all copies.
1059a755a4Schristos *
1159a755a4Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
1259a755a4Schristos * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1359a755a4Schristos * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
1459a755a4Schristos * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1559a755a4Schristos * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
1659a755a4Schristos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1759a755a4Schristos * PERFORMANCE OF THIS SOFTWARE.
1859a755a4Schristos */
192b237084Schristos
202b237084Schristos /*
212b237084Schristos * Copyright (c) 1988, 1993
222b237084Schristos * The Regents of the University of California. All rights reserved.
232b237084Schristos *
242b237084Schristos * Redistribution and use in source and binary forms, with or without
252b237084Schristos * modification, are permitted provided that the following conditions
262b237084Schristos * are met:
272b237084Schristos * 1. Redistributions of source code must retain the above copyright
282b237084Schristos * notice, this list of conditions and the following disclaimer.
292b237084Schristos * 2. Redistributions in binary form must reproduce the above copyright
302b237084Schristos * notice, this list of conditions and the following disclaimer in the
312b237084Schristos * documentation and/or other materials provided with the distribution.
32*52799bbfSchristos * 3. Neither the name of the University nor the names of its contributors
332b237084Schristos * may be used to endorse or promote products derived from this software
342b237084Schristos * without specific prior written permission.
352b237084Schristos *
362b237084Schristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
372b237084Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
382b237084Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
392b237084Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
402b237084Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
412b237084Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
422b237084Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
432b237084Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
442b237084Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
452b237084Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
462b237084Schristos * SUCH DAMAGE.
472b237084Schristos */
482b237084Schristos
492b237084Schristos /*
502b237084Schristos * Portions Copyright (c) 1993 by Digital Equipment Corporation.
512b237084Schristos *
522b237084Schristos * Permission to use, copy, modify, and distribute this software for any
532b237084Schristos * purpose with or without fee is hereby granted, provided that the above
542b237084Schristos * copyright notice and this permission notice appear in all copies, and that
552b237084Schristos * the name of Digital Equipment Corporation not be used in advertising or
562b237084Schristos * publicity pertaining to distribution of the document or software without
572b237084Schristos * specific, written prior permission.
582b237084Schristos *
592b237084Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
602b237084Schristos * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
612b237084Schristos * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
622b237084Schristos * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
632b237084Schristos * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
642b237084Schristos * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
652b237084Schristos * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
662b237084Schristos * SOFTWARE.
672b237084Schristos */
682b237084Schristos
692b237084Schristos /*
702b237084Schristos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
712b237084Schristos * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
722b237084Schristos *
732b237084Schristos * Permission to use, copy, modify, and distribute this software for any
742b237084Schristos * purpose with or without fee is hereby granted, provided that the above
752b237084Schristos * copyright notice and this permission notice appear in all copies.
762b237084Schristos *
772b237084Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
782b237084Schristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
792b237084Schristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
802b237084Schristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
812b237084Schristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
822b237084Schristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
832b237084Schristos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
842b237084Schristos */
852b237084Schristos
86ca31adbdSchristos #include <sys/cdefs.h>
872b237084Schristos #if defined(LIBC_SCCS) && !defined(lint)
88ca31adbdSchristos #ifdef notdef
892b237084Schristos static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
9059a755a4Schristos static const char rcsid[] = "Id: res_query.c,v 1.11 2008/11/14 02:36:51 marka Exp";
91ca31adbdSchristos #else
92*52799bbfSchristos __RCSID("$NetBSD: res_query.c,v 1.16 2015/02/24 17:56:20 christos Exp $");
93ca31adbdSchristos #endif
942b237084Schristos #endif /* LIBC_SCCS and not lint */
952b237084Schristos
962b237084Schristos #include "port_before.h"
976f3786f4Schristos
986f3786f4Schristos #include "namespace.h"
992b237084Schristos #include <sys/types.h>
1002b237084Schristos #include <sys/param.h>
1012b237084Schristos #include <netinet/in.h>
1022b237084Schristos #include <arpa/inet.h>
1032b237084Schristos #include <arpa/nameser.h>
1042b237084Schristos #include <ctype.h>
1052b237084Schristos #include <errno.h>
1062b237084Schristos #include <netdb.h>
1072b237084Schristos #include <resolv.h>
1082b237084Schristos #include <stdio.h>
1092b237084Schristos #include <stdlib.h>
110f4265385Schristos #include <unistd.h>
1112b237084Schristos #include <string.h>
1122b237084Schristos #include "port_after.h"
1132b237084Schristos
1145ce4c264Schristos #if 0
1156f3786f4Schristos #ifdef __weak_alias
1166f3786f4Schristos __weak_alias(res_nquery,_res_nquery)
1176f3786f4Schristos __weak_alias(res_nsearch,_res_nsearch)
1186f3786f4Schristos __weak_alias(res_nquerydomain,__res_nquerydomain)
1196f3786f4Schristos __weak_alias(res_hostalias,__res_hostalias)
1206f3786f4Schristos #endif
1215ce4c264Schristos #endif
1226f3786f4Schristos
1232b237084Schristos /* Options. Leave them on. */
1247ce5e09dSchristos #ifndef DEBUG
1252b237084Schristos #define DEBUG
1267ce5e09dSchristos #endif
1272b237084Schristos
1282b237084Schristos #if PACKETSZ > 1024
1292b237084Schristos #define MAXPACKET PACKETSZ
1302b237084Schristos #else
1312b237084Schristos #define MAXPACKET 1024
1322b237084Schristos #endif
1332b237084Schristos
134d73eb73dSchristos /*%
1352b237084Schristos * Formulate a normal query, send, and await answer.
1362b237084Schristos * Returned answer is placed in supplied buffer "answer".
1372b237084Schristos * Perform preliminary check of answer, returning success only
1382b237084Schristos * if no error is indicated and the answer count is nonzero.
1392b237084Schristos * Return the size of the response on success, -1 on error.
1402b237084Schristos * Error number is left in H_ERRNO.
1412b237084Schristos *
1422b237084Schristos * Caller must parse answer and determine whether it answers the question.
1432b237084Schristos */
1442b237084Schristos int
res_nquery(res_state statp,const char * name,int class,int type,u_char * answer,int anslen)1452b237084Schristos res_nquery(res_state statp,
146d73eb73dSchristos const char *name, /*%< domain name */
147d73eb73dSchristos int class, int type, /*%< class and type of query */
148d73eb73dSchristos u_char *answer, /*%< buffer to put answer */
149d73eb73dSchristos int anslen) /*%< size of answer buffer */
1502b237084Schristos {
1512b237084Schristos u_char buf[MAXPACKET];
152d2fb1f98Schristos HEADER *hp = (HEADER *)(void *)answer;
1532b237084Schristos u_int oflags;
1543873655bSchristos u_char *rdata;
15559a755a4Schristos int n;
1562b237084Schristos
1572b237084Schristos oflags = statp->_flags;
1582b237084Schristos
1592b237084Schristos again:
160d73eb73dSchristos hp->rcode = NOERROR; /*%< default */
1612b237084Schristos #ifdef DEBUG
1622b237084Schristos if (statp->options & RES_DEBUG)
1632b237084Schristos printf(";; res_query(%s, %d, %d)\n", name, class, type);
1642b237084Schristos #endif
1652b237084Schristos
1662b237084Schristos n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
167e826745eSchristos buf, (int)sizeof(buf));
1682b237084Schristos #ifdef RES_USE_EDNS0
1692b237084Schristos if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
1703873655bSchristos (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID)) != 0U) {
171e826745eSchristos n = res_nopt(statp, n, buf, (int)sizeof(buf), anslen);
1723873655bSchristos rdata = &buf[n];
1733873655bSchristos if (n > 0 && (statp->options & RES_NSID) != 0U) {
174e826745eSchristos n = res_nopt_rdata(statp, n, buf, (int)sizeof(buf),
175e826745eSchristos rdata, NS_OPT_NSID, 0, NULL);
1763873655bSchristos }
1773873655bSchristos }
1782b237084Schristos #endif
1792b237084Schristos if (n <= 0) {
1802b237084Schristos #ifdef DEBUG
1812b237084Schristos if (statp->options & RES_DEBUG)
1822b237084Schristos printf(";; res_query: mkquery failed\n");
1832b237084Schristos #endif
1842b237084Schristos RES_SET_H_ERRNO(statp, NO_RECOVERY);
1852b237084Schristos return (n);
1862b237084Schristos }
1873873655bSchristos
1882b237084Schristos n = res_nsend(statp, buf, n, answer, anslen);
1892b237084Schristos if (n < 0) {
1902b237084Schristos #ifdef RES_USE_EDNS0
1912b237084Schristos /* if the query choked with EDNS0, retry without EDNS0 */
1922b237084Schristos if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U &&
1932b237084Schristos ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
1942b237084Schristos statp->_flags |= RES_F_EDNS0ERR;
1952b237084Schristos if (statp->options & RES_DEBUG)
1962b237084Schristos printf(";; res_nquery: retry without EDNS0\n");
1972b237084Schristos goto again;
1982b237084Schristos }
1992b237084Schristos #endif
2002b237084Schristos #ifdef DEBUG
2012b237084Schristos if (statp->options & RES_DEBUG)
2022b237084Schristos printf(";; res_query: send error\n");
2032b237084Schristos #endif
2042b237084Schristos RES_SET_H_ERRNO(statp, TRY_AGAIN);
2052b237084Schristos return (n);
2062b237084Schristos }
2072b237084Schristos
2082b237084Schristos if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
2092b237084Schristos #ifdef DEBUG
2102b237084Schristos if (statp->options & RES_DEBUG)
2112b237084Schristos printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n",
2122b237084Schristos p_rcode(hp->rcode),
2132b237084Schristos ntohs(hp->ancount),
2142b237084Schristos ntohs(hp->nscount),
2152b237084Schristos ntohs(hp->arcount));
2162b237084Schristos #endif
2172b237084Schristos switch (hp->rcode) {
2182b237084Schristos case NXDOMAIN:
2192b237084Schristos RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
2202b237084Schristos break;
2212b237084Schristos case SERVFAIL:
2222b237084Schristos RES_SET_H_ERRNO(statp, TRY_AGAIN);
2232b237084Schristos break;
2242b237084Schristos case NOERROR:
2252b237084Schristos RES_SET_H_ERRNO(statp, NO_DATA);
2262b237084Schristos break;
2272b237084Schristos case FORMERR:
2282b237084Schristos case NOTIMP:
2292b237084Schristos case REFUSED:
2302b237084Schristos default:
2312b237084Schristos RES_SET_H_ERRNO(statp, NO_RECOVERY);
2322b237084Schristos break;
2332b237084Schristos }
2342b237084Schristos return (-1);
2352b237084Schristos }
2362b237084Schristos return (n);
2372b237084Schristos }
2382b237084Schristos
239d73eb73dSchristos /*%
2402b237084Schristos * Formulate a normal query, send, and retrieve answer in supplied buffer.
2412b237084Schristos * Return the size of the response on success, -1 on error.
2422b237084Schristos * If enabled, implement search rules until answer or unrecoverable failure
2432b237084Schristos * is detected. Error code, if any, is left in H_ERRNO.
2442b237084Schristos */
2452b237084Schristos int
res_nsearch(res_state statp,const char * name,int class,int type,u_char * answer,int anslen)2462b237084Schristos res_nsearch(res_state statp,
247d73eb73dSchristos const char *name, /*%< domain name */
248d73eb73dSchristos int class, int type, /*%< class and type of query */
249d73eb73dSchristos u_char *answer, /*%< buffer to put answer */
250d73eb73dSchristos int anslen) /*%< size of answer */
2512b237084Schristos {
2522b237084Schristos const char *cp, * const *domain;
253d2fb1f98Schristos HEADER *hp = (HEADER *)(void *)answer;
2542b237084Schristos char tmp[NS_MAXDNAME];
2552b237084Schristos u_int dots;
2562b237084Schristos int trailing_dot, ret, saved_herrno;
2572b237084Schristos int got_nodata = 0, got_servfail = 0, root_on_list = 0;
2582b237084Schristos int tried_as_is = 0;
2592b237084Schristos int searched = 0;
2602b237084Schristos
2612b237084Schristos errno = 0;
262d73eb73dSchristos RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /*%< True if we never query. */
2632b237084Schristos dots = 0;
2642b237084Schristos for (cp = name; *cp != '\0'; cp++)
2652b237084Schristos dots += (*cp == '.');
2662b237084Schristos trailing_dot = 0;
2672b237084Schristos if (cp > name && *--cp == '.')
2682b237084Schristos trailing_dot++;
2692b237084Schristos
2702b237084Schristos /* If there aren't any dots, it could be a user-level alias. */
2712b237084Schristos if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
2722b237084Schristos return (res_nquery(statp, cp, class, type, answer, anslen));
2732b237084Schristos
2742b237084Schristos /*
2752b237084Schristos * If there are enough dots in the name, let's just give it a
2762b237084Schristos * try 'as is'. The threshold can be set with the "ndots" option.
2772b237084Schristos * Also, query 'as is', if there is a trailing dot in the name.
2782b237084Schristos */
2792b237084Schristos saved_herrno = -1;
2802b237084Schristos if (dots >= statp->ndots || trailing_dot) {
2812b237084Schristos ret = res_nquerydomain(statp, name, NULL, class, type,
2822b237084Schristos answer, anslen);
2832b237084Schristos if (ret > 0 || trailing_dot)
2842b237084Schristos return (ret);
2852b237084Schristos saved_herrno = statp->res_h_errno;
2862b237084Schristos tried_as_is++;
2872b237084Schristos }
2882b237084Schristos
2892b237084Schristos /*
2902b237084Schristos * We do at least one level of search if
2912b237084Schristos * - there is no dot and RES_DEFNAME is set, or
2922b237084Schristos * - there is at least one dot, there is no trailing dot,
2932b237084Schristos * and RES_DNSRCH is set.
2942b237084Schristos */
2952b237084Schristos if ((!dots && (statp->options & RES_DEFNAMES) != 0U) ||
2962b237084Schristos (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) {
2972b237084Schristos int done = 0;
2982b237084Schristos
2992b237084Schristos for (domain = (const char * const *)statp->dnsrch;
3002b237084Schristos *domain && !done;
3012b237084Schristos domain++) {
3022b237084Schristos searched = 1;
3032b237084Schristos
3042b237084Schristos if (domain[0][0] == '\0' ||
3052b237084Schristos (domain[0][0] == '.' && domain[0][1] == '\0'))
3062b237084Schristos root_on_list++;
3072b237084Schristos
3082b237084Schristos ret = res_nquerydomain(statp, name, *domain,
3092b237084Schristos class, type,
3102b237084Schristos answer, anslen);
3112b237084Schristos if (ret > 0)
3122b237084Schristos return (ret);
3132b237084Schristos
3142b237084Schristos /*
3152b237084Schristos * If no server present, give up.
3162b237084Schristos * If name isn't found in this domain,
3172b237084Schristos * keep trying higher domains in the search list
3182b237084Schristos * (if that's enabled).
3192b237084Schristos * On a NO_DATA error, keep trying, otherwise
3202b237084Schristos * a wildcard entry of another type could keep us
3212b237084Schristos * from finding this entry higher in the domain.
3222b237084Schristos * If we get some other error (negative answer or
3232b237084Schristos * server failure), then stop searching up,
3242b237084Schristos * but try the input name below in case it's
3252b237084Schristos * fully-qualified.
3262b237084Schristos */
3272b237084Schristos if (errno == ECONNREFUSED) {
3282b237084Schristos RES_SET_H_ERRNO(statp, TRY_AGAIN);
3292b237084Schristos return (-1);
3302b237084Schristos }
3312b237084Schristos
3322b237084Schristos switch (statp->res_h_errno) {
3332b237084Schristos case NO_DATA:
3342b237084Schristos got_nodata++;
3352b237084Schristos /* FALLTHROUGH */
3362b237084Schristos case HOST_NOT_FOUND:
3372b237084Schristos /* keep trying */
3382b237084Schristos break;
3392b237084Schristos case TRY_AGAIN:
3402b237084Schristos if (hp->rcode == SERVFAIL) {
3412b237084Schristos /* try next search element, if any */
3422b237084Schristos got_servfail++;
3432b237084Schristos break;
3442b237084Schristos }
3452b237084Schristos /* FALLTHROUGH */
3462b237084Schristos default:
3472b237084Schristos /* anything else implies that we're done */
3482b237084Schristos done++;
3492b237084Schristos }
3502b237084Schristos
3512b237084Schristos /* if we got here for some reason other than DNSRCH,
3522b237084Schristos * we only wanted one iteration of the loop, so stop.
3532b237084Schristos */
3542b237084Schristos if ((statp->options & RES_DNSRCH) == 0U)
3552b237084Schristos done++;
3562b237084Schristos }
3572b237084Schristos }
3582b237084Schristos
3592b237084Schristos /*
3602b237084Schristos * If the query has not already been tried as is then try it
3612b237084Schristos * unless RES_NOTLDQUERY is set and there were no dots.
3622b237084Schristos */
3632b237084Schristos if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) &&
3642b237084Schristos !(tried_as_is || root_on_list)) {
3652b237084Schristos ret = res_nquerydomain(statp, name, NULL, class, type,
3662b237084Schristos answer, anslen);
3672b237084Schristos if (ret > 0)
3682b237084Schristos return (ret);
3692b237084Schristos }
3702b237084Schristos
3712b237084Schristos /* if we got here, we didn't satisfy the search.
3722b237084Schristos * if we did an initial full query, return that query's H_ERRNO
3732b237084Schristos * (note that we wouldn't be here if that query had succeeded).
3742b237084Schristos * else if we ever got a nodata, send that back as the reason.
3752b237084Schristos * else send back meaningless H_ERRNO, that being the one from
3762b237084Schristos * the last DNSRCH we did.
3772b237084Schristos */
3782b237084Schristos if (saved_herrno != -1)
3792b237084Schristos RES_SET_H_ERRNO(statp, saved_herrno);
3802b237084Schristos else if (got_nodata)
3812b237084Schristos RES_SET_H_ERRNO(statp, NO_DATA);
3822b237084Schristos else if (got_servfail)
3832b237084Schristos RES_SET_H_ERRNO(statp, TRY_AGAIN);
3842b237084Schristos return (-1);
3852b237084Schristos }
3862b237084Schristos
387d73eb73dSchristos /*%
3882b237084Schristos * Perform a call on res_query on the concatenation of name and domain,
3892b237084Schristos * removing a trailing dot from name if domain is NULL.
3902b237084Schristos */
3912b237084Schristos int
res_nquerydomain(res_state statp,const char * name,const char * domain,int class,int type,u_char * answer,int anslen)3922b237084Schristos res_nquerydomain(res_state statp,
3932b237084Schristos const char *name,
3942b237084Schristos const char *domain,
395d73eb73dSchristos int class, int type, /*%< class and type of query */
396d73eb73dSchristos u_char *answer, /*%< buffer to put answer */
397d73eb73dSchristos int anslen) /*%< size of answer */
3982b237084Schristos {
3992b237084Schristos char nbuf[MAXDNAME];
4002b237084Schristos const char *longname = nbuf;
401e826745eSchristos size_t n, d;
4022b237084Schristos
4032b237084Schristos #ifdef DEBUG
4042b237084Schristos if (statp->options & RES_DEBUG)
4052b237084Schristos printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
4062b237084Schristos name, domain?domain:"<Nil>", class, type);
4072b237084Schristos #endif
4082b237084Schristos if (domain == NULL) {
4092b237084Schristos /*
4102b237084Schristos * Check for trailing '.';
4112b237084Schristos * copy without '.' if present.
4122b237084Schristos */
4132b237084Schristos n = strlen(name);
4142b237084Schristos if (n >= MAXDNAME) {
4152b237084Schristos RES_SET_H_ERRNO(statp, NO_RECOVERY);
4162b237084Schristos return (-1);
4172b237084Schristos }
418e826745eSchristos if (n && name[--n] == '.') {
419e826745eSchristos strncpy(nbuf, name, n);
4202b237084Schristos nbuf[n] = '\0';
4212b237084Schristos } else
4222b237084Schristos longname = name;
4232b237084Schristos } else {
4242b237084Schristos n = strlen(name);
4252b237084Schristos d = strlen(domain);
4262b237084Schristos if (n + d + 1 >= MAXDNAME) {
4272b237084Schristos RES_SET_H_ERRNO(statp, NO_RECOVERY);
4282b237084Schristos return (-1);
4292b237084Schristos }
4302b237084Schristos sprintf(nbuf, "%s.%s", name, domain);
4312b237084Schristos }
4322b237084Schristos return (res_nquery(statp, longname, class, type, answer, anslen));
4332b237084Schristos }
4342b237084Schristos
4352b237084Schristos const char *
res_hostalias(const res_state statp,const char * name,char * dst,size_t siz)4362b237084Schristos res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
4372b237084Schristos char *file, *cp1, *cp2;
4382b237084Schristos char buf[BUFSIZ];
4392b237084Schristos FILE *fp;
4402b237084Schristos
4412b237084Schristos if (statp->options & RES_NOALIASES)
4422b237084Schristos return (NULL);
443f4265385Schristos /*
444f4265385Schristos * forbid hostaliases for setuid binary, due to possible security
445f4265385Schristos * breach.
446f4265385Schristos */
447f4265385Schristos if (issetugid())
448f4265385Schristos return (NULL);
4492b237084Schristos file = getenv("HOSTALIASES");
450cc593076Schristos if (file == NULL || (fp = fopen(file, "re")) == NULL)
4512b237084Schristos return (NULL);
4522b237084Schristos buf[sizeof(buf) - 1] = '\0';
453e826745eSchristos while (fgets(buf, (int)sizeof(buf), fp)) {
4542b237084Schristos for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1)
4552b237084Schristos ;
4562b237084Schristos if (!*cp1)
4572b237084Schristos break;
4582b237084Schristos *cp1 = '\0';
4592b237084Schristos if (ns_samename(buf, name) == 1) {
4602b237084Schristos while (isspace((unsigned char)*++cp1))
4612b237084Schristos ;
4622b237084Schristos if (!*cp1)
4632b237084Schristos break;
4642b237084Schristos for (cp2 = cp1 + 1; *cp2 &&
4652b237084Schristos !isspace((unsigned char)*cp2); ++cp2)
4662b237084Schristos ;
4672b237084Schristos *cp2 = '\0';
4682b237084Schristos strncpy(dst, cp1, siz - 1);
4692b237084Schristos dst[siz - 1] = '\0';
4702b237084Schristos fclose(fp);
4712b237084Schristos return (dst);
4722b237084Schristos }
4732b237084Schristos }
4742b237084Schristos fclose(fp);
4752b237084Schristos return (NULL);
4762b237084Schristos }
477d73eb73dSchristos
478d73eb73dSchristos /*! \file */
479