xref: /titanic_41/usr/src/lib/libresolv2/common/resolv/res_send.c (revision f8919bdadda3ebb97bd55cc14a16e0271ed57615)
1 /*
2  * Copyright 2007 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 	/* No name servers or previous res_ninit() failure */
315 	if (statp->nscount == 0 || EXT(statp).ext == NULL) {
316 		errno = ESRCH;
317 		return (-1);
318 	}
319 	if (anssiz < HFIXEDSZ) {
320 		errno = EINVAL;
321 		return (-1);
322 	}
323 	DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
324 		(stdout, ";; res_send()\n"), buf, buflen);
325 	v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
326 	gotsomewhere = 0;
327 	terrno = ETIMEDOUT;
328 
329 	/*
330 	 * If the ns_addr_list in the resolver context has changed, then
331 	 * invalidate our cached copy and the associated timing data.
332 	 */
333 	if (EXT(statp).nscount != 0) {
334 		int needclose = 0;
335 		struct sockaddr_storage peer;
336 		ISC_SOCKLEN_T peerlen;
337 
338 		if (EXT(statp).nscount != statp->nscount)
339 			needclose++;
340 		else
341 			for (ns = 0; ns < statp->nscount; ns++) {
342 				if (statp->nsaddr_list[ns].sin_family &&
343 				    !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns],
344 					     (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) {
345 					needclose++;
346 					break;
347 				}
348 
349 				if (EXT(statp).nssocks[ns] == -1)
350 					continue;
351 				peerlen = sizeof(peer);
352 				if (getsockname(EXT(statp).nssocks[ns],
353 				    (struct sockaddr *)&peer, &peerlen) < 0) {
354 					needclose++;
355 					break;
356 				}
357 				if (!sock_eq((struct sockaddr *)&peer,
358 				    get_nsaddr(statp, ns))) {
359 					needclose++;
360 					break;
361 				}
362 			}
363 		if (needclose) {
364 			res_nclose(statp);
365 			EXT(statp).nscount = 0;
366 		}
367 	}
368 
369 	/*
370 	 * Maybe initialize our private copy of the ns_addr_list.
371 	 */
372 	if (EXT(statp).nscount == 0) {
373 		for (ns = 0; ns < statp->nscount; ns++) {
374 			EXT(statp).nstimes[ns] = RES_MAXTIME;
375 			EXT(statp).nssocks[ns] = -1;
376 			if (!statp->nsaddr_list[ns].sin_family)
377 				continue;
378 			EXT(statp).ext->nsaddrs[ns].sin =
379 				 statp->nsaddr_list[ns];
380 		}
381 		EXT(statp).nscount = statp->nscount;
382 	}
383 
384 	/*
385 	 * Some resolvers want to even out the load on their nameservers.
386 	 * Note that RES_BLAST overrides RES_ROTATE.
387 	 */
388 	if ((statp->options & RES_ROTATE) != 0 &&
389 	    (statp->options & RES_BLAST) == 0) {
390 		union res_sockaddr_union inu;
391 		struct sockaddr_in ina;
392 		int lastns = statp->nscount - 1;
393 		int fd;
394 		u_int16_t nstime;
395 
396 		if (EXT(statp).ext != NULL)
397 			inu = EXT(statp).ext->nsaddrs[0];
398 		ina = statp->nsaddr_list[0];
399 		fd = EXT(statp).nssocks[0];
400 		nstime = EXT(statp).nstimes[0];
401 		for (ns = 0; ns < lastns; ns++) {
402 			if (EXT(statp).ext != NULL)
403                                 EXT(statp).ext->nsaddrs[ns] =
404 					EXT(statp).ext->nsaddrs[ns + 1];
405 			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
406 			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
407 			EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
408 		}
409 		if (EXT(statp).ext != NULL)
410 			EXT(statp).ext->nsaddrs[lastns] = inu;
411 		statp->nsaddr_list[lastns] = ina;
412 		EXT(statp).nssocks[lastns] = fd;
413 		EXT(statp).nstimes[lastns] = nstime;
414 	}
415 
416 	/*
417 	 * Send request, RETRY times, or until successful.
418 	 */
419 	for (try = 0; try < statp->retry; try++) {
420 	    for (ns = 0; ns < statp->nscount; ns++) {
421 		struct sockaddr *nsap;
422 		int nsaplen;
423 		nsap = get_nsaddr(statp, ns);
424 		nsaplen = get_salen(nsap);
425 		statp->_flags &= ~RES_F_LASTMASK;
426 		statp->_flags |= (ns << RES_F_LASTSHIFT);
427  same_ns:
428 		if (statp->qhook) {
429 			int done = 0, loops = 0;
430 
431 			do {
432 				res_sendhookact act;
433 
434 				act = (*statp->qhook)(&nsap, &buf, &buflen,
435 						      ans, anssiz, &resplen);
436 				switch (act) {
437 				case res_goahead:
438 					done = 1;
439 					break;
440 				case res_nextns:
441 					res_nclose(statp);
442 					goto next_ns;
443 				case res_done:
444 					return (resplen);
445 				case res_modified:
446 					/* give the hook another try */
447 					if (++loops < 42) /*doug adams*/
448 						break;
449 					/*FALLTHROUGH*/
450 				case res_error:
451 					/*FALLTHROUGH*/
452 				default:
453 					goto fail;
454 				}
455 			} while (!done);
456 		}
457 
458 		Dprint(((statp->options & RES_DEBUG) &&
459 			getnameinfo(nsap, nsaplen, abuf, sizeof(abuf),
460 				    NULL, 0, niflags) == 0),
461 		       (stdout, ";; Querying server (# %d) address = %s\n",
462 			ns + 1, abuf));
463 
464 
465 		if (v_circuit) {
466 			/* Use VC; at most one attempt per server. */
467 			try = statp->retry;
468 			n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
469 				    ns);
470 			if (n < 0)
471 				goto fail;
472 			if (n == 0)
473 				goto next_ns;
474 			resplen = n;
475 		} else {
476 			/* Use datagrams. */
477 			n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
478 				    ns, &v_circuit, &gotsomewhere);
479 			if (n < 0)
480 				goto fail;
481 			if (n == 0)
482 				goto next_ns;
483 			if (v_circuit)
484 				goto same_ns;
485 			resplen = n;
486 		}
487 
488 		Dprint((statp->options & RES_DEBUG) ||
489 		       ((statp->pfcode & RES_PRF_REPLY) &&
490 			(statp->pfcode & RES_PRF_HEAD1)),
491 		       (stdout, ";; got answer:\n"));
492 
493 		DprintQ((statp->options & RES_DEBUG) ||
494 			(statp->pfcode & RES_PRF_REPLY),
495 			(stdout, "%s", ""),
496 			ans, (resplen > anssiz) ? anssiz : resplen);
497 
498 		/*
499 		 * If we have temporarily opened a virtual circuit,
500 		 * or if we haven't been asked to keep a socket open,
501 		 * close the socket.
502 		 */
503 		if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
504 		    (statp->options & RES_STAYOPEN) == 0) {
505 			res_nclose(statp);
506 		}
507 		if (statp->rhook) {
508 			int done = 0, loops = 0;
509 
510 			do {
511 				res_sendhookact act;
512 
513 				act = (*statp->rhook)(nsap, buf, buflen,
514 						      ans, anssiz, &resplen);
515 				switch (act) {
516 				case res_goahead:
517 				case res_done:
518 					done = 1;
519 					break;
520 				case res_nextns:
521 					res_nclose(statp);
522 					goto next_ns;
523 				case res_modified:
524 					/* give the hook another try */
525 					if (++loops < 42) /*doug adams*/
526 						break;
527 					/*FALLTHROUGH*/
528 				case res_error:
529 					/*FALLTHROUGH*/
530 				default:
531 					goto fail;
532 				}
533 			} while (!done);
534 
535 		}
536 		return (resplen);
537  next_ns: ;
538 	   } /*foreach ns*/
539 	} /*foreach retry*/
540 	res_nclose(statp);
541 	if (!v_circuit) {
542 		if (!gotsomewhere)
543 			errno = ECONNREFUSED;	/* no nameservers found */
544 		else
545 			errno = ETIMEDOUT;	/* no answer obtained */
546 	} else
547 		errno = terrno;
548 	return (-1);
549  fail:
550 	res_nclose(statp);
551 	return (-1);
552 }
553 
554 /* Private */
555 
556 static int
557 get_salen(sa)
558 	const struct sockaddr *sa;
559 {
560 
561 #ifdef HAVE_SA_LEN
562 	/* There are people do not set sa_len.  Be forgiving to them. */
563 	if (sa->sa_len)
564 		return (sa->sa_len);
565 #endif
566 
567 	if (sa->sa_family == AF_INET)
568 		return (sizeof(struct sockaddr_in));
569 	else if (sa->sa_family == AF_INET6)
570 		return (sizeof(struct sockaddr_in6));
571 	else
572 		return (0);	/* unknown, die on connect */
573 }
574 
575 /*
576  * pick appropriate nsaddr_list for use.  see res_init() for initialization.
577  */
578 static struct sockaddr *
579 get_nsaddr(statp, n)
580 	res_state statp;
581 	size_t n;
582 {
583 
584 	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
585 		/*
586 		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
587 		 *   than struct sockaddr, and
588 		 * - user code did not update statp->nsaddr_list[n].
589 		 */
590 		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
591 	} else {
592 		/*
593 		 * - user code updated statp->nsaddr_list[n], or
594 		 * - statp->nsaddr_list[n] has the same content as
595 		 *   EXT(statp).ext->nsaddrs[n].
596 		 */
597 		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
598 	}
599 }
600 
601 static int
602 send_vc(res_state statp,
603 	const u_char *buf, int buflen, u_char *ans, int anssiz,
604 	int *terrno, int ns)
605 {
606 	const HEADER *hp = (const HEADER *) buf;
607 	HEADER *anhp = (HEADER *) ans;
608 	struct sockaddr *nsap;
609 	int nsaplen;
610 	int truncating, connreset, resplen, n;
611 	struct iovec iov[2];
612 	u_short len;
613 	u_char *cp;
614 	void *tmp;
615 
616 	nsap = get_nsaddr(statp, ns);
617 	nsaplen = get_salen(nsap);
618 
619 	connreset = 0;
620  same_ns:
621 	truncating = 0;
622 
623 	/* Are we still talking to whom we want to talk to? */
624 	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
625 		struct sockaddr_storage peer;
626 		ISC_SOCKLEN_T size = sizeof peer;
627 
628 		if (getpeername(statp->_vcsock,
629 				(struct sockaddr *)&peer, &size) < 0 ||
630 		    !sock_eq((struct sockaddr *)&peer, nsap)) {
631 			res_nclose(statp);
632 			statp->_flags &= ~RES_F_VC;
633 		}
634 	}
635 
636 	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
637 		if (statp->_vcsock >= 0)
638 			res_nclose(statp);
639 
640 		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
641 		if (statp->_vcsock > highestFD) {
642 			res_nclose(statp);
643 			errno = ENOTSOCK;
644 		}
645 		if (statp->_vcsock < 0) {
646 			*terrno = errno;
647 			Perror(statp, stderr, "socket(vc)", errno);
648 			return (-1);
649 		}
650 		errno = 0;
651 		if (connect(statp->_vcsock, nsap, nsaplen) < 0) {
652 			*terrno = errno;
653 			Aerror(statp, stderr, "connect/vc", errno, nsap,
654 			    nsaplen);
655 			res_nclose(statp);
656 			return (0);
657 		}
658 		statp->_flags |= RES_F_VC;
659 	}
660 
661 	/*
662 	 * Send length & message
663 	 */
664 	ns_put16((u_short)buflen, (u_char*)&len);
665 	iov[0] = evConsIovec(&len, INT16SZ);
666 	DE_CONST(buf, tmp);
667 	iov[1] = evConsIovec(tmp, buflen);
668 	if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
669 		*terrno = errno;
670 		Perror(statp, stderr, "write failed", errno);
671 		res_nclose(statp);
672 		return (0);
673 	}
674 	/*
675 	 * Receive length & response
676 	 */
677  read_len:
678 	cp = ans;
679 	len = INT16SZ;
680 	while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
681 		cp += n;
682 		if ((len -= n) <= 0)
683 			break;
684 	}
685 	if (n <= 0) {
686 		*terrno = errno;
687 		Perror(statp, stderr, "read failed", errno);
688 		res_nclose(statp);
689 		/*
690 		 * A long running process might get its TCP
691 		 * connection reset if the remote server was
692 		 * restarted.  Requery the server instead of
693 		 * trying a new one.  When there is only one
694 		 * server, this means that a query might work
695 		 * instead of failing.  We only allow one reset
696 		 * per query to prevent looping.
697 		 */
698 		if (*terrno == ECONNRESET && !connreset) {
699 			connreset = 1;
700 			res_nclose(statp);
701 			goto same_ns;
702 		}
703 		res_nclose(statp);
704 		return (0);
705 	}
706 	resplen = ns_get16(ans);
707 	if (resplen > anssiz) {
708 		Dprint(statp->options & RES_DEBUG,
709 		       (stdout, ";; response truncated\n")
710 		       );
711 		truncating = 1;
712 		len = anssiz;
713 	} else
714 		len = resplen;
715 	if (len < HFIXEDSZ) {
716 		/*
717 		 * Undersized message.
718 		 */
719 		Dprint(statp->options & RES_DEBUG,
720 		       (stdout, ";; undersized: %d\n", len));
721 		*terrno = EMSGSIZE;
722 		res_nclose(statp);
723 		return (0);
724 	}
725 	cp = ans;
726 	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
727 		cp += n;
728 		len -= n;
729 	}
730 	if (n <= 0) {
731 		*terrno = errno;
732 		Perror(statp, stderr, "read(vc)", errno);
733 		res_nclose(statp);
734 		return (0);
735 	}
736 	if (truncating) {
737 		/*
738 		 * Flush rest of answer so connection stays in synch.
739 		 */
740 		anhp->tc = 1;
741 		len = resplen - anssiz;
742 		/*
743 		 * Reset the value of resplen to anssiz,
744 		 * this is done because the caller assumes
745 		 * resplen contains the size of message read
746 		 * into the "ans" buffer passed in.
747 		 */
748 		resplen = anssiz;
749 
750 		while (len != 0) {
751 			char junk[PACKETSZ];
752 
753 			n = read(statp->_vcsock, junk,
754 				 (len > sizeof junk) ? sizeof junk : len);
755 			if (n > 0)
756 				len -= n;
757 			else
758 				break;
759 		}
760 	}
761 	/*
762 	 * If the calling applicating has bailed out of
763 	 * a previous call and failed to arrange to have
764 	 * the circuit closed or the server has got
765 	 * itself confused, then drop the packet and
766 	 * wait for the correct one.
767 	 */
768 	if (hp->id != anhp->id) {
769 		DprintQ((statp->options & RES_DEBUG) ||
770 			(statp->pfcode & RES_PRF_REPLY),
771 			(stdout, ";; old answer (unexpected):\n"),
772 			ans, (resplen > anssiz) ? anssiz: resplen);
773 		goto read_len;
774 	}
775 
776 	/*
777 	 * All is well, or the error is fatal.  Signal that the
778 	 * next nameserver ought not be tried.
779 	 */
780 	return (resplen);
781 }
782 
783 static int
784 send_dg(res_state statp,
785 	const u_char *buf, int buflen, u_char *ans, int anssiz,
786 	int *terrno, int ns, int *v_circuit, int *gotsomewhere)
787 {
788 	const HEADER *hp = (const HEADER *) buf;
789 	HEADER *anhp = (HEADER *) ans;
790 	const struct sockaddr *nsap;
791 	int nsaplen;
792 	struct timespec now, timeout, finish;
793 	fd_set dsmask;
794 	struct sockaddr_storage from;
795 	ISC_SOCKLEN_T fromlen;
796 	int resplen, seconds, n, s;
797 #ifdef	SUNW_POLL
798 	int	polltimeout;
799 	struct pollfd   pollfd;
800 #endif
801 
802 	nsap = get_nsaddr(statp, ns);
803 	nsaplen = get_salen(nsap);
804 	if (EXT(statp).nssocks[ns] == -1) {
805 		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
806 		if (EXT(statp).nssocks[ns] > highestFD) {
807 			res_nclose(statp);
808 			errno = ENOTSOCK;
809 		}
810 		if (EXT(statp).nssocks[ns] < 0) {
811 			*terrno = errno;
812 			Perror(statp, stderr, "socket(dg)", errno);
813 			return (-1);
814 		}
815 #ifndef CANNOT_CONNECT_DGRAM
816 		/*
817 		 * On a 4.3BSD+ machine (client and server,
818 		 * actually), sending to a nameserver datagram
819 		 * port with no nameserver will cause an
820 		 * ICMP port unreachable message to be returned.
821 		 * If our datagram socket is "connected" to the
822 		 * server, we get an ECONNREFUSED error on the next
823 		 * socket operation, and select returns if the
824 		 * error message is received.  We can thus detect
825 		 * the absence of a nameserver without timing out.
826 		 */
827 		if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {
828 			Aerror(statp, stderr, "connect(dg)", errno, nsap,
829 			    nsaplen);
830 			res_nclose(statp);
831 			return (0);
832 		}
833 #endif /* !CANNOT_CONNECT_DGRAM */
834 		Dprint(statp->options & RES_DEBUG,
835 		       (stdout, ";; new DG socket\n"))
836 	}
837 	s = EXT(statp).nssocks[ns];
838 #ifndef CANNOT_CONNECT_DGRAM
839 	if (send(s, (const char*)buf, buflen, 0) != buflen) {
840 		Perror(statp, stderr, "send", errno);
841 		res_nclose(statp);
842 		return (0);
843 	}
844 #else /* !CANNOT_CONNECT_DGRAM */
845 	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
846 	{
847 		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
848 		res_nclose(statp);
849 		return (0);
850 	}
851 #endif /* !CANNOT_CONNECT_DGRAM */
852 
853 	/*
854 	 * Wait for reply.
855 	 */
856 	seconds = (statp->retrans << ns);
857 	if (ns > 0)
858 		seconds /= statp->nscount;
859 	if (seconds <= 0)
860 		seconds = 1;
861 	now = evNowTime();
862 	timeout = evConsTime(seconds, 0);
863 	finish = evAddTime(now, timeout);
864 	goto nonow;
865  wait:
866 	now = evNowTime();
867  nonow:
868 #ifdef	SUNW_POLL
869 	timeout = evSubTime(finish, now);
870 	if (timeout.tv_sec < 0)
871 		timeout = evConsTime(0, 0);
872 	polltimeout = 1000*timeout.tv_sec +
873 		timeout.tv_nsec/1000000;
874 	pollfd.fd = s;
875 	pollfd.events = POLLRDNORM;
876 	n = poll(&pollfd, 1, polltimeout);
877 #else
878 	FD_ZERO(&dsmask);
879 	FD_SET(s, &dsmask);
880 	if (evCmpTime(finish, now) > 0)
881 		timeout = evSubTime(finish, now);
882 	else
883 		timeout = evConsTime(0, 0);
884 	n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
885 #endif
886 	if (n == 0) {
887 		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
888 		*gotsomewhere = 1;
889 		return (0);
890 	}
891 	if (n < 0) {
892 		if (errno == EINTR)
893 			goto wait;
894 #ifdef	SUNW_POLL
895 		Perror(statp, stderr, "poll", errno);
896 #else
897 		Perror(statp, stderr, "select", errno);
898 #endif
899 		res_nclose(statp);
900 		return (0);
901 	}
902 	errno = 0;
903 	fromlen = sizeof(from);
904 	resplen = recvfrom(s, (char*)ans, anssiz,0,
905 			   (struct sockaddr *)&from, &fromlen);
906 	if (resplen <= 0) {
907 		Perror(statp, stderr, "recvfrom", errno);
908 		res_nclose(statp);
909 		return (0);
910 	}
911 	*gotsomewhere = 1;
912 	if (resplen < HFIXEDSZ) {
913 		/*
914 		 * Undersized message.
915 		 */
916 		Dprint(statp->options & RES_DEBUG,
917 		       (stdout, ";; undersized: %d\n",
918 			resplen));
919 		*terrno = EMSGSIZE;
920 		res_nclose(statp);
921 		return (0);
922 	}
923 	if (hp->id != anhp->id) {
924 		/*
925 		 * response from old query, ignore it.
926 		 * XXX - potential security hazard could
927 		 *	 be detected here.
928 		 */
929 		DprintQ((statp->options & RES_DEBUG) ||
930 			(statp->pfcode & RES_PRF_REPLY),
931 			(stdout, ";; old answer:\n"),
932 			ans, (resplen > anssiz) ? anssiz : resplen);
933 		goto wait;
934 	}
935 	if (!(statp->options & RES_INSECURE1) &&
936 	    !res_ourserver_p(statp, (struct sockaddr *)&from)) {
937 		/*
938 		 * response from wrong server? ignore it.
939 		 * XXX - potential security hazard could
940 		 *	 be detected here.
941 		 */
942 		DprintQ((statp->options & RES_DEBUG) ||
943 			(statp->pfcode & RES_PRF_REPLY),
944 			(stdout, ";; not our server:\n"),
945 			ans, (resplen > anssiz) ? anssiz : resplen);
946 		goto wait;
947 	}
948 #ifdef RES_USE_EDNS0
949 	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) {
950 		/*
951 		 * Do not retry if the server do not understand EDNS0.
952 		 * The case has to be captured here, as FORMERR packet do not
953 		 * carry query section, hence res_queriesmatch() returns 0.
954 		 */
955 		DprintQ(statp->options & RES_DEBUG,
956 			(stdout, "server rejected query with EDNS0:\n"),
957 			ans, (resplen > anssiz) ? anssiz : resplen);
958 		/* record the error */
959 		statp->_flags |= RES_F_EDNS0ERR;
960 		res_nclose(statp);
961 		return (0);
962 	}
963 #endif
964 	if (!(statp->options & RES_INSECURE2) &&
965 	    !res_queriesmatch(buf, buf + buflen,
966 			      ans, ans + anssiz)) {
967 		/*
968 		 * response contains wrong query? ignore it.
969 		 * XXX - potential security hazard could
970 		 *	 be detected here.
971 		 */
972 		DprintQ((statp->options & RES_DEBUG) ||
973 			(statp->pfcode & RES_PRF_REPLY),
974 			(stdout, ";; wrong query name:\n"),
975 			ans, (resplen > anssiz) ? anssiz : resplen);
976 		goto wait;
977 	}
978 	if (anhp->rcode == SERVFAIL ||
979 	    anhp->rcode == NOTIMP ||
980 	    anhp->rcode == REFUSED) {
981 		DprintQ(statp->options & RES_DEBUG,
982 			(stdout, "server rejected query:\n"),
983 			ans, (resplen > anssiz) ? anssiz : resplen);
984 		res_nclose(statp);
985 		/* don't retry if called from dig */
986 		if (!statp->pfcode)
987 			return (0);
988 	}
989 	if (!(statp->options & RES_IGNTC) && anhp->tc) {
990 		/*
991 		 * To get the rest of answer,
992 		 * use TCP with same server.
993 		 */
994 		Dprint(statp->options & RES_DEBUG,
995 		       (stdout, ";; truncated answer\n"));
996 		*v_circuit = 1;
997 		res_nclose(statp);
998 		return (1);
999 	}
1000 	/*
1001 	 * All is well, or the error is fatal.  Signal that the
1002 	 * next nameserver ought not be tried.
1003 	 */
1004 	return (resplen);
1005 }
1006 
1007 static void
1008 Aerror(const res_state statp, FILE *file, const char *string, int error,
1009        const struct sockaddr *address, int alen)
1010 {
1011 	int save = errno;
1012 	char hbuf[NI_MAXHOST];
1013 	char sbuf[NI_MAXSERV];
1014 
1015 	alen = alen;
1016 
1017 	if ((statp->options & RES_DEBUG) != 0) {
1018 		if (getnameinfo(address, alen, hbuf, sizeof(hbuf),
1019 		    sbuf, sizeof(sbuf), niflags)) {
1020 			strncpy(hbuf, "?", sizeof(hbuf) - 1);
1021 			hbuf[sizeof(hbuf) - 1] = '\0';
1022 			strncpy(sbuf, "?", sizeof(sbuf) - 1);
1023 			sbuf[sizeof(sbuf) - 1] = '\0';
1024 		}
1025 		fprintf(file, "res_send: %s ([%s].%s): %s\n",
1026 			string, hbuf, sbuf, strerror(error));
1027 	}
1028 	errno = save;
1029 }
1030 
1031 static void
1032 Perror(const res_state statp, FILE *file, const char *string, int error) {
1033 	int save = errno;
1034 
1035 	if ((statp->options & RES_DEBUG) != 0)
1036 		fprintf(file, "res_send: %s: %s\n",
1037 			string, strerror(error));
1038 	errno = save;
1039 }
1040 
1041 static int
1042 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1043 	struct sockaddr_in *a4, *b4;
1044 	struct sockaddr_in6 *a6, *b6;
1045 
1046 	if (a->sa_family != b->sa_family)
1047 		return 0;
1048 	switch (a->sa_family) {
1049 	case AF_INET:
1050 		a4 = (struct sockaddr_in *)a;
1051 		b4 = (struct sockaddr_in *)b;
1052 		return a4->sin_port == b4->sin_port &&
1053 		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1054 	case AF_INET6:
1055 		a6 = (struct sockaddr_in6 *)a;
1056 		b6 = (struct sockaddr_in6 *)b;
1057 		return a6->sin6_port == b6->sin6_port &&
1058 #ifdef HAVE_SIN6_SCOPE_ID
1059 		    a6->sin6_scope_id == b6->sin6_scope_id &&
1060 #endif
1061 		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1062 	default:
1063 		return 0;
1064 	}
1065 }
1066 
1067 #ifdef NEED_PSELECT
1068 /* XXX needs to move to the porting library. */
1069 static int
1070 pselect(int nfds, void *rfds, void *wfds, void *efds,
1071 	struct timespec *tsp, const sigset_t *sigmask)
1072 {
1073 	struct timeval tv, *tvp;
1074 	sigset_t sigs;
1075 	int n;
1076 
1077 	if (tsp) {
1078 		tvp = &tv;
1079 		tv = evTimeVal(*tsp);
1080 	} else
1081 		tvp = NULL;
1082 	if (sigmask)
1083 		sigprocmask(SIG_SETMASK, sigmask, &sigs);
1084 	n = select(nfds, rfds, wfds, efds, tvp);
1085 	if (sigmask)
1086 		sigprocmask(SIG_SETMASK, &sigs, NULL);
1087 	if (tsp)
1088 		*tsp = evTimeSpec(tv);
1089 	return (n);
1090 }
1091 #endif
1092