xref: /illumos-gate/usr/src/lib/libresolv2/common/resolv/res_send.c (revision f498645a3eecf2ddd304b4ea9c7f1b4c155ff79e)
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)
79 static const char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
80 static 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
130 static const int highestFD = FD_SETSIZE - 1;
131 #else
132 static int highestFD = 0;
133 #endif
134 
135 /* Forward. */
136 
137 static int		get_salen __P((const struct sockaddr *));
138 static struct sockaddr * get_nsaddr __P((res_state, size_t));
139 static int		send_vc(res_state, const u_char *, int,
140 				u_char *, int, int *, int);
141 static int		send_dg(res_state, const u_char *, int,
142 				u_char *, int, int *, int,
143 				int *, int *);
144 static void		Aerror(const res_state, FILE *, const char *, int,
145 			       const struct sockaddr *, int);
146 static void		Perror(const res_state, FILE *, const char *, int);
147 static int		sock_eq(struct sockaddr *, struct sockaddr *);
148 #ifdef NEED_PSELECT
149 static int		pselect(int, void *, void *, void *,
150 				struct timespec *,
151 				const sigset_t *);
152 #endif
153 void 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 
162 static 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  */
175 int
176 res_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  */
228 int
229 res_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  */
265 int
266 res_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 
303 int
304 res_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 
555 static int
556 get_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  */
577 static struct sockaddr *
578 get_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 
600 static int
601 send_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 
782 static int
783 send_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 
1006 static void
1007 Aerror(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 
1030 static void
1031 Perror(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 
1040 static int
1041 sock_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. */
1068 static int
1069 pselect(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