133965Sjdp/* 233965Sjdp * Copyright (c) 1988, 1993 338889Sjdp * The Regents of the University of California. All rights reserved. 460484Sobrien * 533965Sjdp * Redistribution and use in source and binary forms, with or without 633965Sjdp * modification, are permitted provided that the following conditions 738889Sjdp * are met: 838889Sjdp * 1. Redistributions of source code must retain the above copyright 938889Sjdp * notice, this list of conditions and the following disclaimer. 1092828Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1189857Sobrien * notice, this list of conditions and the following disclaimer in the 1292828Sobrien * documentation and/or other materials provided with the distribution. 1338889Sjdp * 4. Neither the name of the University nor the names of its contributors 1489857Sobrien * may be used to endorse or promote products derived from this software 1589857Sobrien * without specific prior written permission. 1689857Sobrien * 1789857Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1889857Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1989857Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2089857Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2189857Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2289857Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2389857Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2489857Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2589857Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2689857Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2789857Sobrien * SUCH DAMAGE. 2889857Sobrien */ 2989857Sobrien 3089857Sobrien/* 3189857Sobrien * Portions Copyright (c) 1993 by Digital Equipment Corporation. 3238889Sjdp * 3338889Sjdp * Permission to use, copy, modify, and distribute this software for any 3438889Sjdp * purpose with or without fee is hereby granted, provided that the above 3538889Sjdp * copyright notice and this permission notice appear in all copies, and that 3638889Sjdp * the name of Digital Equipment Corporation not be used in advertising or 3738889Sjdp * publicity pertaining to distribution of the document or software without 3838889Sjdp * specific, written prior permission. 3938889Sjdp * 4038889Sjdp * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 4138889Sjdp * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 4238889Sjdp * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 4333965Sjdp * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 4433965Sjdp * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 4533965Sjdp * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 4633965Sjdp * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4733965Sjdp * SOFTWARE. 4833965Sjdp */ 4933965Sjdp 5033965Sjdp/* 5133965Sjdp * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5233965Sjdp * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 5333965Sjdp * 5433965Sjdp * Permission to use, copy, modify, and distribute this software for any 5533965Sjdp * purpose with or without fee is hereby granted, provided that the above 5633965Sjdp * copyright notice and this permission notice appear in all copies. 5733965Sjdp * 5833965Sjdp * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 5933965Sjdp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 6033965Sjdp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 6133965Sjdp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 6233965Sjdp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 6333965Sjdp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 6433965Sjdp * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6533965Sjdp */ 6633965Sjdp 6733965Sjdp#if defined(LIBC_SCCS) && !defined(lint) 6833965Sjdpstatic const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; 6933965Sjdpstatic const char rcsid[] = "$Id: res_query.c,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $"; 7033965Sjdp#endif /* LIBC_SCCS and not lint */ 7133965Sjdp#include <sys/cdefs.h> 7233965Sjdp__FBSDID("$FreeBSD$"); 7389857Sobrien 7477298Sobrien#include "port_before.h" 7577298Sobrien#include <sys/types.h> 7677298Sobrien#include <sys/param.h> 7777298Sobrien#include <netinet/in.h> 7877298Sobrien#include <arpa/inet.h> 7977298Sobrien#include <arpa/nameser.h> 8077298Sobrien#include <ctype.h> 8177298Sobrien#include <errno.h> 8277298Sobrien#include <netdb.h> 8377298Sobrien#include <resolv.h> 8477298Sobrien#include <stdio.h> 8577298Sobrien#include <stdlib.h> 8677298Sobrien#include <string.h> 8777298Sobrien#include <unistd.h> 8877298Sobrien#include "port_after.h" 8977298Sobrien 9077298Sobrien/* Options. Leave them on. */ 9177298Sobrien#define DEBUG 9277298Sobrien 9377298Sobrien#if PACKETSZ > 1024 9438889Sjdp#define MAXPACKET PACKETSZ 9533965Sjdp#else 9633965Sjdp#define MAXPACKET 1024 9733965Sjdp#endif 9833965Sjdp 9933965Sjdp/*% 10038889Sjdp * Formulate a normal query, send, and await answer. 10160484Sobrien * Returned answer is placed in supplied buffer "answer". 10238889Sjdp * Perform preliminary check of answer, returning success only 10333965Sjdp * if no error is indicated and the answer count is nonzero. 10433965Sjdp * Return the size of the response on success, -1 on error. 10589857Sobrien * Error number is left in H_ERRNO. 10633965Sjdp * 10733965Sjdp * Caller must parse answer and determine whether it answers the question. 10833965Sjdp */ 10933965Sjdpint 11033965Sjdpres_nquery(res_state statp, 11189857Sobrien const char *name, /*%< domain name */ 11260484Sobrien int class, int type, /*%< class and type of query */ 11360484Sobrien u_char *answer, /*%< buffer to put answer */ 11433965Sjdp int anslen) /*%< size of answer buffer */ 11533965Sjdp{ 11633965Sjdp u_char buf[MAXPACKET]; 11733965Sjdp HEADER *hp = (HEADER *) answer; 11860484Sobrien u_int oflags; 11933965Sjdp u_char *rdata; 12033965Sjdp int n; 12133965Sjdp 12233965Sjdp oflags = statp->_flags; 12333965Sjdp 12433965Sjdpagain: 12533965Sjdp hp->rcode = NOERROR; /*%< default */ 12633965Sjdp#ifdef DEBUG 12733965Sjdp if (statp->options & RES_DEBUG) 12833965Sjdp printf(";; res_query(%s, %d, %d)\n", name, class, type); 12933965Sjdp#endif 13033965Sjdp 13133965Sjdp n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, 13233965Sjdp buf, sizeof(buf)); 13333965Sjdp#ifdef RES_USE_EDNS0 13433965Sjdp if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && 13533965Sjdp (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) { 13633965Sjdp n = res_nopt(statp, n, buf, sizeof(buf), anslen); 13733965Sjdp rdata = &buf[n]; 13833965Sjdp if (n > 0 && (statp->options & RES_NSID) != 0U) { 13933965Sjdp n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata, 14033965Sjdp NS_OPT_NSID, 0, NULL); 14160484Sobrien } 14260484Sobrien } 14333965Sjdp#endif 14433965Sjdp if (n <= 0) { 14533965Sjdp#ifdef DEBUG 14633965Sjdp if (statp->options & RES_DEBUG) 14733965Sjdp printf(";; res_query: mkquery failed\n"); 14833965Sjdp#endif 14933965Sjdp RES_SET_H_ERRNO(statp, NO_RECOVERY); 15033965Sjdp return (n); 15133965Sjdp } 15233965Sjdp 15333965Sjdp n = res_nsend(statp, buf, n, answer, anslen); 15433965Sjdp if (n < 0) { 15560484Sobrien#ifdef RES_USE_EDNS0 15633965Sjdp /* if the query choked with EDNS0, retry without EDNS0 */ 15733965Sjdp if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U && 15877298Sobrien ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { 15977298Sobrien statp->_flags |= RES_F_EDNS0ERR; 16077298Sobrien if (statp->options & RES_DEBUG) 16138889Sjdp printf(";; res_nquery: retry without EDNS0\n"); 16238889Sjdp goto again; 16360484Sobrien } 16433965Sjdp#endif 16538889Sjdp#ifdef DEBUG 16638889Sjdp if (statp->options & RES_DEBUG) 16777298Sobrien printf(";; res_query: send error\n"); 16889857Sobrien#endif 16938889Sjdp RES_SET_H_ERRNO(statp, TRY_AGAIN); 17038889Sjdp return (n); 17138889Sjdp } 17260484Sobrien 17338889Sjdp if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 17433965Sjdp#ifdef DEBUG 17589857Sobrien if (statp->options & RES_DEBUG) 17660484Sobrien printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n", 17760484Sobrien p_rcode(hp->rcode), 17860484Sobrien ntohs(hp->ancount), 17960484Sobrien ntohs(hp->nscount), 18033965Sjdp ntohs(hp->arcount)); 18133965Sjdp#endif 18233965Sjdp switch (hp->rcode) { 18360484Sobrien case NXDOMAIN: 18460484Sobrien RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 18533965Sjdp break; 18633965Sjdp case SERVFAIL: 18733965Sjdp RES_SET_H_ERRNO(statp, TRY_AGAIN); 18833965Sjdp break; 18933965Sjdp case NOERROR: 19038889Sjdp RES_SET_H_ERRNO(statp, NO_DATA); 19160484Sobrien break; 19233965Sjdp case FORMERR: 19333965Sjdp case NOTIMP: 19489857Sobrien case REFUSED: 19589857Sobrien default: 19689857Sobrien RES_SET_H_ERRNO(statp, NO_RECOVERY); 19789857Sobrien break; 19889857Sobrien } 19991041Sobrien return (-1); 20033965Sjdp } 20138889Sjdp return (n); 20260484Sobrien} 20333965Sjdp 20433965Sjdp/*% 20577298Sobrien * Formulate a normal query, send, and retrieve answer in supplied buffer. 20677298Sobrien * Return the size of the response on success, -1 on error. 20777298Sobrien * If enabled, implement search rules until answer or unrecoverable failure 20877298Sobrien * is detected. Error code, if any, is left in H_ERRNO. 20977298Sobrien */ 21077298Sobrienint 21133965Sjdpres_nsearch(res_state statp, 21233965Sjdp const char *name, /*%< domain name */ 21338889Sjdp int class, int type, /*%< class and type of query */ 21433965Sjdp u_char *answer, /*%< buffer to put answer */ 21533965Sjdp int anslen) /*%< size of answer */ 21633965Sjdp{ 21733965Sjdp const char *cp, * const *domain; 21838889Sjdp HEADER *hp = (HEADER *) answer; 21960484Sobrien char tmp[NS_MAXDNAME]; 22033965Sjdp u_int dots; 22133965Sjdp int trailing_dot, ret, saved_herrno; 22260484Sobrien int got_nodata = 0, got_servfail = 0, root_on_list = 0; 22360484Sobrien int tried_as_is = 0; 22460484Sobrien int searched = 0; 22560484Sobrien 22660484Sobrien errno = 0; 22733965Sjdp RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /*%< True if we never query. */ 22833965Sjdp dots = 0; 22938889Sjdp for (cp = name; *cp != '\0'; cp++) 23060484Sobrien dots += (*cp == '.'); 23133965Sjdp trailing_dot = 0; 23233965Sjdp if (cp > name && *--cp == '.') 23333965Sjdp trailing_dot++; 23433965Sjdp 23538889Sjdp /* If there aren't any dots, it could be a user-level alias. */ 23660484Sobrien if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) 23733965Sjdp return (res_nquery(statp, cp, class, type, answer, anslen)); 23833965Sjdp 23938889Sjdp /* 24033965Sjdp * If there are enough dots in the name, let's just give it a 24138889Sjdp * try 'as is'. The threshold can be set with the "ndots" option. 24260484Sobrien * Also, query 'as is', if there is a trailing dot in the name. 24333965Sjdp */ 24433965Sjdp saved_herrno = -1; 24538889Sjdp if (dots >= statp->ndots || trailing_dot) { 24638889Sjdp ret = res_nquerydomain(statp, name, NULL, class, type, 24733965Sjdp answer, anslen); 24833965Sjdp if (ret > 0 || trailing_dot) 24938889Sjdp return (ret); 25060484Sobrien if (errno == ECONNREFUSED) { 25133965Sjdp RES_SET_H_ERRNO(statp, TRY_AGAIN); 25233965Sjdp return (-1); 25338889Sjdp } 25460484Sobrien switch (statp->res_h_errno) { 25533965Sjdp case NO_DATA: 25633965Sjdp case HOST_NOT_FOUND: 25738889Sjdp break; 25860484Sobrien case TRY_AGAIN: 25933965Sjdp if (hp->rcode == SERVFAIL) 26033965Sjdp break; 26138889Sjdp /* FALLTHROUGH */ 26233965Sjdp default: 26333965Sjdp return (-1); 26438889Sjdp } 26560484Sobrien saved_herrno = statp->res_h_errno; 26633965Sjdp tried_as_is++; 26738889Sjdp } 26838889Sjdp 26938889Sjdp /* 27033965Sjdp * We do at least one level of search if 27138889Sjdp * - there is no dot and RES_DEFNAME is set, or 27260484Sobrien * - there is at least one dot, there is no trailing dot, 27333965Sjdp * and RES_DNSRCH is set. 27433965Sjdp */ 27533965Sjdp if ((!dots && (statp->options & RES_DEFNAMES) != 0U) || 27638889Sjdp (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) { 27760484Sobrien int done = 0; 27833965Sjdp 27933965Sjdp for (domain = (const char * const *)statp->dnsrch; 28038889Sjdp *domain && !done; 28160484Sobrien domain++) { 28233965Sjdp searched = 1; 28333965Sjdp 28438889Sjdp if (domain[0][0] == '\0' || 28560484Sobrien (domain[0][0] == '.' && domain[0][1] == '\0')) 28633965Sjdp root_on_list++; 28738889Sjdp 28833965Sjdp if (root_on_list && tried_as_is) 28938889Sjdp continue; 29060484Sobrien 29133965Sjdp ret = res_nquerydomain(statp, name, *domain, 29238889Sjdp class, type, 29338889Sjdp answer, anslen); 29460484Sobrien if (ret > 0) 29533965Sjdp return (ret); 29633965Sjdp 29738889Sjdp /* 29860484Sobrien * If no server present, give up. 29933965Sjdp * If name isn't found in this domain, 30033965Sjdp * keep trying higher domains in the search list 30138889Sjdp * (if that's enabled). 30260484Sobrien * On a NO_DATA error, keep trying, otherwise 30333965Sjdp * a wildcard entry of another type could keep us 30433965Sjdp * from finding this entry higher in the domain. 30538889Sjdp * If we get some other error (negative answer or 30633965Sjdp * server failure), then stop searching up, 30733965Sjdp * but try the input name below in case it's 30838889Sjdp * fully-qualified. 30960484Sobrien */ 31033965Sjdp if (errno == ECONNREFUSED) { 31133965Sjdp RES_SET_H_ERRNO(statp, TRY_AGAIN); 31238889Sjdp return (-1); 31333965Sjdp } 31438889Sjdp 31560484Sobrien switch (statp->res_h_errno) { 31633965Sjdp case NO_DATA: 31733965Sjdp got_nodata++; 31838889Sjdp /* FALLTHROUGH */ 31960484Sobrien case HOST_NOT_FOUND: 32033965Sjdp /* keep trying */ 32133965Sjdp break; 32238889Sjdp case TRY_AGAIN: 32333965Sjdp /* 32438889Sjdp * This can occur due to a server failure 32577298Sobrien * (that is, all listed servers have failed), 32677298Sobrien * or all listed servers have timed out. 32777298Sobrien * ((HEADER *)answer)->rcode may not be set 32877298Sobrien * to SERVFAIL in the case of a timeout. 32977298Sobrien * 33077298Sobrien * Either way we must return TRY_AGAIN in 33138889Sjdp * order to avoid non-deterministic 33238889Sjdp * return codes. 33338889Sjdp * For example, loaded name servers or races 33438889Sjdp * against network startup/validation (dhcp, 33533965Sjdp * ppp, etc) can cause the search to timeout 33677298Sobrien * on one search element, e.g. 'fu.bar.com', 33738889Sjdp * and return a definitive failure on the 33878828Sobrien * next search element, e.g. 'fu.'. 33989857Sobrien */ 34089857Sobrien got_servfail++; 34133965Sjdp if (hp->rcode == SERVFAIL) { 34238889Sjdp /* try next search element, if any */ 34333965Sjdp break; 34433965Sjdp } 34538889Sjdp /* FALLTHROUGH */ 34660484Sobrien default: 34733965Sjdp /* anything else implies that we're done */ 34833965Sjdp done++; 34938889Sjdp } 35060484Sobrien 35133965Sjdp /* if we got here for some reason other than DNSRCH, 35233965Sjdp * we only wanted one iteration of the loop, so stop. 35338889Sjdp */ 35460484Sobrien if ((statp->options & RES_DNSRCH) == 0U) 35533965Sjdp done++; 35633965Sjdp } 35738889Sjdp } 35860484Sobrien 35933965Sjdp switch (statp->res_h_errno) { 36089857Sobrien case NO_DATA: 36133965Sjdp case HOST_NOT_FOUND: 36233965Sjdp break; 36333965Sjdp case TRY_AGAIN: 36438889Sjdp if (hp->rcode == SERVFAIL) 36538889Sjdp break; 36638889Sjdp /* FALLTHROUGH */ 36738889Sjdp default: 36838889Sjdp goto giveup; 36938889Sjdp } 37038889Sjdp 37138889Sjdp /* 37238889Sjdp * If the query has not already been tried as is then try it 37360484Sobrien * unless RES_NOTLDQUERY is set and there were no dots. 37438889Sjdp */ 37533965Sjdp if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) && 37633965Sjdp !(tried_as_is || root_on_list)) { 37760484Sobrien ret = res_nquerydomain(statp, name, NULL, class, type, 37860484Sobrien answer, anslen); 37960484Sobrien if (ret > 0) 38060484Sobrien return (ret); 38160484Sobrien } 38277298Sobrien 38360484Sobrien /* if we got here, we didn't satisfy the search. 38477298Sobrien * if we did an initial full query, return that query's H_ERRNO 38560484Sobrien * (note that we wouldn't be here if that query had succeeded). 38677298Sobrien * else if we ever got a nodata, send that back as the reason. 38777298Sobrien * else send back meaningless H_ERRNO, that being the one from 38860484Sobrien * the last DNSRCH we did. 38977298Sobrien */ 39060484Sobriengiveup: 39177298Sobrien if (saved_herrno != -1) 39260484Sobrien RES_SET_H_ERRNO(statp, saved_herrno); 39377298Sobrien else if (got_nodata) 39460484Sobrien RES_SET_H_ERRNO(statp, NO_DATA); 39560484Sobrien else if (got_servfail) 39660484Sobrien RES_SET_H_ERRNO(statp, TRY_AGAIN); 39733965Sjdp return (-1); 39833965Sjdp} 39933965Sjdp 40033965Sjdp/*% 40177298Sobrien * Perform a call on res_query on the concatenation of name and domain, 40277298Sobrien * removing a trailing dot from name if domain is NULL. 40377298Sobrien */ 40477298Sobrienint 40533965Sjdpres_nquerydomain(res_state statp, 40660484Sobrien const char *name, 40760484Sobrien const char *domain, 40860484Sobrien int class, int type, /*%< class and type of query */ 40960484Sobrien u_char *answer, /*%< buffer to put answer */ 41060484Sobrien int anslen) /*%< size of answer */ 41160484Sobrien{ 41260484Sobrien char nbuf[MAXDNAME]; 41360484Sobrien const char *longname = nbuf; 41460484Sobrien int n, d; 41560484Sobrien 41689857Sobrien#ifdef DEBUG 41789857Sobrien if (statp->options & RES_DEBUG) 41889857Sobrien printf(";; res_nquerydomain(%s, %s, %d, %d)\n", 41989857Sobrien name, domain?domain:"<Nil>", class, type); 42089857Sobrien#endif 42189857Sobrien if (domain == NULL) { 42289857Sobrien /* 42389857Sobrien * Check for trailing '.'; 42489857Sobrien * copy without '.' if present. 42589857Sobrien */ 42689857Sobrien n = strlen(name); 42792828Sobrien if (n >= MAXDNAME) { 42892828Sobrien RES_SET_H_ERRNO(statp, NO_RECOVERY); 42992828Sobrien return (-1); 43092828Sobrien } 43189857Sobrien n--; 43289857Sobrien if (n >= 0 && name[n] == '.') { 43389857Sobrien strncpy(nbuf, name, n); 43489857Sobrien nbuf[n] = '\0'; 43589857Sobrien } else 43660484Sobrien longname = name; 43760484Sobrien } else { 43860484Sobrien n = strlen(name); 43960484Sobrien d = strlen(domain); 44033965Sjdp if (n + d + 1 >= MAXDNAME) { 44133965Sjdp RES_SET_H_ERRNO(statp, NO_RECOVERY); 44233965Sjdp return (-1); 44333965Sjdp } 44433965Sjdp sprintf(nbuf, "%s.%s", name, domain); 44533965Sjdp } 44660484Sobrien return (res_nquery(statp, longname, class, type, answer, anslen)); 44733965Sjdp} 44833965Sjdp 44933965Sjdpconst char * 45033965Sjdpres_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { 45133965Sjdp char *file, *cp1, *cp2; 45233965Sjdp char buf[BUFSIZ]; 45333965Sjdp FILE *fp; 45433965Sjdp 45533965Sjdp if (statp->options & RES_NOALIASES) 45633965Sjdp return (NULL); 45733965Sjdp if (issetugid()) 45833965Sjdp return (NULL); 45933965Sjdp file = getenv("HOSTALIASES"); 46033965Sjdp if (file == NULL || (fp = fopen(file, "r")) == NULL) 46133965Sjdp return (NULL); 46233965Sjdp setbuf(fp, NULL); 46333965Sjdp buf[sizeof(buf) - 1] = '\0'; 46433965Sjdp while (fgets(buf, sizeof(buf), fp)) { 46533965Sjdp for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1) 46633965Sjdp ; 46733965Sjdp if (!*cp1) 46833965Sjdp break; 46933965Sjdp *cp1 = '\0'; 47033965Sjdp if (ns_samename(buf, name) == 1) { 47133965Sjdp while (isspace((unsigned char)*++cp1)) 47233965Sjdp ; 47333965Sjdp if (!*cp1) 47433965Sjdp break; 47533965Sjdp for (cp2 = cp1 + 1; *cp2 && 47633965Sjdp !isspace((unsigned char)*cp2); ++cp2) 47733965Sjdp ; 47833965Sjdp *cp2 = '\0'; 47933965Sjdp strncpy(dst, cp1, siz - 1); 48033965Sjdp dst[siz - 1] = '\0'; 48160484Sobrien fclose(fp); 48233965Sjdp return (dst); 48333965Sjdp } 48433965Sjdp } 48533965Sjdp fclose(fp); 48633965Sjdp return (NULL); 48733965Sjdp} 48833965Sjdp 48933965Sjdp/*! \file */ 49033965Sjdp