1/*	$NetBSD: res_send.c,v 1.21 2011/02/09 09:46:59 pooka Exp $	*/
2
3/*
4 * Portions Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1996-2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/*
21 * Copyright (c) 1985, 1989, 1993
22 *    The Regents of the University of California.  All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 * 1. Redistributions of source code must retain the above copyright
28 *    notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 *    notice, this list of conditions and the following disclaimer in the
31 *    documentation and/or other materials provided with the distribution.
32 * 3. All advertising materials mentioning features or use of this software
33 *    must display the following acknowledgement:
34 * 	This product includes software developed by the University of
35 * 	California, Berkeley and its contributors.
36 * 4. Neither the name of the University nor the names of its contributors
37 *    may be used to endorse or promote products derived from this software
38 *    without specific prior written permission.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 */
52
53/*
54 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
55 *
56 * Permission to use, copy, modify, and distribute this software for any
57 * purpose with or without fee is hereby granted, provided that the above
58 * copyright notice and this permission notice appear in all copies, and that
59 * the name of Digital Equipment Corporation not be used in advertising or
60 * publicity pertaining to distribution of the document or software without
61 * specific, written prior permission.
62 *
63 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
64 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
65 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
66 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
67 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
68 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
69 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
70 * SOFTWARE.
71 */
72
73/*
74 * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
75 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
76 *
77 * Permission to use, copy, modify, and distribute this software for any
78 * purpose with or without fee is hereby granted, provided that the above
79 * copyright notice and this permission notice appear in all copies.
80 *
81 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
82 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
83 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
84 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
85 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
86 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
87 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
88 */
89
90#include <sys/cdefs.h>
91#if defined(LIBC_SCCS) && !defined(lint)
92#ifdef notdef
93static const char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
94static const char rcsid[] = "Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp";
95#else
96__RCSID("$NetBSD: res_send.c,v 1.21 2011/02/09 09:46:59 pooka Exp $");
97#endif
98#endif /* LIBC_SCCS and not lint */
99
100/*! \file
101 * \brief
102 * Send query to name server and wait for reply.
103 */
104
105#include "namespace.h"
106#include "port_before.h"
107#include "fd_setsize.h"
108
109#include <sys/types.h>
110#include <sys/param.h>
111#include <sys/time.h>
112#include <sys/socket.h>
113#include <sys/uio.h>
114
115#include <netinet/in.h>
116#include <arpa/nameser.h>
117#include <arpa/inet.h>
118
119#include <errno.h>
120#include <netdb.h>
121#include <resolv.h>
122#include <signal.h>
123#include <stdio.h>
124#include <stdlib.h>
125#include <string.h>
126#include <unistd.h>
127
128#include <isc/eventlib.h>
129
130#include "port_after.h"
131
132#if 0
133#ifdef __weak_alias
134__weak_alias(res_ourserver_p,__res_ourserver_p)
135__weak_alias(res_nameinquery,__res_nameinquery)
136__weak_alias(res_queriesmatch,__res_queriesmatch)
137__weak_alias(res_nsend,__res_nsend)
138#endif
139#endif
140
141
142#ifdef USE_POLL
143#ifdef HAVE_STROPTS_H
144#include <stropts.h>
145#endif
146#include <poll.h>
147#endif /* USE_POLL */
148
149/* Options.  Leave them on. */
150#ifndef DEBUG
151#define DEBUG
152#endif
153#include "res_debug.h"
154#include "res_private.h"
155
156#define EXT(res) ((res)->_u._ext)
157
158#ifndef USE_POLL
159static const int highestFD = FD_SETSIZE - 1;
160#endif
161
162/* Forward. */
163
164static int		get_salen __P((const struct sockaddr *));
165static struct sockaddr * get_nsaddr __P((res_state, size_t));
166static int		send_vc(res_state, const u_char *, int,
167				u_char *, int, int *, int);
168static int		send_dg(res_state, const u_char *, int,
169				u_char *, int, int *, int, int,
170				int *, int *);
171static void		Aerror(const res_state, FILE *, const char *, int,
172			       const struct sockaddr *, int);
173static void		Perror(const res_state, FILE *, const char *, int);
174static int		sock_eq(struct sockaddr *, struct sockaddr *);
175#if defined(NEED_PSELECT) && !defined(USE_POLL)
176static int		pselect(int, void *, void *, void *,
177				struct timespec *,
178				const sigset_t *);
179#endif
180void res_pquery(const res_state, const u_char *, int, FILE *);
181
182static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
183
184/* Public. */
185
186/*%
187 *	looks up "ina" in _res.ns_addr_list[]
188 *
189 * returns:
190 *\li	0  : not found
191 *\li	>0 : found
192 *
193 * author:
194 *\li	paul vixie, 29may94
195 */
196int
197res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
198	const struct sockaddr_in *inp, *srv;
199	const struct sockaddr_in6 *in6p, *srv6;
200	int ns;
201
202	switch (sa->sa_family) {
203	case AF_INET:
204		inp = (const struct sockaddr_in *)(const void *)sa;
205		for (ns = 0;  ns < statp->nscount;  ns++) {
206			srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
207			if (srv->sin_family == inp->sin_family &&
208			    srv->sin_port == inp->sin_port &&
209			    (srv->sin_addr.s_addr == INADDR_ANY ||
210			     srv->sin_addr.s_addr == inp->sin_addr.s_addr))
211				return (1);
212		}
213		break;
214	case AF_INET6:
215		if (EXT(statp).ext == NULL)
216			break;
217		in6p = (const struct sockaddr_in6 *)(const void *)sa;
218		for (ns = 0;  ns < statp->nscount;  ns++) {
219			srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
220			if (srv6->sin6_family == in6p->sin6_family &&
221			    srv6->sin6_port == in6p->sin6_port &&
222#ifdef HAVE_SIN6_SCOPE_ID
223			    (srv6->sin6_scope_id == 0 ||
224			     srv6->sin6_scope_id == in6p->sin6_scope_id) &&
225#endif
226			    (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
227			     IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
228				return (1);
229		}
230		break;
231	default:
232		break;
233	}
234	return (0);
235}
236
237/*%
238 *	look for (name,type,class) in the query section of packet (buf,eom)
239 *
240 * requires:
241 *\li	buf + HFIXEDSZ <= eom
242 *
243 * returns:
244 *\li	-1 : format error
245 *\li	0  : not found
246 *\li	>0 : found
247 *
248 * author:
249 *\li	paul vixie, 29may94
250 */
251int
252res_nameinquery(const char *name, int type, int class,
253		const u_char *buf, const u_char *eom)
254{
255	const u_char *cp = buf + HFIXEDSZ;
256	int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
257
258	while (qdcount-- > 0) {
259		char tname[MAXDNAME+1];
260		int n, ttype, tclass;
261
262		n = dn_expand(buf, eom, cp, tname, sizeof tname);
263		if (n < 0)
264			return (-1);
265		cp += n;
266		if (cp + 2 * INT16SZ > eom)
267			return (-1);
268		ttype = ns_get16(cp); cp += INT16SZ;
269		tclass = ns_get16(cp); cp += INT16SZ;
270		if (ttype == type && tclass == class &&
271		    ns_samename(tname, name) == 1)
272			return (1);
273	}
274	return (0);
275}
276
277/*%
278 *	is there a 1:1 mapping of (name,type,class)
279 *	in (buf1,eom1) and (buf2,eom2)?
280 *
281 * returns:
282 *\li	-1 : format error
283 *\li	0  : not a 1:1 mapping
284 *\li	>0 : is a 1:1 mapping
285 *
286 * author:
287 *\li	paul vixie, 29may94
288 */
289int
290res_queriesmatch(const u_char *buf1, const u_char *eom1,
291		 const u_char *buf2, const u_char *eom2)
292{
293	const u_char *cp = buf1 + HFIXEDSZ;
294	int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
295
296	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
297		return (-1);
298
299	/*
300	 * Only header section present in replies to
301	 * dynamic update packets.
302	 */
303	if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
304	    (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
305		return (1);
306
307	if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
308		return (0);
309	while (qdcount-- > 0) {
310		char tname[MAXDNAME+1];
311		int n, ttype, tclass;
312
313		n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
314		if (n < 0)
315			return (-1);
316		cp += n;
317		if (cp + 2 * INT16SZ > eom1)
318			return (-1);
319		ttype = ns_get16(cp);	cp += INT16SZ;
320		tclass = ns_get16(cp); cp += INT16SZ;
321		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
322			return (0);
323	}
324	return (1);
325}
326
327int
328res_nsend(res_state statp,
329	  const u_char *buf, int buflen, u_char *ans, int anssiz)
330{
331	int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
332	char abuf[NI_MAXHOST];
333
334	(void)res_check(statp, NULL);
335
336	/* No name servers or res_init() failure */
337	if (statp->nscount == 0 || EXT(statp).ext == NULL) {
338		errno = ESRCH;
339		return (-1);
340	}
341	if (anssiz < HFIXEDSZ) {
342		errno = EINVAL;
343		return (-1);
344	}
345	DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
346		(stdout, ";; res_send()\n"), buf, buflen);
347	v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
348	gotsomewhere = 0;
349	terrno = ETIMEDOUT;
350
351	/*
352	 * If the ns_addr_list in the resolver context has changed, then
353	 * invalidate our cached copy and the associated timing data.
354	 */
355	if (EXT(statp).nscount != 0) {
356		int needclose = 0;
357		struct sockaddr_storage peer;
358		ISC_SOCKLEN_T peerlen;
359
360		if (EXT(statp).nscount != statp->nscount)
361			needclose++;
362		else
363			for (ns = 0; ns < statp->nscount; ns++) {
364				if (statp->nsaddr_list[ns].sin_family &&
365				    !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
366					     (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
367					needclose++;
368					break;
369				}
370
371				if (EXT(statp).nssocks[ns] == -1)
372					continue;
373				peerlen = sizeof(peer);
374				if (getpeername(EXT(statp).nssocks[ns],
375				    (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
376					needclose++;
377					break;
378				}
379				if (!sock_eq((struct sockaddr *)(void *)&peer,
380				    get_nsaddr(statp, (size_t)ns))) {
381					needclose++;
382					break;
383				}
384			}
385		if (needclose) {
386			res_nclose(statp);
387			EXT(statp).nscount = 0;
388		}
389	}
390
391	/*
392	 * Maybe initialize our private copy of the ns_addr_list.
393	 */
394	if (EXT(statp).nscount == 0) {
395		for (ns = 0; ns < statp->nscount; ns++) {
396			EXT(statp).nstimes[ns] = RES_MAXTIME;
397			EXT(statp).nssocks[ns] = -1;
398			if (!statp->nsaddr_list[ns].sin_family)
399				continue;
400			EXT(statp).ext->nsaddrs[ns].sin =
401				 statp->nsaddr_list[ns];
402		}
403		EXT(statp).nscount = statp->nscount;
404	}
405
406	/*
407	 * Some resolvers want to even out the load on their nameservers.
408	 * Note that RES_BLAST overrides RES_ROTATE.
409	 */
410	if ((statp->options & RES_ROTATE) != 0U &&
411	    (statp->options & RES_BLAST) == 0U) {
412		union res_sockaddr_union inu;
413		struct sockaddr_in ina;
414		int lastns = statp->nscount - 1;
415		int fd;
416		u_int16_t nstime;
417
418		if (EXT(statp).ext != NULL)
419			inu = EXT(statp).ext->nsaddrs[0];
420		ina = statp->nsaddr_list[0];
421		fd = EXT(statp).nssocks[0];
422		nstime = EXT(statp).nstimes[0];
423		for (ns = 0; ns < lastns; ns++) {
424			if (EXT(statp).ext != NULL)
425				EXT(statp).ext->nsaddrs[ns] =
426					EXT(statp).ext->nsaddrs[ns + 1];
427			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
428			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
429			EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
430		}
431		if (EXT(statp).ext != NULL)
432			EXT(statp).ext->nsaddrs[lastns] = inu;
433		statp->nsaddr_list[lastns] = ina;
434		EXT(statp).nssocks[lastns] = fd;
435		EXT(statp).nstimes[lastns] = nstime;
436	}
437
438	/*
439	 * Send request, RETRY times, or until successful.
440	 */
441	for (tries = 0; tries < statp->retry; tries++) {
442	    for (ns = 0; ns < statp->nscount; ns++) {
443		struct sockaddr *nsap;
444		int nsaplen;
445		nsap = get_nsaddr(statp, (size_t)ns);
446		nsaplen = get_salen(nsap);
447		statp->_flags &= ~RES_F_LASTMASK;
448		statp->_flags |= (ns << RES_F_LASTSHIFT);
449 same_ns:
450		if (statp->qhook) {
451			int done = 0, loops = 0;
452
453			do {
454				res_sendhookact act;
455
456				act = (*statp->qhook)(&nsap, &buf, &buflen,
457						      ans, anssiz, &resplen);
458				switch (act) {
459				case res_goahead:
460					done = 1;
461					break;
462				case res_nextns:
463					res_nclose(statp);
464					goto next_ns;
465				case res_done:
466					return (resplen);
467				case res_modified:
468					/* give the hook another try */
469					if (++loops < 42) /*doug adams*/
470						break;
471					/*FALLTHROUGH*/
472				case res_error:
473					/*FALLTHROUGH*/
474				default:
475					goto fail;
476				}
477			} while (!done);
478		}
479
480		Dprint(((statp->options & RES_DEBUG) &&
481			getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
482				    NULL, 0, niflags) == 0),
483		       (stdout, ";; Querying server (# %d) address = %s\n",
484			ns + 1, abuf));
485
486
487		if (v_circuit) {
488			/* Use VC; at most one attempt per server. */
489			tries = statp->retry;
490			n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
491				    ns);
492			if (n < 0)
493				goto fail;
494			if (n == 0)
495				goto next_ns;
496			resplen = n;
497		} else {
498			/* Use datagrams. */
499			n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
500				    ns, tries, &v_circuit, &gotsomewhere);
501			if (n < 0)
502				goto fail;
503			if (n == 0)
504				goto next_ns;
505			if (v_circuit)
506				goto same_ns;
507			resplen = n;
508		}
509
510		Dprint((statp->options & RES_DEBUG) ||
511		       ((statp->pfcode & RES_PRF_REPLY) &&
512			(statp->pfcode & RES_PRF_HEAD1)),
513		       (stdout, ";; got answer:\n"));
514
515		DprintQ((statp->options & RES_DEBUG) ||
516			(statp->pfcode & RES_PRF_REPLY),
517			(stdout, "%s", ""),
518			ans, (resplen > anssiz) ? anssiz : resplen);
519
520		/*
521		 * If we have temporarily opened a virtual circuit,
522		 * or if we haven't been asked to keep a socket open,
523		 * close the socket.
524		 */
525		if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
526		    (statp->options & RES_STAYOPEN) == 0U) {
527			res_nclose(statp);
528		}
529		if (statp->rhook) {
530			int done = 0, loops = 0;
531
532			do {
533				res_sendhookact act;
534
535				act = (*statp->rhook)(nsap, buf, buflen,
536						      ans, anssiz, &resplen);
537				switch (act) {
538				case res_goahead:
539				case res_done:
540					done = 1;
541					break;
542				case res_nextns:
543					res_nclose(statp);
544					goto next_ns;
545				case res_modified:
546					/* give the hook another try */
547					if (++loops < 42) /*doug adams*/
548						break;
549					/*FALLTHROUGH*/
550				case res_error:
551					/*FALLTHROUGH*/
552				default:
553					goto fail;
554				}
555			} while (!done);
556
557		}
558		return (resplen);
559 next_ns: ;
560	   } /*foreach ns*/
561	} /*foreach retry*/
562	res_nclose(statp);
563	if (!v_circuit) {
564		if (!gotsomewhere)
565			errno = ECONNREFUSED;	/*%< no nameservers found */
566		else
567			errno = ETIMEDOUT;	/*%< no answer obtained */
568	} else
569		errno = terrno;
570	return (-1);
571 fail:
572	res_nclose(statp);
573	return (-1);
574}
575
576/* Private */
577
578static int
579get_salen(sa)
580	const struct sockaddr *sa;
581{
582
583#ifdef HAVE_SA_LEN
584	/* There are people do not set sa_len.  Be forgiving to them. */
585	if (sa->sa_len)
586		return (sa->sa_len);
587#endif
588
589	if (sa->sa_family == AF_INET)
590		return (sizeof(struct sockaddr_in));
591	else if (sa->sa_family == AF_INET6)
592		return (sizeof(struct sockaddr_in6));
593	else
594		return (0);	/*%< unknown, die on connect */
595}
596
597/*%
598 * pick appropriate nsaddr_list for use.  see res_init() for initialization.
599 */
600static struct sockaddr *
601get_nsaddr(statp, n)
602	res_state statp;
603	size_t n;
604{
605
606	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
607		/*
608		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
609		 *   than struct sockaddr, and
610		 * - user code did not update statp->nsaddr_list[n].
611		 */
612		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
613	} else {
614		/*
615		 * - user code updated statp->nsaddr_list[n], or
616		 * - statp->nsaddr_list[n] has the same content as
617		 *   EXT(statp).ext->nsaddrs[n].
618		 */
619		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
620	}
621}
622
623static int
624send_vc(res_state statp,
625	const u_char *buf, int buflen, u_char *ans, int anssiz,
626	int *terrno, int ns)
627{
628	const HEADER *hp = (const HEADER *)(const void *)buf;
629	HEADER *anhp = (HEADER *)(void *)ans;
630	struct sockaddr *nsap;
631	int nsaplen;
632	int truncating, connreset, resplen, n;
633	struct iovec iov[2];
634	u_short len;
635	u_char *cp;
636	void *tmp;
637#ifdef SO_NOSIGPIPE
638	int on = 1;
639#endif
640
641	nsap = get_nsaddr(statp, (size_t)ns);
642	nsaplen = get_salen(nsap);
643
644	connreset = 0;
645 same_ns:
646	truncating = 0;
647
648	/* Are we still talking to whom we want to talk to? */
649	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
650		struct sockaddr_storage peer;
651		ISC_SOCKLEN_T size = sizeof peer;
652
653		if (getpeername(statp->_vcsock,
654				(struct sockaddr *)(void *)&peer, &size) < 0 ||
655		    !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
656			res_nclose(statp);
657			statp->_flags &= ~RES_F_VC;
658		}
659	}
660
661	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
662		if (statp->_vcsock >= 0)
663			res_nclose(statp);
664
665		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
666#ifndef USE_POLL
667		if (statp->_vcsock > highestFD) {
668			res_nclose(statp);
669			errno = ENOTSOCK;
670		}
671#endif
672		if (statp->_vcsock < 0) {
673			switch (errno) {
674			case EPROTONOSUPPORT:
675#ifdef EPFNOSUPPORT
676			case EPFNOSUPPORT:
677#endif
678			case EAFNOSUPPORT:
679				Perror(statp, stderr, "socket(vc)", errno);
680				return (0);
681			default:
682				*terrno = errno;
683				Perror(statp, stderr, "socket(vc)", errno);
684				return (-1);
685			}
686		}
687#ifdef SO_NOSIGPIPE
688		/*
689		 * Disable generation of SIGPIPE when writing to a closed
690		 * socket.  Write should return -1 and set errno to EPIPE
691		 * instead.
692		 *
693		 * Push on even if setsockopt(SO_NOSIGPIPE) fails.
694		 */
695		(void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
696				 sizeof(on));
697#endif
698		errno = 0;
699		if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
700			*terrno = errno;
701			Aerror(statp, stderr, "connect/vc", errno, nsap,
702			    nsaplen);
703			res_nclose(statp);
704			return (0);
705		}
706		statp->_flags |= RES_F_VC;
707	}
708
709	/*
710	 * Send length & message
711	 */
712	ns_put16((u_short)buflen, (u_char*)(void *)&len);
713	iov[0] = evConsIovec(&len, INT16SZ);
714	DE_CONST(buf, tmp);
715	iov[1] = evConsIovec(tmp, (size_t)buflen);
716	if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
717		*terrno = errno;
718		Perror(statp, stderr, "write failed", errno);
719		res_nclose(statp);
720		return (0);
721	}
722	/*
723	 * Receive length & response
724	 */
725 read_len:
726	cp = ans;
727	len = INT16SZ;
728	while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
729		cp += n;
730		if ((len -= n) == 0)
731			break;
732	}
733	if (n <= 0) {
734		*terrno = errno;
735		Perror(statp, stderr, "read failed", errno);
736		res_nclose(statp);
737		/*
738		 * A long running process might get its TCP
739		 * connection reset if the remote server was
740		 * restarted.  Requery the server instead of
741		 * trying a new one.  When there is only one
742		 * server, this means that a query might work
743		 * instead of failing.  We only allow one reset
744		 * per query to prevent looping.
745		 */
746		if (*terrno == ECONNRESET && !connreset) {
747			connreset = 1;
748			res_nclose(statp);
749			goto same_ns;
750		}
751		res_nclose(statp);
752		return (0);
753	}
754	resplen = ns_get16(ans);
755	if (resplen > anssiz) {
756		Dprint(statp->options & RES_DEBUG,
757		       (stdout, ";; response truncated\n")
758		       );
759		truncating = 1;
760		len = anssiz;
761	} else
762		len = resplen;
763	if (len < HFIXEDSZ) {
764		/*
765		 * Undersized message.
766		 */
767		Dprint(statp->options & RES_DEBUG,
768		       (stdout, ";; undersized: %d\n", len));
769		*terrno = EMSGSIZE;
770		res_nclose(statp);
771		return (0);
772	}
773	cp = ans;
774	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
775		cp += n;
776		len -= n;
777	}
778	if (n <= 0) {
779		*terrno = errno;
780		Perror(statp, stderr, "read(vc)", errno);
781		res_nclose(statp);
782		return (0);
783	}
784	if (truncating) {
785		/*
786		 * Flush rest of answer so connection stays in synch.
787		 */
788		anhp->tc = 1;
789		len = resplen - anssiz;
790		while (len != 0) {
791			char junk[PACKETSZ];
792
793			n = read(statp->_vcsock, junk,
794				 (len > sizeof junk) ? sizeof junk : len);
795			if (n > 0)
796				len -= n;
797			else
798				break;
799		}
800	}
801	/*
802	 * If the calling applicating has bailed out of
803	 * a previous call and failed to arrange to have
804	 * the circuit closed or the server has got
805	 * itself confused, then drop the packet and
806	 * wait for the correct one.
807	 */
808	if (hp->id != anhp->id) {
809		DprintQ((statp->options & RES_DEBUG) ||
810			(statp->pfcode & RES_PRF_REPLY),
811			(stdout, ";; old answer (unexpected):\n"),
812			ans, (resplen > anssiz) ? anssiz: resplen);
813		goto read_len;
814	}
815
816	/*
817	 * All is well, or the error is fatal.  Signal that the
818	 * next nameserver ought not be tried.
819	 */
820	return (resplen);
821}
822
823static int
824send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
825	int anssiz, int *terrno, int ns, int tries, int *v_circuit,
826	int *gotsomewhere)
827{
828	const HEADER *hp = (const HEADER *)(const void *)buf;
829	HEADER *anhp = (HEADER *)(void *)ans;
830	const struct sockaddr *nsap;
831	int nsaplen;
832	struct timespec now, timeout, finish;
833	struct sockaddr_storage from;
834	ISC_SOCKLEN_T fromlen;
835	int resplen, seconds, n, s;
836#ifdef USE_POLL
837	int     polltimeout;
838	struct pollfd   pollfd;
839#else
840	fd_set dsmask;
841#endif
842
843	nsap = get_nsaddr(statp, (size_t)ns);
844	nsaplen = get_salen(nsap);
845	if (EXT(statp).nssocks[ns] == -1) {
846		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
847#ifndef USE_POLL
848		if (EXT(statp).nssocks[ns] > highestFD) {
849			res_nclose(statp);
850			errno = ENOTSOCK;
851		}
852#endif
853		if (EXT(statp).nssocks[ns] < 0) {
854			switch (errno) {
855			case EPROTONOSUPPORT:
856#ifdef EPFNOSUPPORT
857			case EPFNOSUPPORT:
858#endif
859			case EAFNOSUPPORT:
860				Perror(statp, stderr, "socket(dg)", errno);
861				return (0);
862			default:
863				*terrno = errno;
864				Perror(statp, stderr, "socket(dg)", errno);
865				return (-1);
866			}
867		}
868#ifndef CANNOT_CONNECT_DGRAM
869		/*
870		 * On a 4.3BSD+ machine (client and server,
871		 * actually), sending to a nameserver datagram
872		 * port with no nameserver will cause an
873		 * ICMP port unreachable message to be returned.
874		 * If our datagram socket is "connected" to the
875		 * server, we get an ECONNREFUSED error on the next
876		 * socket operation, and select returns if the
877		 * error message is received.  We can thus detect
878		 * the absence of a nameserver without timing out.
879		 */
880		if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
881			Aerror(statp, stderr, "connect(dg)", errno, nsap,
882			    nsaplen);
883			res_nclose(statp);
884			return (0);
885		}
886#endif /* !CANNOT_CONNECT_DGRAM */
887		Dprint(statp->options & RES_DEBUG,
888		       (stdout, ";; new DG socket\n"))
889	}
890	s = EXT(statp).nssocks[ns];
891#ifndef CANNOT_CONNECT_DGRAM
892	if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
893		Perror(statp, stderr, "send", errno);
894		res_nclose(statp);
895		return (0);
896	}
897#else /* !CANNOT_CONNECT_DGRAM */
898	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
899	{
900		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
901		res_nclose(statp);
902		return (0);
903	}
904#endif /* !CANNOT_CONNECT_DGRAM */
905
906	/*
907	 * Wait for reply.
908	 */
909	seconds = (statp->retrans << tries);
910	if (ns > 0)
911		seconds /= statp->nscount;
912	if (seconds <= 0)
913		seconds = 1;
914	now = evNowTime();
915	timeout = evConsTime((long)seconds, 0L);
916	finish = evAddTime(now, timeout);
917	goto nonow;
918 wait:
919	now = evNowTime();
920 nonow:
921#ifndef USE_POLL
922	FD_ZERO(&dsmask);
923	FD_SET(s, &dsmask);
924	if (evCmpTime(finish, now) > 0)
925		timeout = evSubTime(finish, now);
926	else
927		timeout = evConsTime(0L, 0L);
928	n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
929#else
930	timeout = evSubTime(finish, now);
931	if (timeout.tv_sec < 0)
932		timeout = evConsTime(0L, 0L);
933	polltimeout = 1000*(int)timeout.tv_sec +
934		(int)timeout.tv_nsec/1000000;
935	pollfd.fd = s;
936	pollfd.events = POLLRDNORM;
937	n = poll(&pollfd, 1, polltimeout);
938#endif /* USE_POLL */
939
940	if (n == 0) {
941		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
942		*gotsomewhere = 1;
943		return (0);
944	}
945	if (n < 0) {
946		if (errno == EINTR)
947			goto wait;
948#ifndef USE_POLL
949		Perror(statp, stderr, "select", errno);
950#else
951		Perror(statp, stderr, "poll", errno);
952#endif /* USE_POLL */
953		res_nclose(statp);
954		return (0);
955	}
956	errno = 0;
957	fromlen = sizeof(from);
958	resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
959			   (struct sockaddr *)(void *)&from, &fromlen);
960	if (resplen <= 0) {
961		Perror(statp, stderr, "recvfrom", errno);
962		res_nclose(statp);
963		return (0);
964	}
965	*gotsomewhere = 1;
966	if (resplen < HFIXEDSZ) {
967		/*
968		 * Undersized message.
969		 */
970		Dprint(statp->options & RES_DEBUG,
971		       (stdout, ";; undersized: %d\n",
972			resplen));
973		*terrno = EMSGSIZE;
974		res_nclose(statp);
975		return (0);
976	}
977	if (hp->id != anhp->id) {
978		/*
979		 * response from old query, ignore it.
980		 * XXX - potential security hazard could
981		 *	 be detected here.
982		 */
983		DprintQ((statp->options & RES_DEBUG) ||
984			(statp->pfcode & RES_PRF_REPLY),
985			(stdout, ";; old answer:\n"),
986			ans, (resplen > anssiz) ? anssiz : resplen);
987		goto wait;
988	}
989	if (!(statp->options & RES_INSECURE1) &&
990	    !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
991		/*
992		 * response from wrong server? ignore it.
993		 * XXX - potential security hazard could
994		 *	 be detected here.
995		 */
996		DprintQ((statp->options & RES_DEBUG) ||
997			(statp->pfcode & RES_PRF_REPLY),
998			(stdout, ";; not our server:\n"),
999			ans, (resplen > anssiz) ? anssiz : resplen);
1000		goto wait;
1001	}
1002#ifdef RES_USE_EDNS0
1003	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1004		/*
1005		 * Do not retry if the server do not understand EDNS0.
1006		 * The case has to be captured here, as FORMERR packet do not
1007		 * carry query section, hence res_queriesmatch() returns 0.
1008		 */
1009		DprintQ(statp->options & RES_DEBUG,
1010			(stdout, "server rejected query with EDNS0:\n"),
1011			ans, (resplen > anssiz) ? anssiz : resplen);
1012		/* record the error */
1013		statp->_flags |= RES_F_EDNS0ERR;
1014		res_nclose(statp);
1015		return (0);
1016	}
1017#endif
1018	if (!(statp->options & RES_INSECURE2) &&
1019	    !res_queriesmatch(buf, buf + buflen,
1020			      ans, ans + anssiz)) {
1021		/*
1022		 * response contains wrong query? ignore it.
1023		 * XXX - potential security hazard could
1024		 *	 be detected here.
1025		 */
1026		DprintQ((statp->options & RES_DEBUG) ||
1027			(statp->pfcode & RES_PRF_REPLY),
1028			(stdout, ";; wrong query name:\n"),
1029			ans, (resplen > anssiz) ? anssiz : resplen);
1030		goto wait;
1031	}
1032	if (anhp->rcode == SERVFAIL ||
1033	    anhp->rcode == NOTIMP ||
1034	    anhp->rcode == REFUSED) {
1035		DprintQ(statp->options & RES_DEBUG,
1036			(stdout, "server rejected query:\n"),
1037			ans, (resplen > anssiz) ? anssiz : resplen);
1038		res_nclose(statp);
1039		/* don't retry if called from dig */
1040		if (!statp->pfcode)
1041			return (0);
1042	}
1043	if (!(statp->options & RES_IGNTC) && anhp->tc) {
1044		/*
1045		 * To get the rest of answer,
1046		 * use TCP with same server.
1047		 */
1048		Dprint(statp->options & RES_DEBUG,
1049		       (stdout, ";; truncated answer\n"));
1050		*v_circuit = 1;
1051		res_nclose(statp);
1052		return (1);
1053	}
1054	/*
1055	 * All is well, or the error is fatal.  Signal that the
1056	 * next nameserver ought not be tried.
1057	 */
1058	return (resplen);
1059}
1060
1061static void
1062Aerror(const res_state statp, FILE *file, const char *string, int error,
1063       const struct sockaddr *address, int alen)
1064{
1065	int save = errno;
1066	char hbuf[NI_MAXHOST];
1067	char sbuf[NI_MAXSERV];
1068
1069	if ((statp->options & RES_DEBUG) != 0U) {
1070		if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1071		    sbuf, sizeof(sbuf), niflags)) {
1072			strncpy(hbuf, "?", sizeof(hbuf) - 1);
1073			hbuf[sizeof(hbuf) - 1] = '\0';
1074			strncpy(sbuf, "?", sizeof(sbuf) - 1);
1075			sbuf[sizeof(sbuf) - 1] = '\0';
1076		}
1077		fprintf(file, "res_send: %s ([%s].%s): %s\n",
1078			string, hbuf, sbuf, strerror(error));
1079	}
1080	errno = save;
1081}
1082
1083static void
1084Perror(const res_state statp, FILE *file, const char *string, int error) {
1085	int save = errno;
1086
1087	if ((statp->options & RES_DEBUG) != 0U)
1088		fprintf(file, "res_send: %s: %s\n",
1089			string, strerror(error));
1090	errno = save;
1091}
1092
1093static int
1094sock_eq(struct sockaddr *a, struct sockaddr *b) {
1095	struct sockaddr_in *a4, *b4;
1096	struct sockaddr_in6 *a6, *b6;
1097
1098	if (a->sa_family != b->sa_family)
1099		return 0;
1100	switch (a->sa_family) {
1101	case AF_INET:
1102		a4 = (struct sockaddr_in *)(void *)a;
1103		b4 = (struct sockaddr_in *)(void *)b;
1104		return a4->sin_port == b4->sin_port &&
1105		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1106	case AF_INET6:
1107		a6 = (struct sockaddr_in6 *)(void *)a;
1108		b6 = (struct sockaddr_in6 *)(void *)b;
1109		return a6->sin6_port == b6->sin6_port &&
1110#ifdef HAVE_SIN6_SCOPE_ID
1111		    a6->sin6_scope_id == b6->sin6_scope_id &&
1112#endif
1113		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1114	default:
1115		return 0;
1116	}
1117}
1118
1119#if defined(NEED_PSELECT) && !defined(USE_POLL)
1120/* XXX needs to move to the porting library. */
1121static int
1122pselect(int nfds, void *rfds, void *wfds, void *efds,
1123	struct timespec *tsp, const sigset_t *sigmask)
1124{
1125	struct timeval tv, *tvp;
1126	sigset_t sigs;
1127	int n;
1128
1129	if (tsp) {
1130		tvp = &tv;
1131		tv = evTimeVal(*tsp);
1132	} else
1133		tvp = NULL;
1134	if (sigmask)
1135		sigprocmask(SIG_SETMASK, sigmask, &sigs);
1136	n = select(nfds, rfds, wfds, efds, tvp);
1137	if (sigmask)
1138		sigprocmask(SIG_SETMASK, &sigs, NULL);
1139	if (tsp)
1140		*tsp = evTimeSpec(tv);
1141	return (n);
1142}
1143#endif
1144