165e96449SHajimu UMEMOTO /* 2046c3635SPedro F. Giffuni * Portions Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") 3046c3635SPedro F. Giffuni * Portions Copyright (C) 1996-2001, 2003 Internet Software Consortium. 4046c3635SPedro F. Giffuni * 5046c3635SPedro F. Giffuni * Permission to use, copy, modify, and/or distribute this software for any 6046c3635SPedro F. Giffuni * purpose with or without fee is hereby granted, provided that the above 7046c3635SPedro F. Giffuni * copyright notice and this permission notice appear in all copies. 8046c3635SPedro F. Giffuni * 9046c3635SPedro F. Giffuni * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10046c3635SPedro F. Giffuni * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11046c3635SPedro F. Giffuni * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12046c3635SPedro F. Giffuni * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13046c3635SPedro F. Giffuni * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14046c3635SPedro F. Giffuni * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15046c3635SPedro F. Giffuni * PERFORMANCE OF THIS SOFTWARE. 16046c3635SPedro F. Giffuni */ 17046c3635SPedro F. Giffuni 18046c3635SPedro F. Giffuni /* 1965e96449SHajimu UMEMOTO * Copyright (c) 1988, 1993 2065e96449SHajimu UMEMOTO * The Regents of the University of California. All rights reserved. 2165e96449SHajimu UMEMOTO * 2265e96449SHajimu UMEMOTO * Redistribution and use in source and binary forms, with or without 2365e96449SHajimu UMEMOTO * modification, are permitted provided that the following conditions 2465e96449SHajimu UMEMOTO * are met: 2565e96449SHajimu UMEMOTO * 1. Redistributions of source code must retain the above copyright 2665e96449SHajimu UMEMOTO * notice, this list of conditions and the following disclaimer. 2765e96449SHajimu UMEMOTO * 2. Redistributions in binary form must reproduce the above copyright 2865e96449SHajimu UMEMOTO * notice, this list of conditions and the following disclaimer in the 2965e96449SHajimu UMEMOTO * documentation and/or other materials provided with the distribution. 3065e96449SHajimu UMEMOTO * 4. Neither the name of the University nor the names of its contributors 3165e96449SHajimu UMEMOTO * may be used to endorse or promote products derived from this software 3265e96449SHajimu UMEMOTO * without specific prior written permission. 3365e96449SHajimu UMEMOTO * 3465e96449SHajimu UMEMOTO * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 3565e96449SHajimu UMEMOTO * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3665e96449SHajimu UMEMOTO * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3765e96449SHajimu UMEMOTO * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3865e96449SHajimu UMEMOTO * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3965e96449SHajimu UMEMOTO * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4065e96449SHajimu UMEMOTO * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4165e96449SHajimu UMEMOTO * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4265e96449SHajimu UMEMOTO * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4365e96449SHajimu UMEMOTO * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4465e96449SHajimu UMEMOTO * SUCH DAMAGE. 4565e96449SHajimu UMEMOTO */ 4665e96449SHajimu UMEMOTO 4765e96449SHajimu UMEMOTO /* 4865e96449SHajimu UMEMOTO * Portions Copyright (c) 1993 by Digital Equipment Corporation. 4965e96449SHajimu UMEMOTO * 5065e96449SHajimu UMEMOTO * Permission to use, copy, modify, and distribute this software for any 5165e96449SHajimu UMEMOTO * purpose with or without fee is hereby granted, provided that the above 5265e96449SHajimu UMEMOTO * copyright notice and this permission notice appear in all copies, and that 5365e96449SHajimu UMEMOTO * the name of Digital Equipment Corporation not be used in advertising or 5465e96449SHajimu UMEMOTO * publicity pertaining to distribution of the document or software without 5565e96449SHajimu UMEMOTO * specific, written prior permission. 5665e96449SHajimu UMEMOTO * 5765e96449SHajimu UMEMOTO * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 5865e96449SHajimu UMEMOTO * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 5965e96449SHajimu UMEMOTO * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 6065e96449SHajimu UMEMOTO * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 6165e96449SHajimu UMEMOTO * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 6265e96449SHajimu UMEMOTO * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 6365e96449SHajimu UMEMOTO * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 6465e96449SHajimu UMEMOTO * SOFTWARE. 6565e96449SHajimu UMEMOTO */ 6665e96449SHajimu UMEMOTO 6765e96449SHajimu UMEMOTO #if defined(LIBC_SCCS) && !defined(lint) 6865e96449SHajimu UMEMOTO static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; 69046c3635SPedro F. Giffuni static const char rcsid[] = "$Id: res_query.c,v 1.11 2008/11/14 02:36:51 marka Exp $"; 7065e96449SHajimu UMEMOTO #endif /* LIBC_SCCS and not lint */ 71ab96eeabSHajimu UMEMOTO #include <sys/cdefs.h> 72ab96eeabSHajimu UMEMOTO __FBSDID("$FreeBSD$"); 7365e96449SHajimu UMEMOTO 7465e96449SHajimu UMEMOTO #include "port_before.h" 7565e96449SHajimu UMEMOTO #include <sys/types.h> 7665e96449SHajimu UMEMOTO #include <sys/param.h> 7765e96449SHajimu UMEMOTO #include <netinet/in.h> 7865e96449SHajimu UMEMOTO #include <arpa/inet.h> 7965e96449SHajimu UMEMOTO #include <arpa/nameser.h> 8065e96449SHajimu UMEMOTO #include <ctype.h> 8165e96449SHajimu UMEMOTO #include <errno.h> 8265e96449SHajimu UMEMOTO #include <netdb.h> 8365e96449SHajimu UMEMOTO #include <resolv.h> 8465e96449SHajimu UMEMOTO #include <stdio.h> 8565e96449SHajimu UMEMOTO #include <stdlib.h> 8665e96449SHajimu UMEMOTO #include <string.h> 87ab96eeabSHajimu UMEMOTO #include <unistd.h> 8865e96449SHajimu UMEMOTO #include "port_after.h" 8965e96449SHajimu UMEMOTO 9065e96449SHajimu UMEMOTO /* Options. Leave them on. */ 91*8a615d0fSEnji Cooper #ifndef DEBUG 9265e96449SHajimu UMEMOTO #define DEBUG 93*8a615d0fSEnji Cooper #endif 9465e96449SHajimu UMEMOTO 9565e96449SHajimu UMEMOTO #if PACKETSZ > 1024 9665e96449SHajimu UMEMOTO #define MAXPACKET PACKETSZ 9765e96449SHajimu UMEMOTO #else 9865e96449SHajimu UMEMOTO #define MAXPACKET 1024 9965e96449SHajimu UMEMOTO #endif 10065e96449SHajimu UMEMOTO 101dde4a85dSHajimu UMEMOTO /*% 10265e96449SHajimu UMEMOTO * Formulate a normal query, send, and await answer. 10365e96449SHajimu UMEMOTO * Returned answer is placed in supplied buffer "answer". 10465e96449SHajimu UMEMOTO * Perform preliminary check of answer, returning success only 10565e96449SHajimu UMEMOTO * if no error is indicated and the answer count is nonzero. 10665e96449SHajimu UMEMOTO * Return the size of the response on success, -1 on error. 10765e96449SHajimu UMEMOTO * Error number is left in H_ERRNO. 10865e96449SHajimu UMEMOTO * 10965e96449SHajimu UMEMOTO * Caller must parse answer and determine whether it answers the question. 11065e96449SHajimu UMEMOTO */ 11165e96449SHajimu UMEMOTO int 11265e96449SHajimu UMEMOTO res_nquery(res_state statp, 113dde4a85dSHajimu UMEMOTO const char *name, /*%< domain name */ 114dde4a85dSHajimu UMEMOTO int class, int type, /*%< class and type of query */ 115dde4a85dSHajimu UMEMOTO u_char *answer, /*%< buffer to put answer */ 116dde4a85dSHajimu UMEMOTO int anslen) /*%< size of answer buffer */ 11765e96449SHajimu UMEMOTO { 11865e96449SHajimu UMEMOTO u_char buf[MAXPACKET]; 11965e96449SHajimu UMEMOTO HEADER *hp = (HEADER *) answer; 12065e96449SHajimu UMEMOTO u_int oflags; 12154ebdd63SHajimu UMEMOTO u_char *rdata; 12254ebdd63SHajimu UMEMOTO int n; 12365e96449SHajimu UMEMOTO 12465e96449SHajimu UMEMOTO oflags = statp->_flags; 12565e96449SHajimu UMEMOTO 12665e96449SHajimu UMEMOTO again: 127dde4a85dSHajimu UMEMOTO hp->rcode = NOERROR; /*%< default */ 12865e96449SHajimu UMEMOTO #ifdef DEBUG 12965e96449SHajimu UMEMOTO if (statp->options & RES_DEBUG) 13065e96449SHajimu UMEMOTO printf(";; res_query(%s, %d, %d)\n", name, class, type); 13165e96449SHajimu UMEMOTO #endif 13265e96449SHajimu UMEMOTO 13365e96449SHajimu UMEMOTO n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, 13465e96449SHajimu UMEMOTO buf, sizeof(buf)); 13565e96449SHajimu UMEMOTO #ifdef RES_USE_EDNS0 13665e96449SHajimu UMEMOTO if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && 13754ebdd63SHajimu UMEMOTO (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) { 13865e96449SHajimu UMEMOTO n = res_nopt(statp, n, buf, sizeof(buf), anslen); 13954ebdd63SHajimu UMEMOTO rdata = &buf[n]; 14054ebdd63SHajimu UMEMOTO if (n > 0 && (statp->options & RES_NSID) != 0U) { 14154ebdd63SHajimu UMEMOTO n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata, 14254ebdd63SHajimu UMEMOTO NS_OPT_NSID, 0, NULL); 14354ebdd63SHajimu UMEMOTO } 14454ebdd63SHajimu UMEMOTO } 14565e96449SHajimu UMEMOTO #endif 14665e96449SHajimu UMEMOTO if (n <= 0) { 14765e96449SHajimu UMEMOTO #ifdef DEBUG 14865e96449SHajimu UMEMOTO if (statp->options & RES_DEBUG) 14965e96449SHajimu UMEMOTO printf(";; res_query: mkquery failed\n"); 15065e96449SHajimu UMEMOTO #endif 15165e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, NO_RECOVERY); 15265e96449SHajimu UMEMOTO return (n); 15365e96449SHajimu UMEMOTO } 15454ebdd63SHajimu UMEMOTO 15565e96449SHajimu UMEMOTO n = res_nsend(statp, buf, n, answer, anslen); 15665e96449SHajimu UMEMOTO if (n < 0) { 15765e96449SHajimu UMEMOTO #ifdef RES_USE_EDNS0 15865e96449SHajimu UMEMOTO /* if the query choked with EDNS0, retry without EDNS0 */ 15965e96449SHajimu UMEMOTO if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U && 16065e96449SHajimu UMEMOTO ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { 16165e96449SHajimu UMEMOTO statp->_flags |= RES_F_EDNS0ERR; 16265e96449SHajimu UMEMOTO if (statp->options & RES_DEBUG) 16365e96449SHajimu UMEMOTO printf(";; res_nquery: retry without EDNS0\n"); 16465e96449SHajimu UMEMOTO goto again; 16565e96449SHajimu UMEMOTO } 16665e96449SHajimu UMEMOTO #endif 16765e96449SHajimu UMEMOTO #ifdef DEBUG 16865e96449SHajimu UMEMOTO if (statp->options & RES_DEBUG) 16965e96449SHajimu UMEMOTO printf(";; res_query: send error\n"); 17065e96449SHajimu UMEMOTO #endif 17165e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, TRY_AGAIN); 17265e96449SHajimu UMEMOTO return (n); 17365e96449SHajimu UMEMOTO } 17465e96449SHajimu UMEMOTO 17565e96449SHajimu UMEMOTO if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 17665e96449SHajimu UMEMOTO #ifdef DEBUG 17765e96449SHajimu UMEMOTO if (statp->options & RES_DEBUG) 17865e96449SHajimu UMEMOTO printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n", 17965e96449SHajimu UMEMOTO p_rcode(hp->rcode), 18065e96449SHajimu UMEMOTO ntohs(hp->ancount), 18165e96449SHajimu UMEMOTO ntohs(hp->nscount), 18265e96449SHajimu UMEMOTO ntohs(hp->arcount)); 18365e96449SHajimu UMEMOTO #endif 18465e96449SHajimu UMEMOTO switch (hp->rcode) { 18565e96449SHajimu UMEMOTO case NXDOMAIN: 18665e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 18765e96449SHajimu UMEMOTO break; 18865e96449SHajimu UMEMOTO case SERVFAIL: 18965e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, TRY_AGAIN); 19065e96449SHajimu UMEMOTO break; 19165e96449SHajimu UMEMOTO case NOERROR: 19265e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, NO_DATA); 19365e96449SHajimu UMEMOTO break; 19465e96449SHajimu UMEMOTO case FORMERR: 19565e96449SHajimu UMEMOTO case NOTIMP: 19665e96449SHajimu UMEMOTO case REFUSED: 19765e96449SHajimu UMEMOTO default: 19865e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, NO_RECOVERY); 19965e96449SHajimu UMEMOTO break; 20065e96449SHajimu UMEMOTO } 20165e96449SHajimu UMEMOTO return (-1); 20265e96449SHajimu UMEMOTO } 20365e96449SHajimu UMEMOTO return (n); 20465e96449SHajimu UMEMOTO } 20565e96449SHajimu UMEMOTO 206dde4a85dSHajimu UMEMOTO /*% 20765e96449SHajimu UMEMOTO * Formulate a normal query, send, and retrieve answer in supplied buffer. 20865e96449SHajimu UMEMOTO * Return the size of the response on success, -1 on error. 20965e96449SHajimu UMEMOTO * If enabled, implement search rules until answer or unrecoverable failure 21065e96449SHajimu UMEMOTO * is detected. Error code, if any, is left in H_ERRNO. 21165e96449SHajimu UMEMOTO */ 21265e96449SHajimu UMEMOTO int 21365e96449SHajimu UMEMOTO res_nsearch(res_state statp, 214dde4a85dSHajimu UMEMOTO const char *name, /*%< domain name */ 215dde4a85dSHajimu UMEMOTO int class, int type, /*%< class and type of query */ 216dde4a85dSHajimu UMEMOTO u_char *answer, /*%< buffer to put answer */ 217dde4a85dSHajimu UMEMOTO int anslen) /*%< size of answer */ 21865e96449SHajimu UMEMOTO { 21965e96449SHajimu UMEMOTO const char *cp, * const *domain; 220aebc6ec2SHajimu UMEMOTO HEADER *hp = (HEADER *) answer; 22165e96449SHajimu UMEMOTO char tmp[NS_MAXDNAME]; 22265e96449SHajimu UMEMOTO u_int dots; 22365e96449SHajimu UMEMOTO int trailing_dot, ret, saved_herrno; 22465e96449SHajimu UMEMOTO int got_nodata = 0, got_servfail = 0, root_on_list = 0; 22565e96449SHajimu UMEMOTO int tried_as_is = 0; 22665e96449SHajimu UMEMOTO int searched = 0; 22765e96449SHajimu UMEMOTO 22865e96449SHajimu UMEMOTO errno = 0; 229dde4a85dSHajimu UMEMOTO RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /*%< True if we never query. */ 23065e96449SHajimu UMEMOTO dots = 0; 23165e96449SHajimu UMEMOTO for (cp = name; *cp != '\0'; cp++) 23265e96449SHajimu UMEMOTO dots += (*cp == '.'); 23365e96449SHajimu UMEMOTO trailing_dot = 0; 23465e96449SHajimu UMEMOTO if (cp > name && *--cp == '.') 23565e96449SHajimu UMEMOTO trailing_dot++; 23665e96449SHajimu UMEMOTO 23765e96449SHajimu UMEMOTO /* If there aren't any dots, it could be a user-level alias. */ 23865e96449SHajimu UMEMOTO if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) 23965e96449SHajimu UMEMOTO return (res_nquery(statp, cp, class, type, answer, anslen)); 24065e96449SHajimu UMEMOTO 24165e96449SHajimu UMEMOTO /* 24265e96449SHajimu UMEMOTO * If there are enough dots in the name, let's just give it a 24365e96449SHajimu UMEMOTO * try 'as is'. The threshold can be set with the "ndots" option. 24465e96449SHajimu UMEMOTO * Also, query 'as is', if there is a trailing dot in the name. 24565e96449SHajimu UMEMOTO */ 24665e96449SHajimu UMEMOTO saved_herrno = -1; 24765e96449SHajimu UMEMOTO if (dots >= statp->ndots || trailing_dot) { 24865e96449SHajimu UMEMOTO ret = res_nquerydomain(statp, name, NULL, class, type, 24965e96449SHajimu UMEMOTO answer, anslen); 25065e96449SHajimu UMEMOTO if (ret > 0 || trailing_dot) 25165e96449SHajimu UMEMOTO return (ret); 252ab96eeabSHajimu UMEMOTO if (errno == ECONNREFUSED) { 253ab96eeabSHajimu UMEMOTO RES_SET_H_ERRNO(statp, TRY_AGAIN); 254ab96eeabSHajimu UMEMOTO return (-1); 255ab96eeabSHajimu UMEMOTO } 256ab96eeabSHajimu UMEMOTO switch (statp->res_h_errno) { 257ab96eeabSHajimu UMEMOTO case NO_DATA: 258ab96eeabSHajimu UMEMOTO case HOST_NOT_FOUND: 259ab96eeabSHajimu UMEMOTO break; 260aebc6ec2SHajimu UMEMOTO case TRY_AGAIN: 261aebc6ec2SHajimu UMEMOTO if (hp->rcode == SERVFAIL) 262aebc6ec2SHajimu UMEMOTO break; 263aebc6ec2SHajimu UMEMOTO /* FALLTHROUGH */ 264ab96eeabSHajimu UMEMOTO default: 265ab96eeabSHajimu UMEMOTO return (-1); 266ab96eeabSHajimu UMEMOTO } 26765e96449SHajimu UMEMOTO saved_herrno = statp->res_h_errno; 26865e96449SHajimu UMEMOTO tried_as_is++; 26965e96449SHajimu UMEMOTO } 27065e96449SHajimu UMEMOTO 27165e96449SHajimu UMEMOTO /* 27265e96449SHajimu UMEMOTO * We do at least one level of search if 27365e96449SHajimu UMEMOTO * - there is no dot and RES_DEFNAME is set, or 27465e96449SHajimu UMEMOTO * - there is at least one dot, there is no trailing dot, 27565e96449SHajimu UMEMOTO * and RES_DNSRCH is set. 27665e96449SHajimu UMEMOTO */ 27765e96449SHajimu UMEMOTO if ((!dots && (statp->options & RES_DEFNAMES) != 0U) || 27865e96449SHajimu UMEMOTO (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) { 27965e96449SHajimu UMEMOTO int done = 0; 28065e96449SHajimu UMEMOTO 28165e96449SHajimu UMEMOTO for (domain = (const char * const *)statp->dnsrch; 28265e96449SHajimu UMEMOTO *domain && !done; 28365e96449SHajimu UMEMOTO domain++) { 28465e96449SHajimu UMEMOTO searched = 1; 28565e96449SHajimu UMEMOTO 28665e96449SHajimu UMEMOTO if (domain[0][0] == '\0' || 28765e96449SHajimu UMEMOTO (domain[0][0] == '.' && domain[0][1] == '\0')) 28865e96449SHajimu UMEMOTO root_on_list++; 28965e96449SHajimu UMEMOTO 290ab96eeabSHajimu UMEMOTO if (root_on_list && tried_as_is) 291ab96eeabSHajimu UMEMOTO continue; 292ab96eeabSHajimu UMEMOTO 29365e96449SHajimu UMEMOTO ret = res_nquerydomain(statp, name, *domain, 29465e96449SHajimu UMEMOTO class, type, 29565e96449SHajimu UMEMOTO answer, anslen); 29665e96449SHajimu UMEMOTO if (ret > 0) 29765e96449SHajimu UMEMOTO return (ret); 29865e96449SHajimu UMEMOTO 29965e96449SHajimu UMEMOTO /* 30065e96449SHajimu UMEMOTO * If no server present, give up. 30165e96449SHajimu UMEMOTO * If name isn't found in this domain, 30265e96449SHajimu UMEMOTO * keep trying higher domains in the search list 30365e96449SHajimu UMEMOTO * (if that's enabled). 30465e96449SHajimu UMEMOTO * On a NO_DATA error, keep trying, otherwise 30565e96449SHajimu UMEMOTO * a wildcard entry of another type could keep us 30665e96449SHajimu UMEMOTO * from finding this entry higher in the domain. 30765e96449SHajimu UMEMOTO * If we get some other error (negative answer or 30865e96449SHajimu UMEMOTO * server failure), then stop searching up, 30965e96449SHajimu UMEMOTO * but try the input name below in case it's 31065e96449SHajimu UMEMOTO * fully-qualified. 31165e96449SHajimu UMEMOTO */ 31265e96449SHajimu UMEMOTO if (errno == ECONNREFUSED) { 31365e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, TRY_AGAIN); 31465e96449SHajimu UMEMOTO return (-1); 31565e96449SHajimu UMEMOTO } 31665e96449SHajimu UMEMOTO 31765e96449SHajimu UMEMOTO switch (statp->res_h_errno) { 31865e96449SHajimu UMEMOTO case NO_DATA: 31965e96449SHajimu UMEMOTO got_nodata++; 32065e96449SHajimu UMEMOTO /* FALLTHROUGH */ 32165e96449SHajimu UMEMOTO case HOST_NOT_FOUND: 32265e96449SHajimu UMEMOTO /* keep trying */ 32365e96449SHajimu UMEMOTO break; 32465e96449SHajimu UMEMOTO case TRY_AGAIN: 325ab96eeabSHajimu UMEMOTO /* 326ab96eeabSHajimu UMEMOTO * This can occur due to a server failure 327ab96eeabSHajimu UMEMOTO * (that is, all listed servers have failed), 328ab96eeabSHajimu UMEMOTO * or all listed servers have timed out. 329ab96eeabSHajimu UMEMOTO * ((HEADER *)answer)->rcode may not be set 330ab96eeabSHajimu UMEMOTO * to SERVFAIL in the case of a timeout. 331ab96eeabSHajimu UMEMOTO * 332aebc6ec2SHajimu UMEMOTO * Either way we must return TRY_AGAIN in 333aebc6ec2SHajimu UMEMOTO * order to avoid non-deterministic 334aebc6ec2SHajimu UMEMOTO * return codes. 335aebc6ec2SHajimu UMEMOTO * For example, loaded name servers or races 336ab96eeabSHajimu UMEMOTO * against network startup/validation (dhcp, 337ab96eeabSHajimu UMEMOTO * ppp, etc) can cause the search to timeout 338ab96eeabSHajimu UMEMOTO * on one search element, e.g. 'fu.bar.com', 339ab96eeabSHajimu UMEMOTO * and return a definitive failure on the 340ab96eeabSHajimu UMEMOTO * next search element, e.g. 'fu.'. 341ab96eeabSHajimu UMEMOTO */ 34265e96449SHajimu UMEMOTO got_servfail++; 343aebc6ec2SHajimu UMEMOTO if (hp->rcode == SERVFAIL) { 344aebc6ec2SHajimu UMEMOTO /* try next search element, if any */ 345aebc6ec2SHajimu UMEMOTO break; 346aebc6ec2SHajimu UMEMOTO } 34765e96449SHajimu UMEMOTO /* FALLTHROUGH */ 34865e96449SHajimu UMEMOTO default: 34965e96449SHajimu UMEMOTO /* anything else implies that we're done */ 35065e96449SHajimu UMEMOTO done++; 35165e96449SHajimu UMEMOTO } 35265e96449SHajimu UMEMOTO 35365e96449SHajimu UMEMOTO /* if we got here for some reason other than DNSRCH, 35465e96449SHajimu UMEMOTO * we only wanted one iteration of the loop, so stop. 35565e96449SHajimu UMEMOTO */ 35665e96449SHajimu UMEMOTO if ((statp->options & RES_DNSRCH) == 0U) 35765e96449SHajimu UMEMOTO done++; 35865e96449SHajimu UMEMOTO } 35965e96449SHajimu UMEMOTO } 36065e96449SHajimu UMEMOTO 361ab96eeabSHajimu UMEMOTO switch (statp->res_h_errno) { 362ab96eeabSHajimu UMEMOTO case NO_DATA: 363ab96eeabSHajimu UMEMOTO case HOST_NOT_FOUND: 364ab96eeabSHajimu UMEMOTO break; 365aebc6ec2SHajimu UMEMOTO case TRY_AGAIN: 366aebc6ec2SHajimu UMEMOTO if (hp->rcode == SERVFAIL) 367aebc6ec2SHajimu UMEMOTO break; 368aebc6ec2SHajimu UMEMOTO /* FALLTHROUGH */ 369ab96eeabSHajimu UMEMOTO default: 370ab96eeabSHajimu UMEMOTO goto giveup; 371ab96eeabSHajimu UMEMOTO } 372ab96eeabSHajimu UMEMOTO 37365e96449SHajimu UMEMOTO /* 37465e96449SHajimu UMEMOTO * If the query has not already been tried as is then try it 37565e96449SHajimu UMEMOTO * unless RES_NOTLDQUERY is set and there were no dots. 37665e96449SHajimu UMEMOTO */ 37765e96449SHajimu UMEMOTO if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) && 37865e96449SHajimu UMEMOTO !(tried_as_is || root_on_list)) { 37965e96449SHajimu UMEMOTO ret = res_nquerydomain(statp, name, NULL, class, type, 38065e96449SHajimu UMEMOTO answer, anslen); 38165e96449SHajimu UMEMOTO if (ret > 0) 38265e96449SHajimu UMEMOTO return (ret); 38365e96449SHajimu UMEMOTO } 38465e96449SHajimu UMEMOTO 38565e96449SHajimu UMEMOTO /* if we got here, we didn't satisfy the search. 38665e96449SHajimu UMEMOTO * if we did an initial full query, return that query's H_ERRNO 38765e96449SHajimu UMEMOTO * (note that we wouldn't be here if that query had succeeded). 38865e96449SHajimu UMEMOTO * else if we ever got a nodata, send that back as the reason. 38965e96449SHajimu UMEMOTO * else send back meaningless H_ERRNO, that being the one from 39065e96449SHajimu UMEMOTO * the last DNSRCH we did. 39165e96449SHajimu UMEMOTO */ 392ab96eeabSHajimu UMEMOTO giveup: 39365e96449SHajimu UMEMOTO if (saved_herrno != -1) 39465e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, saved_herrno); 39565e96449SHajimu UMEMOTO else if (got_nodata) 39665e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, NO_DATA); 39765e96449SHajimu UMEMOTO else if (got_servfail) 39865e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, TRY_AGAIN); 39965e96449SHajimu UMEMOTO return (-1); 40065e96449SHajimu UMEMOTO } 40165e96449SHajimu UMEMOTO 402dde4a85dSHajimu UMEMOTO /*% 40365e96449SHajimu UMEMOTO * Perform a call on res_query on the concatenation of name and domain, 40465e96449SHajimu UMEMOTO * removing a trailing dot from name if domain is NULL. 40565e96449SHajimu UMEMOTO */ 40665e96449SHajimu UMEMOTO int 40765e96449SHajimu UMEMOTO res_nquerydomain(res_state statp, 40865e96449SHajimu UMEMOTO const char *name, 40965e96449SHajimu UMEMOTO const char *domain, 410dde4a85dSHajimu UMEMOTO int class, int type, /*%< class and type of query */ 411dde4a85dSHajimu UMEMOTO u_char *answer, /*%< buffer to put answer */ 412dde4a85dSHajimu UMEMOTO int anslen) /*%< size of answer */ 41365e96449SHajimu UMEMOTO { 41465e96449SHajimu UMEMOTO char nbuf[MAXDNAME]; 41565e96449SHajimu UMEMOTO const char *longname = nbuf; 41665e96449SHajimu UMEMOTO int n, d; 41765e96449SHajimu UMEMOTO 41865e96449SHajimu UMEMOTO #ifdef DEBUG 41965e96449SHajimu UMEMOTO if (statp->options & RES_DEBUG) 42065e96449SHajimu UMEMOTO printf(";; res_nquerydomain(%s, %s, %d, %d)\n", 42165e96449SHajimu UMEMOTO name, domain?domain:"<Nil>", class, type); 42265e96449SHajimu UMEMOTO #endif 42365e96449SHajimu UMEMOTO if (domain == NULL) { 42465e96449SHajimu UMEMOTO /* 42565e96449SHajimu UMEMOTO * Check for trailing '.'; 42665e96449SHajimu UMEMOTO * copy without '.' if present. 42765e96449SHajimu UMEMOTO */ 42865e96449SHajimu UMEMOTO n = strlen(name); 42965e96449SHajimu UMEMOTO if (n >= MAXDNAME) { 43065e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, NO_RECOVERY); 43165e96449SHajimu UMEMOTO return (-1); 43265e96449SHajimu UMEMOTO } 43365e96449SHajimu UMEMOTO n--; 43465e96449SHajimu UMEMOTO if (n >= 0 && name[n] == '.') { 43565e96449SHajimu UMEMOTO strncpy(nbuf, name, n); 43665e96449SHajimu UMEMOTO nbuf[n] = '\0'; 43765e96449SHajimu UMEMOTO } else 43865e96449SHajimu UMEMOTO longname = name; 43965e96449SHajimu UMEMOTO } else { 44065e96449SHajimu UMEMOTO n = strlen(name); 44165e96449SHajimu UMEMOTO d = strlen(domain); 44265e96449SHajimu UMEMOTO if (n + d + 1 >= MAXDNAME) { 44365e96449SHajimu UMEMOTO RES_SET_H_ERRNO(statp, NO_RECOVERY); 44465e96449SHajimu UMEMOTO return (-1); 44565e96449SHajimu UMEMOTO } 44665e96449SHajimu UMEMOTO sprintf(nbuf, "%s.%s", name, domain); 44765e96449SHajimu UMEMOTO } 44865e96449SHajimu UMEMOTO return (res_nquery(statp, longname, class, type, answer, anslen)); 44965e96449SHajimu UMEMOTO } 45065e96449SHajimu UMEMOTO 45165e96449SHajimu UMEMOTO const char * 45265e96449SHajimu UMEMOTO res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { 45365e96449SHajimu UMEMOTO char *file, *cp1, *cp2; 45465e96449SHajimu UMEMOTO char buf[BUFSIZ]; 45565e96449SHajimu UMEMOTO FILE *fp; 45665e96449SHajimu UMEMOTO 45765e96449SHajimu UMEMOTO if (statp->options & RES_NOALIASES) 45865e96449SHajimu UMEMOTO return (NULL); 459ab96eeabSHajimu UMEMOTO if (issetugid()) 460ab96eeabSHajimu UMEMOTO return (NULL); 46165e96449SHajimu UMEMOTO file = getenv("HOSTALIASES"); 462a93705b0SJilles Tjoelker if (file == NULL || (fp = fopen(file, "re")) == NULL) 46365e96449SHajimu UMEMOTO return (NULL); 46465e96449SHajimu UMEMOTO setbuf(fp, NULL); 46565e96449SHajimu UMEMOTO buf[sizeof(buf) - 1] = '\0'; 46665e96449SHajimu UMEMOTO while (fgets(buf, sizeof(buf), fp)) { 46765e96449SHajimu UMEMOTO for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1) 46865e96449SHajimu UMEMOTO ; 46965e96449SHajimu UMEMOTO if (!*cp1) 47065e96449SHajimu UMEMOTO break; 47165e96449SHajimu UMEMOTO *cp1 = '\0'; 47265e96449SHajimu UMEMOTO if (ns_samename(buf, name) == 1) { 47365e96449SHajimu UMEMOTO while (isspace((unsigned char)*++cp1)) 47465e96449SHajimu UMEMOTO ; 47565e96449SHajimu UMEMOTO if (!*cp1) 47665e96449SHajimu UMEMOTO break; 47765e96449SHajimu UMEMOTO for (cp2 = cp1 + 1; *cp2 && 47865e96449SHajimu UMEMOTO !isspace((unsigned char)*cp2); ++cp2) 47965e96449SHajimu UMEMOTO ; 48065e96449SHajimu UMEMOTO *cp2 = '\0'; 48165e96449SHajimu UMEMOTO strncpy(dst, cp1, siz - 1); 48265e96449SHajimu UMEMOTO dst[siz - 1] = '\0'; 48365e96449SHajimu UMEMOTO fclose(fp); 48465e96449SHajimu UMEMOTO return (dst); 48565e96449SHajimu UMEMOTO } 48665e96449SHajimu UMEMOTO } 48765e96449SHajimu UMEMOTO fclose(fp); 48865e96449SHajimu UMEMOTO return (NULL); 48965e96449SHajimu UMEMOTO } 490dde4a85dSHajimu UMEMOTO 491dde4a85dSHajimu UMEMOTO /*! \file */ 492