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