xref: /netbsd-src/lib/libc/resolv/res_send.c (revision 4d416d886b829bba9ade816478dc45578e88d40a)
1*4d416d88Schristos /*	$NetBSD: res_send.c,v 1.30 2015/02/24 17:56:20 christos Exp $	*/
259a755a4Schristos 
359a755a4Schristos /*
459a755a4Schristos  * Portions Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
559a755a4Schristos  * Portions Copyright (C) 1996-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) 1985, 1989, 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*4d416d88Schristos  * 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 /*
70d73eb73dSchristos  * Copyright (c) 2005 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_send.c	8.1 (Berkeley) 6/4/93";
9059a755a4Schristos static const char rcsid[] = "Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp";
91ca31adbdSchristos #else
92*4d416d88Schristos __RCSID("$NetBSD: res_send.c,v 1.30 2015/02/24 17:56:20 christos Exp $");
93ca31adbdSchristos #endif
942b237084Schristos #endif /* LIBC_SCCS and not lint */
952b237084Schristos 
96d73eb73dSchristos /*! \file
97d73eb73dSchristos  * \brief
982b237084Schristos  * Send query to name server and wait for reply.
992b237084Schristos  */
1002b237084Schristos 
101fd5cb0acSkleink #include "namespace.h"
1022b237084Schristos #include "port_before.h"
103650d1881Schristos #ifndef USE_KQUEUE
1042b237084Schristos #include "fd_setsize.h"
105650d1881Schristos #endif /* USE_KQUEUE */
1062b237084Schristos 
1072b237084Schristos #include <sys/types.h>
1082b237084Schristos #include <sys/param.h>
1092b237084Schristos #include <sys/time.h>
1102b237084Schristos #include <sys/socket.h>
1112b237084Schristos #include <sys/uio.h>
112650d1881Schristos #ifdef USE_KQUEUE
113650d1881Schristos #include <sys/event.h>
114650d1881Schristos #endif /* USE_KQUEUE */
1152b237084Schristos 
1162b237084Schristos #include <netinet/in.h>
1172b237084Schristos #include <arpa/nameser.h>
1182b237084Schristos #include <arpa/inet.h>
1192b237084Schristos 
120c5e820caSchristos #include <assert.h>
1212b237084Schristos #include <errno.h>
1222b237084Schristos #include <netdb.h>
1232b237084Schristos #include <resolv.h>
1242b237084Schristos #include <signal.h>
1252b237084Schristos #include <stdio.h>
126650d1881Schristos #include <fcntl.h>
1272b237084Schristos #include <stdlib.h>
1282b237084Schristos #include <string.h>
1292b237084Schristos #include <unistd.h>
1302b237084Schristos 
1312b237084Schristos #include <isc/eventlib.h>
1322b237084Schristos 
1332b237084Schristos #include "port_after.h"
1342b237084Schristos 
1355ce4c264Schristos #if 0
1366f3786f4Schristos #ifdef __weak_alias
1376f3786f4Schristos __weak_alias(res_ourserver_p,__res_ourserver_p)
1386f3786f4Schristos __weak_alias(res_nameinquery,__res_nameinquery)
1396f3786f4Schristos __weak_alias(res_queriesmatch,__res_queriesmatch)
1406f3786f4Schristos __weak_alias(res_nsend,__res_nsend)
1416f3786f4Schristos #endif
1425ce4c264Schristos #endif
1436f3786f4Schristos 
144650d1881Schristos #ifndef SOCK_NOSIGPIPE
145650d1881Schristos #define SOCK_NOSIGPIPE 0
146650d1881Schristos #endif
147650d1881Schristos #ifndef SOCK_NOCLOEXEC
148650d1881Schristos #define SOCK_NOCLOEXEC 0
149650d1881Schristos #endif
150d73eb73dSchristos 
151d73eb73dSchristos #ifdef USE_POLL
152d73eb73dSchristos #ifdef HAVE_STROPTS_H
153d73eb73dSchristos #include <stropts.h>
154d73eb73dSchristos #endif
155d73eb73dSchristos #include <poll.h>
156d73eb73dSchristos #endif /* USE_POLL */
157d73eb73dSchristos 
1582b237084Schristos /* Options.  Leave them on. */
1597ce5e09dSchristos #ifndef DEBUG
1602b237084Schristos #define DEBUG
1617ce5e09dSchristos #endif
1622b237084Schristos #include "res_debug.h"
1632b237084Schristos #include "res_private.h"
1642b237084Schristos 
1652b237084Schristos #define EXT(res) ((res)->_u._ext)
1662b237084Schristos 
167650d1881Schristos #if !defined(USE_POLL) && !defined(USE_KQUEUE)
1682b237084Schristos static const int highestFD = FD_SETSIZE - 1;
169d73eb73dSchristos #endif
1702b237084Schristos 
1712b237084Schristos /* Forward. */
1722b237084Schristos 
17372e5329bSchristos static socklen_t	get_salen(const struct sockaddr *);
174504f8671Smatt static struct sockaddr * get_nsaddr(res_state, size_t);
17561fab154Schristos static int		send_vc(res_state, const void *, size_t,
1762b237084Schristos 				u_char *, int, int *, int);
177650d1881Schristos static int		send_dg(res_state,
178650d1881Schristos #ifdef USE_KQUEUE
179650d1881Schristos 				int,
180650d1881Schristos #endif
18172e5329bSchristos 				const void *, size_t,
182d73eb73dSchristos 				u_char *, int, int *, int, int,
1832b237084Schristos 				int *, int *);
1842b237084Schristos static void		Aerror(const res_state, FILE *, const char *, int,
18572e5329bSchristos 			       const struct sockaddr *, socklen_t);
1862b237084Schristos static void		Perror(const res_state, FILE *, const char *, int);
1872b237084Schristos static int		sock_eq(struct sockaddr *, struct sockaddr *);
188650d1881Schristos #if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
1892b237084Schristos static int		pselect(int, void *, void *, void *,
1902b237084Schristos 				struct timespec *,
1912b237084Schristos 				const sigset_t *);
1922b237084Schristos #endif
1932b237084Schristos void res_pquery(const res_state, const u_char *, int, FILE *);
1942b237084Schristos 
1952b237084Schristos static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
1962b237084Schristos 
1972b237084Schristos /* Public. */
1982b237084Schristos 
199d73eb73dSchristos /*%
2002b237084Schristos  *	looks up "ina" in _res.ns_addr_list[]
201d73eb73dSchristos  *
2022b237084Schristos  * returns:
203d73eb73dSchristos  *\li	0  : not found
204d73eb73dSchristos  *\li	>0 : found
205d73eb73dSchristos  *
2062b237084Schristos  * author:
207d73eb73dSchristos  *\li	paul vixie, 29may94
2082b237084Schristos  */
2092b237084Schristos int
res_ourserver_p(const res_state statp,const struct sockaddr * sa)2102b237084Schristos res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
2112b237084Schristos 	const struct sockaddr_in *inp, *srv;
2122b237084Schristos 	const struct sockaddr_in6 *in6p, *srv6;
2132b237084Schristos 	int ns;
2142b237084Schristos 
2152b237084Schristos 	switch (sa->sa_family) {
2162b237084Schristos 	case AF_INET:
21750d86ec2Schristos 		inp = (const struct sockaddr_in *)(const void *)sa;
2182b237084Schristos 		for (ns = 0;  ns < statp->nscount;  ns++) {
2191ad5eecbSchristos 			srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
2202b237084Schristos 			if (srv->sin_family == inp->sin_family &&
2212b237084Schristos 			    srv->sin_port == inp->sin_port &&
2222b237084Schristos 			    (srv->sin_addr.s_addr == INADDR_ANY ||
2232b237084Schristos 			     srv->sin_addr.s_addr == inp->sin_addr.s_addr))
2242b237084Schristos 				return (1);
2252b237084Schristos 		}
2262b237084Schristos 		break;
2272b237084Schristos 	case AF_INET6:
2282b237084Schristos 		if (EXT(statp).ext == NULL)
2292b237084Schristos 			break;
23050d86ec2Schristos 		in6p = (const struct sockaddr_in6 *)(const void *)sa;
2312b237084Schristos 		for (ns = 0;  ns < statp->nscount;  ns++) {
2321ad5eecbSchristos 			srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
2332b237084Schristos 			if (srv6->sin6_family == in6p->sin6_family &&
2342b237084Schristos 			    srv6->sin6_port == in6p->sin6_port &&
2352b237084Schristos #ifdef HAVE_SIN6_SCOPE_ID
2360766545fSchristos 			    (srv6->sin6_scope_id == 0 ||
2370766545fSchristos 			     srv6->sin6_scope_id == in6p->sin6_scope_id) &&
2382b237084Schristos #endif
2392b237084Schristos 			    (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
2402b237084Schristos 			     IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
2412b237084Schristos 				return (1);
2422b237084Schristos 		}
2432b237084Schristos 		break;
2442b237084Schristos 	default:
2452b237084Schristos 		break;
2462b237084Schristos 	}
2472b237084Schristos 	return (0);
2482b237084Schristos }
2492b237084Schristos 
250d73eb73dSchristos /*%
2512b237084Schristos  *	look for (name,type,class) in the query section of packet (buf,eom)
252d73eb73dSchristos  *
2532b237084Schristos  * requires:
254d73eb73dSchristos  *\li	buf + HFIXEDSZ <= eom
255d73eb73dSchristos  *
2562b237084Schristos  * returns:
257d73eb73dSchristos  *\li	-1 : format error
258d73eb73dSchristos  *\li	0  : not found
259d73eb73dSchristos  *\li	>0 : found
260d73eb73dSchristos  *
2612b237084Schristos  * author:
262d73eb73dSchristos  *\li	paul vixie, 29may94
2632b237084Schristos  */
2642b237084Schristos int
res_nameinquery(const char * name,int type,int class,const u_char * buf,const u_char * eom)2652b237084Schristos res_nameinquery(const char *name, int type, int class,
2662b237084Schristos 		const u_char *buf, const u_char *eom)
2672b237084Schristos {
2682b237084Schristos 	const u_char *cp = buf + HFIXEDSZ;
2691ad5eecbSchristos 	int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
2702b237084Schristos 
2712b237084Schristos 	while (qdcount-- > 0) {
2722b237084Schristos 		char tname[MAXDNAME+1];
2732b237084Schristos 		int n, ttype, tclass;
2742b237084Schristos 
275c5e820caSchristos 		n = dn_expand(buf, eom, cp, tname, (int)sizeof tname);
2762b237084Schristos 		if (n < 0)
2772b237084Schristos 			return (-1);
2782b237084Schristos 		cp += n;
2792b237084Schristos 		if (cp + 2 * INT16SZ > eom)
2802b237084Schristos 			return (-1);
2812b237084Schristos 		ttype = ns_get16(cp); cp += INT16SZ;
2822b237084Schristos 		tclass = ns_get16(cp); cp += INT16SZ;
2832b237084Schristos 		if (ttype == type && tclass == class &&
2842b237084Schristos 		    ns_samename(tname, name) == 1)
2852b237084Schristos 			return (1);
2862b237084Schristos 	}
2872b237084Schristos 	return (0);
2882b237084Schristos }
2892b237084Schristos 
290d73eb73dSchristos /*%
2912b237084Schristos  *	is there a 1:1 mapping of (name,type,class)
2922b237084Schristos  *	in (buf1,eom1) and (buf2,eom2)?
293d73eb73dSchristos  *
2942b237084Schristos  * returns:
295d73eb73dSchristos  *\li	-1 : format error
296d73eb73dSchristos  *\li	0  : not a 1:1 mapping
297d73eb73dSchristos  *\li	>0 : is a 1:1 mapping
298d73eb73dSchristos  *
2992b237084Schristos  * author:
300d73eb73dSchristos  *\li	paul vixie, 29may94
3012b237084Schristos  */
3022b237084Schristos int
res_queriesmatch(const u_char * buf1,const u_char * eom1,const u_char * buf2,const u_char * eom2)3032b237084Schristos res_queriesmatch(const u_char *buf1, const u_char *eom1,
3042b237084Schristos 		 const u_char *buf2, const u_char *eom2)
3052b237084Schristos {
3062b237084Schristos 	const u_char *cp = buf1 + HFIXEDSZ;
3071ad5eecbSchristos 	int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
3082b237084Schristos 
3092b237084Schristos 	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
3102b237084Schristos 		return (-1);
3112b237084Schristos 
3122b237084Schristos 	/*
3132b237084Schristos 	 * Only header section present in replies to
3142b237084Schristos 	 * dynamic update packets.
3152b237084Schristos 	 */
3161ad5eecbSchristos 	if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
3171ad5eecbSchristos 	    (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
3182b237084Schristos 		return (1);
3192b237084Schristos 
3201ad5eecbSchristos 	if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
3212b237084Schristos 		return (0);
3222b237084Schristos 	while (qdcount-- > 0) {
3232b237084Schristos 		char tname[MAXDNAME+1];
3242b237084Schristos 		int n, ttype, tclass;
3252b237084Schristos 
326c5e820caSchristos 		n = dn_expand(buf1, eom1, cp, tname, (int)sizeof tname);
3272b237084Schristos 		if (n < 0)
3282b237084Schristos 			return (-1);
3292b237084Schristos 		cp += n;
3302b237084Schristos 		if (cp + 2 * INT16SZ > eom1)
3312b237084Schristos 			return (-1);
3322b237084Schristos 		ttype = ns_get16(cp);	cp += INT16SZ;
3332b237084Schristos 		tclass = ns_get16(cp); cp += INT16SZ;
3342b237084Schristos 		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
3352b237084Schristos 			return (0);
3362b237084Schristos 	}
3372b237084Schristos 	return (1);
3382b237084Schristos }
3392b237084Schristos 
3402b237084Schristos int
res_nsend(res_state statp,const u_char * buf,int buflen,u_char * ans,int anssiz)3412b237084Schristos res_nsend(res_state statp,
3422b237084Schristos 	  const u_char *buf, int buflen, u_char *ans, int anssiz)
3432b237084Schristos {
3443873655bSchristos 	int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
345650d1881Schristos #ifdef USE_KQUEUE
346650d1881Schristos 	int kq;
347650d1881Schristos #endif
3482b237084Schristos 	char abuf[NI_MAXHOST];
3492b237084Schristos 
350e942b6ecSchristos 	(void)res_check(statp, NULL);
351249296c4Schristos 
352d73eb73dSchristos 	/* No name servers or res_init() failure */
353d73eb73dSchristos 	if (statp->nscount == 0 || EXT(statp).ext == NULL) {
3542b237084Schristos 		errno = ESRCH;
3552b237084Schristos 		return (-1);
3562b237084Schristos 	}
3572b237084Schristos 	if (anssiz < HFIXEDSZ) {
3582b237084Schristos 		errno = EINVAL;
3592b237084Schristos 		return (-1);
3602b237084Schristos 	}
3612b237084Schristos 	DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
3622b237084Schristos 		(stdout, ";; res_send()\n"), buf, buflen);
3632b237084Schristos 	v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
3642b237084Schristos 	gotsomewhere = 0;
3652b237084Schristos 	terrno = ETIMEDOUT;
3662b237084Schristos 
367650d1881Schristos #ifdef USE_KQUEUE
368650d1881Schristos 	if ((kq = kqueue1(O_CLOEXEC)) == -1) {
369650d1881Schristos 		return (-1);
370650d1881Schristos 	}
371650d1881Schristos #endif
372650d1881Schristos 
3732b237084Schristos 	/*
3742b237084Schristos 	 * If the ns_addr_list in the resolver context has changed, then
3752b237084Schristos 	 * invalidate our cached copy and the associated timing data.
3762b237084Schristos 	 */
3772b237084Schristos 	if (EXT(statp).nscount != 0) {
3782b237084Schristos 		int needclose = 0;
3792b237084Schristos 		struct sockaddr_storage peer;
3802b237084Schristos 		ISC_SOCKLEN_T peerlen;
3812b237084Schristos 
3822b237084Schristos 		if (EXT(statp).nscount != statp->nscount)
3832b237084Schristos 			needclose++;
3842b237084Schristos 		else
3852b237084Schristos 			for (ns = 0; ns < statp->nscount; ns++) {
3862b237084Schristos 				if (statp->nsaddr_list[ns].sin_family &&
3871ad5eecbSchristos 				    !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
3881ad5eecbSchristos 					     (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
3892b237084Schristos 					needclose++;
3902b237084Schristos 					break;
3912b237084Schristos 				}
3922b237084Schristos 
3932b237084Schristos 				if (EXT(statp).nssocks[ns] == -1)
3942b237084Schristos 					continue;
3952b237084Schristos 				peerlen = sizeof(peer);
396798e7182Smrg 				if (getpeername(EXT(statp).nssocks[ns],
3971ad5eecbSchristos 				    (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
3982b237084Schristos 					needclose++;
3992b237084Schristos 					break;
4002b237084Schristos 				}
4011ad5eecbSchristos 				if (!sock_eq((struct sockaddr *)(void *)&peer,
4021ad5eecbSchristos 				    get_nsaddr(statp, (size_t)ns))) {
4032b237084Schristos 					needclose++;
4042b237084Schristos 					break;
4052b237084Schristos 				}
4062b237084Schristos 			}
4072b237084Schristos 		if (needclose) {
4082b237084Schristos 			res_nclose(statp);
4092b237084Schristos 			EXT(statp).nscount = 0;
4102b237084Schristos 		}
4112b237084Schristos 	}
4122b237084Schristos 
4132b237084Schristos 	/*
4142b237084Schristos 	 * Maybe initialize our private copy of the ns_addr_list.
4152b237084Schristos 	 */
4162b237084Schristos 	if (EXT(statp).nscount == 0) {
4172b237084Schristos 		for (ns = 0; ns < statp->nscount; ns++) {
4182b237084Schristos 			EXT(statp).nstimes[ns] = RES_MAXTIME;
4192b237084Schristos 			EXT(statp).nssocks[ns] = -1;
4202b237084Schristos 			if (!statp->nsaddr_list[ns].sin_family)
4212b237084Schristos 				continue;
4222b237084Schristos 			EXT(statp).ext->nsaddrs[ns].sin =
4232b237084Schristos 				 statp->nsaddr_list[ns];
4242b237084Schristos 		}
4252b237084Schristos 		EXT(statp).nscount = statp->nscount;
4262b237084Schristos 	}
4272b237084Schristos 
4282b237084Schristos 	/*
4292b237084Schristos 	 * Some resolvers want to even out the load on their nameservers.
4302b237084Schristos 	 * Note that RES_BLAST overrides RES_ROTATE.
4312b237084Schristos 	 */
4322b237084Schristos 	if ((statp->options & RES_ROTATE) != 0U &&
4332b237084Schristos 	    (statp->options & RES_BLAST) == 0U) {
4342b237084Schristos 		union res_sockaddr_union inu;
4352b237084Schristos 		struct sockaddr_in ina;
4362b237084Schristos 		int lastns = statp->nscount - 1;
4372b237084Schristos 		int fd;
4382b237084Schristos 		u_int16_t nstime;
4392b237084Schristos 
4402b237084Schristos 		if (EXT(statp).ext != NULL)
4412b237084Schristos 			inu = EXT(statp).ext->nsaddrs[0];
4422b237084Schristos 		ina = statp->nsaddr_list[0];
4432b237084Schristos 		fd = EXT(statp).nssocks[0];
4442b237084Schristos 		nstime = EXT(statp).nstimes[0];
4452b237084Schristos 		for (ns = 0; ns < lastns; ns++) {
4462b237084Schristos 			if (EXT(statp).ext != NULL)
4472b237084Schristos 				EXT(statp).ext->nsaddrs[ns] =
4482b237084Schristos 					EXT(statp).ext->nsaddrs[ns + 1];
4492b237084Schristos 			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
4502b237084Schristos 			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
4512b237084Schristos 			EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
4522b237084Schristos 		}
4532b237084Schristos 		if (EXT(statp).ext != NULL)
4542b237084Schristos 			EXT(statp).ext->nsaddrs[lastns] = inu;
4552b237084Schristos 		statp->nsaddr_list[lastns] = ina;
4562b237084Schristos 		EXT(statp).nssocks[lastns] = fd;
4572b237084Schristos 		EXT(statp).nstimes[lastns] = nstime;
4582b237084Schristos 	}
4592b237084Schristos 
4602b237084Schristos 	/*
4612b237084Schristos 	 * Send request, RETRY times, or until successful.
4622b237084Schristos 	 */
4633873655bSchristos 	for (tries = 0; tries < statp->retry; tries++) {
4642b237084Schristos 	    for (ns = 0; ns < statp->nscount; ns++) {
4652b237084Schristos 		struct sockaddr *nsap;
46672e5329bSchristos 		socklen_t nsaplen;
4671ad5eecbSchristos 		nsap = get_nsaddr(statp, (size_t)ns);
4682b237084Schristos 		nsaplen = get_salen(nsap);
4692b237084Schristos 		statp->_flags &= ~RES_F_LASTMASK;
4702b237084Schristos 		statp->_flags |= (ns << RES_F_LASTSHIFT);
4712b237084Schristos  same_ns:
4722b237084Schristos 		if (statp->qhook) {
4732b237084Schristos 			int done = 0, loops = 0;
4742b237084Schristos 
4752b237084Schristos 			do {
4762b237084Schristos 				res_sendhookact act;
4772b237084Schristos 
4782b237084Schristos 				act = (*statp->qhook)(&nsap, &buf, &buflen,
4792b237084Schristos 						      ans, anssiz, &resplen);
4802b237084Schristos 				switch (act) {
4812b237084Schristos 				case res_goahead:
4822b237084Schristos 					done = 1;
4832b237084Schristos 					break;
4842b237084Schristos 				case res_nextns:
4852b237084Schristos 					res_nclose(statp);
4862b237084Schristos 					goto next_ns;
4872b237084Schristos 				case res_done:
488650d1881Schristos #ifdef USE_KQUEUE
489650d1881Schristos 					close(kq);
490650d1881Schristos #endif
4912b237084Schristos 					return (resplen);
4922b237084Schristos 				case res_modified:
4932b237084Schristos 					/* give the hook another try */
4942b237084Schristos 					if (++loops < 42) /*doug adams*/
4952b237084Schristos 						break;
4962b237084Schristos 					/*FALLTHROUGH*/
4972b237084Schristos 				case res_error:
4982b237084Schristos 					/*FALLTHROUGH*/
4992b237084Schristos 				default:
5002b237084Schristos 					goto fail;
5012b237084Schristos 				}
5022b237084Schristos 			} while (!done);
5032b237084Schristos 		}
5042b237084Schristos 
5052b237084Schristos 		Dprint(((statp->options & RES_DEBUG) &&
50672e5329bSchristos 			getnameinfo(nsap, nsaplen, abuf,
507c5e820caSchristos 			    (socklen_t)sizeof(abuf), NULL, 0, niflags) == 0),
5082b237084Schristos 		       (stdout, ";; Querying server (# %d) address = %s\n",
5092b237084Schristos 			ns + 1, abuf));
5102b237084Schristos 
5112b237084Schristos 
5122b237084Schristos 		if (v_circuit) {
5132b237084Schristos 			/* Use VC; at most one attempt per server. */
5143873655bSchristos 			tries = statp->retry;
515bc91d7faSpara 			n = send_vc(statp, buf, (size_t)buflen, ans, anssiz, &terrno,
5162b237084Schristos 				    ns);
5172b237084Schristos 			if (n < 0)
5182b237084Schristos 				goto fail;
5192b237084Schristos 			if (n == 0)
5202b237084Schristos 				goto next_ns;
5212b237084Schristos 			resplen = n;
5222b237084Schristos 		} else {
5232b237084Schristos 			/* Use datagrams. */
524650d1881Schristos 			n = send_dg(statp,
525650d1881Schristos #ifdef USE_KQUEUE
526650d1881Schristos 			    kq,
527650d1881Schristos #endif
52872e5329bSchristos 			    buf, (size_t)buflen, ans, anssiz, &terrno,
5293873655bSchristos 			    ns, tries, &v_circuit, &gotsomewhere);
5302b237084Schristos 			if (n < 0)
5312b237084Schristos 				goto fail;
5322b237084Schristos 			if (n == 0)
5332b237084Schristos 				goto next_ns;
5342b237084Schristos 			if (v_circuit)
5352b237084Schristos 				goto same_ns;
5362b237084Schristos 			resplen = n;
5372b237084Schristos 		}
5382b237084Schristos 
5392b237084Schristos 		Dprint((statp->options & RES_DEBUG) ||
5402b237084Schristos 		       ((statp->pfcode & RES_PRF_REPLY) &&
5412b237084Schristos 			(statp->pfcode & RES_PRF_HEAD1)),
5422b237084Schristos 		       (stdout, ";; got answer:\n"));
5432b237084Schristos 
5442b237084Schristos 		DprintQ((statp->options & RES_DEBUG) ||
5452b237084Schristos 			(statp->pfcode & RES_PRF_REPLY),
5462b237084Schristos 			(stdout, "%s", ""),
5472b237084Schristos 			ans, (resplen > anssiz) ? anssiz : resplen);
5482b237084Schristos 
5492b237084Schristos 		/*
5502b237084Schristos 		 * If we have temporarily opened a virtual circuit,
5512b237084Schristos 		 * or if we haven't been asked to keep a socket open,
5522b237084Schristos 		 * close the socket.
5532b237084Schristos 		 */
5542b237084Schristos 		if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
5552b237084Schristos 		    (statp->options & RES_STAYOPEN) == 0U) {
5562b237084Schristos 			res_nclose(statp);
5572b237084Schristos 		}
5582b237084Schristos 		if (statp->rhook) {
5592b237084Schristos 			int done = 0, loops = 0;
5602b237084Schristos 
5612b237084Schristos 			do {
5622b237084Schristos 				res_sendhookact act;
5632b237084Schristos 
5642b237084Schristos 				act = (*statp->rhook)(nsap, buf, buflen,
5652b237084Schristos 						      ans, anssiz, &resplen);
5662b237084Schristos 				switch (act) {
5672b237084Schristos 				case res_goahead:
5682b237084Schristos 				case res_done:
5692b237084Schristos 					done = 1;
5702b237084Schristos 					break;
5712b237084Schristos 				case res_nextns:
5722b237084Schristos 					res_nclose(statp);
5732b237084Schristos 					goto next_ns;
5742b237084Schristos 				case res_modified:
5752b237084Schristos 					/* give the hook another try */
5762b237084Schristos 					if (++loops < 42) /*doug adams*/
5772b237084Schristos 						break;
5782b237084Schristos 					/*FALLTHROUGH*/
5792b237084Schristos 				case res_error:
5802b237084Schristos 					/*FALLTHROUGH*/
5812b237084Schristos 				default:
5822b237084Schristos 					goto fail;
5832b237084Schristos 				}
5842b237084Schristos 			} while (!done);
5852b237084Schristos 
5862b237084Schristos 		}
587650d1881Schristos #ifdef USE_KQUEUE
588650d1881Schristos 		close(kq);
589650d1881Schristos #endif
5902b237084Schristos 		return (resplen);
5912b237084Schristos  next_ns: ;
5922b237084Schristos 	   } /*foreach ns*/
5932b237084Schristos 	} /*foreach retry*/
5942b237084Schristos 	res_nclose(statp);
595650d1881Schristos #ifdef USE_KQUEUE
596650d1881Schristos 	close(kq);
597650d1881Schristos #endif
5982b237084Schristos 	if (!v_circuit) {
5992b237084Schristos 		if (!gotsomewhere)
600d73eb73dSchristos 			errno = ECONNREFUSED;	/*%< no nameservers found */
6012b237084Schristos 		else
602d73eb73dSchristos 			errno = ETIMEDOUT;	/*%< no answer obtained */
6032b237084Schristos 	} else
6042b237084Schristos 		errno = terrno;
6052b237084Schristos 	return (-1);
6062b237084Schristos  fail:
6072b237084Schristos 	res_nclose(statp);
608650d1881Schristos #ifdef USE_KQUEUE
609650d1881Schristos 	close(kq);
610650d1881Schristos #endif
6112b237084Schristos 	return (-1);
6122b237084Schristos }
6132b237084Schristos 
6142b237084Schristos /* Private */
6152b237084Schristos 
61672e5329bSchristos static socklen_t
get_salen(const struct sockaddr * sa)617504f8671Smatt get_salen(const struct sockaddr *sa)
6182b237084Schristos {
6192b237084Schristos 
6202b237084Schristos #ifdef HAVE_SA_LEN
6212b237084Schristos 	/* There are people do not set sa_len.  Be forgiving to them. */
6222b237084Schristos 	if (sa->sa_len)
62372e5329bSchristos 		return (socklen_t)sa->sa_len;
6242b237084Schristos #endif
6252b237084Schristos 
6262b237084Schristos 	if (sa->sa_family == AF_INET)
62772e5329bSchristos 		return (socklen_t)sizeof(struct sockaddr_in);
6282b237084Schristos 	else if (sa->sa_family == AF_INET6)
62972e5329bSchristos 		return (socklen_t)sizeof(struct sockaddr_in6);
6302b237084Schristos 	else
63172e5329bSchristos 		return 0;	/*%< unknown, die on connect */
6322b237084Schristos }
6332b237084Schristos 
634d73eb73dSchristos /*%
6352b237084Schristos  * pick appropriate nsaddr_list for use.  see res_init() for initialization.
6362b237084Schristos  */
6372b237084Schristos static struct sockaddr *
get_nsaddr(res_state statp,size_t n)638504f8671Smatt get_nsaddr(res_state statp, size_t n)
6392b237084Schristos {
6402b237084Schristos 
6412b237084Schristos 	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
6422b237084Schristos 		/*
6432b237084Schristos 		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
6442b237084Schristos 		 *   than struct sockaddr, and
6452b237084Schristos 		 * - user code did not update statp->nsaddr_list[n].
6462b237084Schristos 		 */
6472b237084Schristos 		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
6482b237084Schristos 	} else {
6492b237084Schristos 		/*
6502b237084Schristos 		 * - user code updated statp->nsaddr_list[n], or
6512b237084Schristos 		 * - statp->nsaddr_list[n] has the same content as
6522b237084Schristos 		 *   EXT(statp).ext->nsaddrs[n].
6532b237084Schristos 		 */
6542b237084Schristos 		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
6552b237084Schristos 	}
6562b237084Schristos }
6572b237084Schristos 
6582b237084Schristos static int
send_vc(res_state statp,const void * buf,size_t buflen,u_char * ans,int anssiz,int * terrno,int ns)6592b237084Schristos send_vc(res_state statp,
66061fab154Schristos 	const void *buf, size_t buflen, u_char *ans, int anssiz,
6612b237084Schristos 	int *terrno, int ns)
6622b237084Schristos {
66350d86ec2Schristos 	const HEADER *hp = (const HEADER *)(const void *)buf;
66450d86ec2Schristos 	HEADER *anhp = (HEADER *)(void *)ans;
6652b237084Schristos 	struct sockaddr *nsap;
66672e5329bSchristos 	socklen_t nsaplen;
667c5e820caSchristos 	int truncating, connreset, resplen;
668c5e820caSchristos 	ssize_t n;
6692b237084Schristos 	struct iovec iov[2];
6702b237084Schristos 	u_short len;
6712b237084Schristos 	u_char *cp;
6722b237084Schristos 	void *tmp;
673650d1881Schristos #if defined(SO_NOSIGPIPE) && SOCK_NOSIGPIPE == 0
6743873655bSchristos 	int on = 1;
6753873655bSchristos #endif
6762b237084Schristos 
6771ad5eecbSchristos 	nsap = get_nsaddr(statp, (size_t)ns);
6782b237084Schristos 	nsaplen = get_salen(nsap);
6792b237084Schristos 
6802b237084Schristos 	connreset = 0;
6812b237084Schristos  same_ns:
6822b237084Schristos 	truncating = 0;
6832b237084Schristos 
6842b237084Schristos 	/* Are we still talking to whom we want to talk to? */
6852b237084Schristos 	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
6862b237084Schristos 		struct sockaddr_storage peer;
6872b237084Schristos 		ISC_SOCKLEN_T size = sizeof peer;
6882b237084Schristos 
6892b237084Schristos 		if (getpeername(statp->_vcsock,
6901ad5eecbSchristos 				(struct sockaddr *)(void *)&peer, &size) < 0 ||
6911ad5eecbSchristos 		    !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
6922b237084Schristos 			res_nclose(statp);
6932b237084Schristos 			statp->_flags &= ~RES_F_VC;
6942b237084Schristos 		}
6952b237084Schristos 	}
6962b237084Schristos 
6972b237084Schristos 	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
6982b237084Schristos 		if (statp->_vcsock >= 0)
6992b237084Schristos 			res_nclose(statp);
7002b237084Schristos 
701650d1881Schristos 		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM
702650d1881Schristos 			| SOCK_NOSIGPIPE | SOCK_CLOEXEC, 0);
703650d1881Schristos #if SOCK_CLOEXEC == 0
704650d1881Schristos 		fcntl(statp->_vcsock, F_SETFD, FD_CLOEXEC);
705650d1881Schristos #endif
706650d1881Schristos #if !defined(USE_POLL) && !defined(USE_KQUEUE)
7072b237084Schristos 		if (statp->_vcsock > highestFD) {
7082b237084Schristos 			res_nclose(statp);
7092b237084Schristos 			errno = ENOTSOCK;
7102b237084Schristos 		}
71179b560daSpooka #endif
7122b237084Schristos 		if (statp->_vcsock < 0) {
7132b237084Schristos 			switch (errno) {
7142b237084Schristos 			case EPROTONOSUPPORT:
7152b237084Schristos #ifdef EPFNOSUPPORT
7162b237084Schristos 			case EPFNOSUPPORT:
7172b237084Schristos #endif
7182b237084Schristos 			case EAFNOSUPPORT:
7192b237084Schristos 				Perror(statp, stderr, "socket(vc)", errno);
7202b237084Schristos 				return (0);
7212b237084Schristos 			default:
7222b237084Schristos 				*terrno = errno;
7232b237084Schristos 				Perror(statp, stderr, "socket(vc)", errno);
7242b237084Schristos 				return (-1);
7252b237084Schristos 			}
7262b237084Schristos 		}
727650d1881Schristos #if defined(SO_NOSIGPIPE) && SOCK_NOSIGPIPE == 0
7283873655bSchristos 		/*
7293873655bSchristos 		 * Disable generation of SIGPIPE when writing to a closed
7303873655bSchristos 		 * socket.  Write should return -1 and set errno to EPIPE
7313873655bSchristos 		 * instead.
7323873655bSchristos 		 *
7333873655bSchristos 		 * Push on even if setsockopt(SO_NOSIGPIPE) fails.
7343873655bSchristos 		 */
7353873655bSchristos 		(void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
736650d1881Schristos 				 (socklen_t)sizeof(on));
7373873655bSchristos #endif
7382b237084Schristos 		errno = 0;
73972e5329bSchristos 		if (connect(statp->_vcsock, nsap, nsaplen) < 0) {
7402b237084Schristos 			*terrno = errno;
7412b237084Schristos 			Aerror(statp, stderr, "connect/vc", errno, nsap,
7422b237084Schristos 			    nsaplen);
7432b237084Schristos 			res_nclose(statp);
7442b237084Schristos 			return (0);
7452b237084Schristos 		}
7462b237084Schristos 		statp->_flags |= RES_F_VC;
7472b237084Schristos 	}
7482b237084Schristos 
7492b237084Schristos 	/*
7502b237084Schristos 	 * Send length & message
7512b237084Schristos 	 */
7521ad5eecbSchristos 	ns_put16((u_short)buflen, (u_char*)(void *)&len);
7532b237084Schristos 	iov[0] = evConsIovec(&len, INT16SZ);
7542b237084Schristos 	DE_CONST(buf, tmp);
755bc91d7faSpara 	iov[1] = evConsIovec(tmp, (size_t)buflen);
75672e5329bSchristos 	if (writev(statp->_vcsock, iov, 2) != (ssize_t)(INT16SZ + buflen)) {
7572b237084Schristos 		*terrno = errno;
7582b237084Schristos 		Perror(statp, stderr, "write failed", errno);
7592b237084Schristos 		res_nclose(statp);
7602b237084Schristos 		return (0);
7612b237084Schristos 	}
7622b237084Schristos 	/*
7632b237084Schristos 	 * Receive length & response
7642b237084Schristos 	 */
7652b237084Schristos  read_len:
7662b237084Schristos 	cp = ans;
7672b237084Schristos 	len = INT16SZ;
7681ad5eecbSchristos 	while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
7692b237084Schristos 		cp += n;
770c5e820caSchristos 		if ((len -= (u_short)n) == 0)
7712b237084Schristos 			break;
7722b237084Schristos 	}
7732b237084Schristos 	if (n <= 0) {
7742b237084Schristos 		*terrno = errno;
7752b237084Schristos 		Perror(statp, stderr, "read failed", errno);
7762b237084Schristos 		res_nclose(statp);
7772b237084Schristos 		/*
7782b237084Schristos 		 * A long running process might get its TCP
7792b237084Schristos 		 * connection reset if the remote server was
7802b237084Schristos 		 * restarted.  Requery the server instead of
7812b237084Schristos 		 * trying a new one.  When there is only one
7822b237084Schristos 		 * server, this means that a query might work
7832b237084Schristos 		 * instead of failing.  We only allow one reset
7842b237084Schristos 		 * per query to prevent looping.
7852b237084Schristos 		 */
7862b237084Schristos 		if (*terrno == ECONNRESET && !connreset) {
7872b237084Schristos 			connreset = 1;
7882b237084Schristos 			res_nclose(statp);
7892b237084Schristos 			goto same_ns;
7902b237084Schristos 		}
7912b237084Schristos 		res_nclose(statp);
7922b237084Schristos 		return (0);
7932b237084Schristos 	}
7942b237084Schristos 	resplen = ns_get16(ans);
7952b237084Schristos 	if (resplen > anssiz) {
7962b237084Schristos 		Dprint(statp->options & RES_DEBUG,
7972b237084Schristos 		       (stdout, ";; response truncated\n")
7982b237084Schristos 		       );
7992b237084Schristos 		truncating = 1;
8002b237084Schristos 		len = anssiz;
8012b237084Schristos 	} else
8022b237084Schristos 		len = resplen;
8032b237084Schristos 	if (len < HFIXEDSZ) {
8042b237084Schristos 		/*
8052b237084Schristos 		 * Undersized message.
8062b237084Schristos 		 */
8072b237084Schristos 		Dprint(statp->options & RES_DEBUG,
8082b237084Schristos 		       (stdout, ";; undersized: %d\n", len));
8092b237084Schristos 		*terrno = EMSGSIZE;
8102b237084Schristos 		res_nclose(statp);
8112b237084Schristos 		return (0);
8122b237084Schristos 	}
8132b237084Schristos 	cp = ans;
8141ad5eecbSchristos 	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
8152b237084Schristos 		cp += n;
816c5e820caSchristos 		len -= (u_short)n;
8172b237084Schristos 	}
8182b237084Schristos 	if (n <= 0) {
8192b237084Schristos 		*terrno = errno;
8202b237084Schristos 		Perror(statp, stderr, "read(vc)", errno);
8212b237084Schristos 		res_nclose(statp);
8222b237084Schristos 		return (0);
8232b237084Schristos 	}
8242b237084Schristos 	if (truncating) {
8252b237084Schristos 		/*
8262b237084Schristos 		 * Flush rest of answer so connection stays in synch.
8272b237084Schristos 		 */
8282b237084Schristos 		anhp->tc = 1;
8292b237084Schristos 		len = resplen - anssiz;
8302b237084Schristos 		while (len != 0) {
8312b237084Schristos 			char junk[PACKETSZ];
8322b237084Schristos 
8332b237084Schristos 			n = read(statp->_vcsock, junk,
8342b237084Schristos 				 (len > sizeof junk) ? sizeof junk : len);
8352b237084Schristos 			if (n > 0)
836c5e820caSchristos 				len -= (u_short)n;
8372b237084Schristos 			else
8382b237084Schristos 				break;
8392b237084Schristos 		}
8402b237084Schristos 	}
8412b237084Schristos 	/*
8422b237084Schristos 	 * If the calling applicating has bailed out of
8432b237084Schristos 	 * a previous call and failed to arrange to have
8442b237084Schristos 	 * the circuit closed or the server has got
8452b237084Schristos 	 * itself confused, then drop the packet and
8462b237084Schristos 	 * wait for the correct one.
8472b237084Schristos 	 */
8482b237084Schristos 	if (hp->id != anhp->id) {
8492b237084Schristos 		DprintQ((statp->options & RES_DEBUG) ||
8502b237084Schristos 			(statp->pfcode & RES_PRF_REPLY),
8512b237084Schristos 			(stdout, ";; old answer (unexpected):\n"),
8522b237084Schristos 			ans, (resplen > anssiz) ? anssiz: resplen);
8532b237084Schristos 		goto read_len;
8542b237084Schristos 	}
8552b237084Schristos 
8562b237084Schristos 	/*
8572b237084Schristos 	 * All is well, or the error is fatal.  Signal that the
8582b237084Schristos 	 * next nameserver ought not be tried.
8592b237084Schristos 	 */
8602b237084Schristos 	return (resplen);
8612b237084Schristos }
8622b237084Schristos 
8632b237084Schristos static int
send_dg(res_state statp,int kq,const void * buf,size_t buflen,u_char * ans,int anssiz,int * terrno,int ns,int tries,int * v_circuit,int * gotsomewhere)864650d1881Schristos send_dg(res_state statp,
865650d1881Schristos #ifdef USE_KQUEUE
866650d1881Schristos 	int kq,
867650d1881Schristos #endif
86872e5329bSchristos 	const void *buf, size_t buflen, u_char *ans,
8693873655bSchristos 	int anssiz, int *terrno, int ns, int tries, int *v_circuit,
870d73eb73dSchristos 	int *gotsomewhere)
8712b237084Schristos {
8721ad5eecbSchristos 	const HEADER *hp = (const HEADER *)(const void *)buf;
8731ad5eecbSchristos 	HEADER *anhp = (HEADER *)(void *)ans;
8742b237084Schristos 	const struct sockaddr *nsap;
87572e5329bSchristos 	socklen_t nsaplen;
8762b237084Schristos 	struct timespec now, timeout, finish;
8772b237084Schristos 	struct sockaddr_storage from;
8782b237084Schristos 	ISC_SOCKLEN_T fromlen;
879c5e820caSchristos 	ssize_t resplen;
880c5e820caSchristos 	int seconds, n, s;
881650d1881Schristos #ifdef USE_KQUEUE
882650d1881Schristos 	struct kevent kv;
883650d1881Schristos #else
884d73eb73dSchristos #ifdef USE_POLL
885d73eb73dSchristos 	int     polltimeout;
886d73eb73dSchristos 	struct pollfd   pollfd;
887d73eb73dSchristos #else
888d73eb73dSchristos 	fd_set dsmask;
889d73eb73dSchristos #endif
890650d1881Schristos #endif
8912b237084Schristos 
8921ad5eecbSchristos 	nsap = get_nsaddr(statp, (size_t)ns);
8932b237084Schristos 	nsaplen = get_salen(nsap);
8942b237084Schristos 	if (EXT(statp).nssocks[ns] == -1) {
895650d1881Schristos 		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM
896650d1881Schristos 			| SOCK_CLOEXEC, 0);
897650d1881Schristos #if SOCK_CLOEXEC == 0
898650d1881Schristos 		fcntl(EXT(statp)nssocks[ns], F_SETFD, FD_CLOEXEC);
899650d1881Schristos #endif
900650d1881Schristos #if !defined(USE_POLL) && !defined(USE_KQUEUE)
9012b237084Schristos 		if (EXT(statp).nssocks[ns] > highestFD) {
9022b237084Schristos 			res_nclose(statp);
9032b237084Schristos 			errno = ENOTSOCK;
9042b237084Schristos 		}
90579b560daSpooka #endif
9062b237084Schristos 		if (EXT(statp).nssocks[ns] < 0) {
9072b237084Schristos 			switch (errno) {
9082b237084Schristos 			case EPROTONOSUPPORT:
9092b237084Schristos #ifdef EPFNOSUPPORT
9102b237084Schristos 			case EPFNOSUPPORT:
9112b237084Schristos #endif
9122b237084Schristos 			case EAFNOSUPPORT:
9132b237084Schristos 				Perror(statp, stderr, "socket(dg)", errno);
9142b237084Schristos 				return (0);
9152b237084Schristos 			default:
9162b237084Schristos 				*terrno = errno;
9172b237084Schristos 				Perror(statp, stderr, "socket(dg)", errno);
9182b237084Schristos 				return (-1);
9192b237084Schristos 			}
9202b237084Schristos 		}
9212b237084Schristos #ifndef CANNOT_CONNECT_DGRAM
9222b237084Schristos 		/*
9232b237084Schristos 		 * On a 4.3BSD+ machine (client and server,
9242b237084Schristos 		 * actually), sending to a nameserver datagram
9252b237084Schristos 		 * port with no nameserver will cause an
9262b237084Schristos 		 * ICMP port unreachable message to be returned.
9272b237084Schristos 		 * If our datagram socket is "connected" to the
9282b237084Schristos 		 * server, we get an ECONNREFUSED error on the next
9292b237084Schristos 		 * socket operation, and select returns if the
9302b237084Schristos 		 * error message is received.  We can thus detect
9312b237084Schristos 		 * the absence of a nameserver without timing out.
932650d1881Schristos 		 *
933650d1881Schristos 		 * When the option "insecure1" is specified, we'd
934650d1881Schristos 		 * rather expect to see responses from an "unknown"
935650d1881Schristos 		 * address.  In order to let the kernel accept such
936650d1881Schristos 		 * responses, do not connect the socket here.
937650d1881Schristos 		 * XXX: or do we need an explicit option to disable
938650d1881Schristos 		 * connecting?
9392b237084Schristos  		 */
940650d1881Schristos 		if (!(statp->options & RES_INSECURE1) &&
94172e5329bSchristos 		    connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {
9422b237084Schristos 			Aerror(statp, stderr, "connect(dg)", errno, nsap,
9432b237084Schristos 			    nsaplen);
9442b237084Schristos 			res_nclose(statp);
9452b237084Schristos 			return (0);
9462b237084Schristos 		}
9472b237084Schristos #endif /* !CANNOT_CONNECT_DGRAM */
9482b237084Schristos 		Dprint(statp->options & RES_DEBUG,
9492b237084Schristos 		       (stdout, ";; new DG socket\n"))
9502b237084Schristos 	}
9512b237084Schristos 	s = EXT(statp).nssocks[ns];
9522b237084Schristos #ifndef CANNOT_CONNECT_DGRAM
953650d1881Schristos 	if (statp->options & RES_INSECURE1) {
95472e5329bSchristos 		if (sendto(s, buf, buflen, 0, nsap, nsaplen) !=
95572e5329bSchristos 		    (ssize_t)buflen) {
956650d1881Schristos 			Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
957650d1881Schristos 			res_nclose(statp);
958650d1881Schristos 			return (0);
959650d1881Schristos 		}
96072e5329bSchristos 	} else if (send(s, buf, buflen, 0) != (ssize_t)buflen) {
9612b237084Schristos 		Perror(statp, stderr, "send", errno);
9622b237084Schristos 		res_nclose(statp);
9632b237084Schristos 		return (0);
9642b237084Schristos 	}
9652b237084Schristos #else /* !CANNOT_CONNECT_DGRAM */
96672e5329bSchristos 	if (sendto(s, buf, buflen, 0, nsap, nsaplen) != (ssize_t)buflen)
9672b237084Schristos 	{
9682b237084Schristos 		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
9692b237084Schristos 		res_nclose(statp);
9702b237084Schristos 		return (0);
9712b237084Schristos 	}
9722b237084Schristos #endif /* !CANNOT_CONNECT_DGRAM */
9732b237084Schristos 
9742b237084Schristos 	/*
9752b237084Schristos 	 * Wait for reply.
9762b237084Schristos 	 */
9773873655bSchristos 	seconds = (statp->retrans << tries);
9782b237084Schristos 	if (ns > 0)
9792b237084Schristos 		seconds /= statp->nscount;
9802b237084Schristos 	if (seconds <= 0)
9812b237084Schristos 		seconds = 1;
9822b237084Schristos 	now = evNowTime();
983a8d19c80Schristos 	timeout = evConsTime((time_t)seconds, 0L);
9842b237084Schristos 	finish = evAddTime(now, timeout);
9852b237084Schristos 	goto nonow;
9862b237084Schristos  wait:
9872b237084Schristos 	now = evNowTime();
9882b237084Schristos  nonow:
989d73eb73dSchristos #ifndef USE_POLL
9902b237084Schristos 	if (evCmpTime(finish, now) > 0)
9912b237084Schristos 		timeout = evSubTime(finish, now);
9922b237084Schristos 	else
99350d86ec2Schristos 		timeout = evConsTime(0L, 0L);
994650d1881Schristos #ifdef USE_KQUEUE
995650d1881Schristos 	EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0);
996650d1881Schristos 	n = kevent(kq, &kv, 1, &kv, 1, &timeout);
997650d1881Schristos #else
998650d1881Schristos 	FD_ZERO(&dsmask);
999650d1881Schristos 	FD_SET(s, &dsmask);
10002b237084Schristos 	n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
1001650d1881Schristos #endif
1002d73eb73dSchristos #else
1003d73eb73dSchristos 	timeout = evSubTime(finish, now);
1004d73eb73dSchristos 	if (timeout.tv_sec < 0)
1005a8d19c80Schristos 		timeout = evConsTime((time_t)0, 0L);
1006461a86f9Schristos 	polltimeout = 1000*(int)timeout.tv_sec +
1007461a86f9Schristos 		(int)timeout.tv_nsec/1000000;
1008d73eb73dSchristos 	pollfd.fd = s;
1009d73eb73dSchristos 	pollfd.events = POLLRDNORM;
1010d73eb73dSchristos 	n = poll(&pollfd, 1, polltimeout);
1011d73eb73dSchristos #endif /* USE_POLL */
1012d73eb73dSchristos 
10132b237084Schristos 	if (n == 0) {
10142b237084Schristos 		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
10152b237084Schristos 		*gotsomewhere = 1;
10162b237084Schristos 		return (0);
10172b237084Schristos 	}
10182b237084Schristos 	if (n < 0) {
1019650d1881Schristos #if defined(USE_POLL)
1020650d1881Schristos 		static const char *fun = "poll";
1021650d1881Schristos #elif defined(USE_SELECT)
1022650d1881Schristos 		static const char *fun = "select";
1023650d1881Schristos #elif defined(USE_KQUEUE)
1024650d1881Schristos 		static const char *fun = "kevent";
1025650d1881Schristos #endif
10262b237084Schristos 		if (errno == EINTR)
10272b237084Schristos 			goto wait;
1028650d1881Schristos 		Perror(statp, stderr, fun, errno);
10292b237084Schristos 		res_nclose(statp);
10302b237084Schristos 		return (0);
10312b237084Schristos 	}
1032650d1881Schristos #ifdef USE_KQUEUE
1033650d1881Schristos 	if ((int)kv.ident != s)
1034650d1881Schristos 		goto wait;
1035650d1881Schristos #endif
10362b237084Schristos 	errno = 0;
10372b237084Schristos 	fromlen = sizeof(from);
10381ad5eecbSchristos 	resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
10391ad5eecbSchristos 			   (struct sockaddr *)(void *)&from, &fromlen);
10402b237084Schristos 	if (resplen <= 0) {
10412b237084Schristos 		Perror(statp, stderr, "recvfrom", errno);
10422b237084Schristos 		res_nclose(statp);
10432b237084Schristos 		return (0);
10442b237084Schristos 	}
10452b237084Schristos 	*gotsomewhere = 1;
10462b237084Schristos 	if (resplen < HFIXEDSZ) {
10472b237084Schristos 		/*
10482b237084Schristos 		 * Undersized message.
10492b237084Schristos 		 */
10502b237084Schristos 		Dprint(statp->options & RES_DEBUG,
1051c5e820caSchristos 		       (stdout, ";; undersized: %zd\n",
10522b237084Schristos 			resplen));
10532b237084Schristos 		*terrno = EMSGSIZE;
10542b237084Schristos 		res_nclose(statp);
10552b237084Schristos 		return (0);
10562b237084Schristos 	}
10572b237084Schristos 	if (hp->id != anhp->id) {
10582b237084Schristos 		/*
10592b237084Schristos 		 * response from old query, ignore it.
10602b237084Schristos 		 * XXX - potential security hazard could
10612b237084Schristos 		 *	 be detected here.
10622b237084Schristos 		 */
10632b237084Schristos 		DprintQ((statp->options & RES_DEBUG) ||
10642b237084Schristos 			(statp->pfcode & RES_PRF_REPLY),
10652b237084Schristos 			(stdout, ";; old answer:\n"),
10662b237084Schristos 			ans, (resplen > anssiz) ? anssiz : resplen);
10672b237084Schristos 		goto wait;
10682b237084Schristos 	}
10692b237084Schristos 	if (!(statp->options & RES_INSECURE1) &&
10701ad5eecbSchristos 	    !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
10712b237084Schristos 		/*
10722b237084Schristos 		 * response from wrong server? ignore it.
10732b237084Schristos 		 * XXX - potential security hazard could
10742b237084Schristos 		 *	 be detected here.
10752b237084Schristos 		 */
10762b237084Schristos 		DprintQ((statp->options & RES_DEBUG) ||
10772b237084Schristos 			(statp->pfcode & RES_PRF_REPLY),
10782b237084Schristos 			(stdout, ";; not our server:\n"),
10792b237084Schristos 			ans, (resplen > anssiz) ? anssiz : resplen);
10802b237084Schristos 		goto wait;
10812b237084Schristos 	}
10822b237084Schristos #ifdef RES_USE_EDNS0
10832b237084Schristos 	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
10842b237084Schristos 		/*
10852b237084Schristos 		 * Do not retry if the server do not understand EDNS0.
10862b237084Schristos 		 * The case has to be captured here, as FORMERR packet do not
10872b237084Schristos 		 * carry query section, hence res_queriesmatch() returns 0.
10882b237084Schristos 		 */
10892b237084Schristos 		DprintQ(statp->options & RES_DEBUG,
10902b237084Schristos 			(stdout, "server rejected query with EDNS0:\n"),
10912b237084Schristos 			ans, (resplen > anssiz) ? anssiz : resplen);
10922b237084Schristos 		/* record the error */
10932b237084Schristos 		statp->_flags |= RES_F_EDNS0ERR;
10942b237084Schristos 		res_nclose(statp);
10952b237084Schristos 		return (0);
10962b237084Schristos 	}
10972b237084Schristos #endif
10982b237084Schristos 	if (!(statp->options & RES_INSECURE2) &&
109972e5329bSchristos 	    !res_queriesmatch(buf, (const u_char *)buf + buflen,
11002b237084Schristos 			      ans, ans + anssiz)) {
11012b237084Schristos 		/*
11022b237084Schristos 		 * response contains wrong query? ignore it.
11032b237084Schristos 		 * XXX - potential security hazard could
11042b237084Schristos 		 *	 be detected here.
11052b237084Schristos 		 */
11062b237084Schristos 		DprintQ((statp->options & RES_DEBUG) ||
11072b237084Schristos 			(statp->pfcode & RES_PRF_REPLY),
11082b237084Schristos 			(stdout, ";; wrong query name:\n"),
1109c5e820caSchristos 			ans, (int)(resplen > anssiz) ? anssiz : resplen);
11102b237084Schristos 		goto wait;
11112b237084Schristos 	}
11122b237084Schristos 	if (anhp->rcode == SERVFAIL ||
11132b237084Schristos 	    anhp->rcode == NOTIMP ||
11142b237084Schristos 	    anhp->rcode == REFUSED) {
11152b237084Schristos 		DprintQ(statp->options & RES_DEBUG,
11162b237084Schristos 			(stdout, "server rejected query:\n"),
1117c5e820caSchristos 			ans, (int)(resplen > anssiz) ? anssiz : resplen);
11182b237084Schristos 		res_nclose(statp);
11192b237084Schristos 		/* don't retry if called from dig */
11202b237084Schristos 		if (!statp->pfcode)
11212b237084Schristos 			return (0);
11222b237084Schristos 	}
11232b237084Schristos 	if (!(statp->options & RES_IGNTC) && anhp->tc) {
11242b237084Schristos 		/*
11252b237084Schristos 		 * To get the rest of answer,
11262b237084Schristos 		 * use TCP with same server.
11272b237084Schristos 		 */
11282b237084Schristos 		Dprint(statp->options & RES_DEBUG,
11292b237084Schristos 		       (stdout, ";; truncated answer\n"));
11302b237084Schristos 		*v_circuit = 1;
11312b237084Schristos 		res_nclose(statp);
11322b237084Schristos 		return (1);
11332b237084Schristos 	}
11342b237084Schristos 	/*
11352b237084Schristos 	 * All is well, or the error is fatal.  Signal that the
11362b237084Schristos 	 * next nameserver ought not be tried.
11372b237084Schristos 	 */
1138c5e820caSchristos 	_DIAGASSERT(__type_fit(int, resplen));
1139c5e820caSchristos 	return (int)resplen;
11402b237084Schristos }
11412b237084Schristos 
11422b237084Schristos static void
Aerror(const res_state statp,FILE * file,const char * string,int error,const struct sockaddr * address,socklen_t alen)11432b237084Schristos Aerror(const res_state statp, FILE *file, const char *string, int error,
114472e5329bSchristos        const struct sockaddr *address, socklen_t alen)
11452b237084Schristos {
11462b237084Schristos 	int save = errno;
11472b237084Schristos 	char hbuf[NI_MAXHOST];
11482b237084Schristos 	char sbuf[NI_MAXSERV];
11492b237084Schristos 
11502b237084Schristos 	if ((statp->options & RES_DEBUG) != 0U) {
115172e5329bSchristos 		if (getnameinfo(address, alen, hbuf,
1152c5e820caSchristos 		    (socklen_t)sizeof(hbuf), sbuf, (socklen_t)sizeof(sbuf),
1153c5e820caSchristos 		    niflags)) {
11542b237084Schristos 			strncpy(hbuf, "?", sizeof(hbuf) - 1);
11552b237084Schristos 			hbuf[sizeof(hbuf) - 1] = '\0';
11562b237084Schristos 			strncpy(sbuf, "?", sizeof(sbuf) - 1);
11572b237084Schristos 			sbuf[sizeof(sbuf) - 1] = '\0';
11582b237084Schristos 		}
11592b237084Schristos 		fprintf(file, "res_send: %s ([%s].%s): %s\n",
11602b237084Schristos 			string, hbuf, sbuf, strerror(error));
11612b237084Schristos 	}
11622b237084Schristos 	errno = save;
11632b237084Schristos }
11642b237084Schristos 
11652b237084Schristos static void
Perror(const res_state statp,FILE * file,const char * string,int error)11662b237084Schristos Perror(const res_state statp, FILE *file, const char *string, int error) {
11672b237084Schristos 	int save = errno;
11682b237084Schristos 
11692b237084Schristos 	if ((statp->options & RES_DEBUG) != 0U)
11702b237084Schristos 		fprintf(file, "res_send: %s: %s\n",
11712b237084Schristos 			string, strerror(error));
11722b237084Schristos 	errno = save;
11732b237084Schristos }
11742b237084Schristos 
11752b237084Schristos static int
sock_eq(struct sockaddr * a,struct sockaddr * b)11762b237084Schristos sock_eq(struct sockaddr *a, struct sockaddr *b) {
11772b237084Schristos 	struct sockaddr_in *a4, *b4;
11782b237084Schristos 	struct sockaddr_in6 *a6, *b6;
11792b237084Schristos 
11802b237084Schristos 	if (a->sa_family != b->sa_family)
11812b237084Schristos 		return 0;
11822b237084Schristos 	switch (a->sa_family) {
11832b237084Schristos 	case AF_INET:
11841ad5eecbSchristos 		a4 = (struct sockaddr_in *)(void *)a;
11851ad5eecbSchristos 		b4 = (struct sockaddr_in *)(void *)b;
11862b237084Schristos 		return a4->sin_port == b4->sin_port &&
11872b237084Schristos 		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
11882b237084Schristos 	case AF_INET6:
11891ad5eecbSchristos 		a6 = (struct sockaddr_in6 *)(void *)a;
11901ad5eecbSchristos 		b6 = (struct sockaddr_in6 *)(void *)b;
11912b237084Schristos 		return a6->sin6_port == b6->sin6_port &&
11922b237084Schristos #ifdef HAVE_SIN6_SCOPE_ID
11932b237084Schristos 		    a6->sin6_scope_id == b6->sin6_scope_id &&
11942b237084Schristos #endif
11952b237084Schristos 		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
11962b237084Schristos 	default:
11972b237084Schristos 		return 0;
11982b237084Schristos 	}
11992b237084Schristos }
12002b237084Schristos 
1201650d1881Schristos #if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
12022b237084Schristos /* XXX needs to move to the porting library. */
12032b237084Schristos static int
pselect(int nfds,void * rfds,void * wfds,void * efds,struct timespec * tsp,const sigset_t * sigmask)12042b237084Schristos pselect(int nfds, void *rfds, void *wfds, void *efds,
12052b237084Schristos 	struct timespec *tsp, const sigset_t *sigmask)
12062b237084Schristos {
12072b237084Schristos 	struct timeval tv, *tvp;
12082b237084Schristos 	sigset_t sigs;
12092b237084Schristos 	int n;
12102b237084Schristos 
12112b237084Schristos 	if (tsp) {
12122b237084Schristos 		tvp = &tv;
12132b237084Schristos 		tv = evTimeVal(*tsp);
12142b237084Schristos 	} else
12152b237084Schristos 		tvp = NULL;
12162b237084Schristos 	if (sigmask)
12172b237084Schristos 		sigprocmask(SIG_SETMASK, sigmask, &sigs);
12182b237084Schristos 	n = select(nfds, rfds, wfds, efds, tvp);
12192b237084Schristos 	if (sigmask)
12202b237084Schristos 		sigprocmask(SIG_SETMASK, &sigs, NULL);
12212b237084Schristos 	if (tsp)
12222b237084Schristos 		*tsp = evTimeSpec(tv);
12232b237084Schristos 	return (n);
12242b237084Schristos }
12252b237084Schristos #endif
1226