xref: /netbsd/lib/libc/resolv/res_query.c (revision 52799bbf)
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