xref: /illumos-gate/usr/src/lib/libresolv2/common/resolv/res_send.c (revision 6e6545bfaed3bab9ce836ee82d1abd8f2edba89a)
1 /*
2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  *
5  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
6  */
7 
8 
9 /*
10  * Portions Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
11  * Portions Copyright (C) 1996-2003  Internet Software Consortium.
12  *
13  * Permission to use, copy, modify, and/or distribute this software for any
14  * purpose with or without fee is hereby granted, provided that the above
15  * copyright notice and this permission notice appear in all copies.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
18  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
20  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  */
25 
26 /*
27  * Copyright (c) 1985, 1989, 1993
28  *    The Regents of the University of California.  All rights reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without
31  * modification, are permitted provided that the following conditions
32  * are met:
33  * 1. Redistributions of source code must retain the above copyright
34  *    notice, this list of conditions and the following disclaimer.
35  * 2. Redistributions in binary form must reproduce the above copyright
36  *    notice, this list of conditions and the following disclaimer in the
37  *    documentation and/or other materials provided with the distribution.
38  * 3. All advertising materials mentioning features or use of this software
39  *    must display the following acknowledgement:
40  * 	This product includes software developed by the University of
41  * 	California, Berkeley and its contributors.
42  * 4. Neither the name of the University nor the names of its contributors
43  *    may be used to endorse or promote products derived from this software
44  *    without specific prior written permission.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  */
58 
59 /*
60  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
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, and that
65  * the name of Digital Equipment Corporation not be used in advertising or
66  * publicity pertaining to distribution of the document or software without
67  * specific, written prior permission.
68  *
69  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
70  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
71  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
72  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
73  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
74  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
75  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76  * SOFTWARE.
77  */
78 
79 /*! \file
80  * \brief
81  * Send query to name server and wait for reply.
82  */
83 
84 #include "port_before.h"
85 #include "fd_setsize.h"
86 
87 #include <sys/types.h>
88 #include <sys/param.h>
89 #include <sys/time.h>
90 #include <sys/socket.h>
91 #include <sys/uio.h>
92 
93 #include <netinet/in.h>
94 #include <netinet/tcp.h>
95 #include <arpa/nameser.h>
96 #include <arpa/inet.h>
97 
98 #include <errno.h>
99 #include <netdb.h>
100 #include <resolv.h>
101 #include <signal.h>
102 #include <stdio.h>
103 #include <stdlib.h>
104 #include <string.h>
105 #include <unistd.h>
106 
107 #include <isc/eventlib.h>
108 
109 #include "port_after.h"
110 
111 #ifdef USE_POLL
112 #ifdef HAVE_STROPTS_H
113 #include <stropts.h>
114 #endif
115 #include <poll.h>
116 #endif /* USE_POLL */
117 
118 /* Options.  Leave them on. */
119 #define DEBUG
120 #include "res_debug.h"
121 #include "res_private.h"
122 
123 #define EXT(res) ((res)->_u._ext)
124 
125 #ifndef USE_POLL
126 static const int highestFD = FD_SETSIZE - 1;
127 #else
128 static int highestFD = 0;
129 #endif
130 
131 /* Forward. */
132 
133 static int		get_salen __P((const struct sockaddr *));
134 static struct sockaddr * get_nsaddr __P((res_state, size_t));
135 static int		send_vc(res_state, const u_char *, int,
136 				u_char *, int, int *, int);
137 static int		send_dg(res_state, const u_char *, int,
138 				u_char *, int, int *, int, int,
139 				int *, int *);
140 static void		Aerror(const res_state, FILE *, const char *, int,
141 			       const struct sockaddr *, int);
142 static void		Perror(const res_state, FILE *, const char *, int);
143 static int		sock_eq(struct sockaddr *, struct sockaddr *);
144 #if defined(NEED_PSELECT) && !defined(USE_POLL)
145 static int		pselect(int, void *, void *, void *,
146 				struct timespec *,
147 				const sigset_t *);
148 #endif
149 void res_pquery(const res_state, const u_char *, int, FILE *);
150 
151 #ifndef	ORIGINAL_ISC_CODE
152 #pragma weak	__res_nameinquery	=	res_nameinquery
153 #pragma weak	__res_queriesmatch	=	res_queriesmatch
154 #pragma weak	res_nisourserver	=	res_ourserver_p
155 #endif	/* ORIGINAL_ISC_CODE */
156 
157 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
158 
159 /* Public. */
160 
161 /*%
162  *	looks up "ina" in _res.ns_addr_list[]
163  *
164  * returns:
165  *\li	0  : not found
166  *\li	>0 : found
167  *
168  * author:
169  *\li	paul vixie, 29may94
170  */
171 int
172 res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
173 	const struct sockaddr_in *inp, *srv;
174 	const struct sockaddr_in6 *in6p, *srv6;
175 	int ns;
176 
177 	switch (sa->sa_family) {
178 	case AF_INET:
179 		inp = (const struct sockaddr_in *)sa;
180 		for (ns = 0;  ns < statp->nscount;  ns++) {
181 			srv = (struct sockaddr_in *)get_nsaddr(statp, ns);
182 			if (srv->sin_family == inp->sin_family &&
183 			    srv->sin_port == inp->sin_port &&
184 			    (srv->sin_addr.s_addr == INADDR_ANY ||
185 			     srv->sin_addr.s_addr == inp->sin_addr.s_addr))
186 				return (1);
187 		}
188 		break;
189 	case AF_INET6:
190 		if (EXT(statp).ext == NULL)
191 			break;
192 		in6p = (const struct sockaddr_in6 *)sa;
193 		for (ns = 0;  ns < statp->nscount;  ns++) {
194 			srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns);
195 			if (srv6->sin6_family == in6p->sin6_family &&
196 			    srv6->sin6_port == in6p->sin6_port &&
197 #ifdef HAVE_SIN6_SCOPE_ID
198 			    (srv6->sin6_scope_id == 0 ||
199 			     srv6->sin6_scope_id == in6p->sin6_scope_id) &&
200 #endif
201 			    (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
202 			     IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
203 				return (1);
204 		}
205 		break;
206 	default:
207 		break;
208 	}
209 	return (0);
210 }
211 
212 /*%
213  *	look for (name,type,class) in the query section of packet (buf,eom)
214  *
215  * requires:
216  *\li	buf + HFIXEDSZ <= eom
217  *
218  * returns:
219  *\li	-1 : format error
220  *\li	0  : not found
221  *\li	>0 : found
222  *
223  * author:
224  *\li	paul vixie, 29may94
225  */
226 int
227 res_nameinquery(const char *name, int type, int class,
228 		const u_char *buf, const u_char *eom)
229 {
230 	const u_char *cp = buf + HFIXEDSZ;
231 	int qdcount = ntohs(((const HEADER*)buf)->qdcount);
232 
233 	while (qdcount-- > 0) {
234 		char tname[MAXDNAME+1];
235 		int n, ttype, tclass;
236 
237 		n = dn_expand(buf, eom, cp, tname, sizeof tname);
238 		if (n < 0)
239 			return (-1);
240 		cp += n;
241 		if (cp + 2 * INT16SZ > eom)
242 			return (-1);
243 		ttype = ns_get16(cp); cp += INT16SZ;
244 		tclass = ns_get16(cp); cp += INT16SZ;
245 		if (ttype == type && tclass == class &&
246 		    ns_samename(tname, name) == 1)
247 			return (1);
248 	}
249 	return (0);
250 }
251 
252 /*%
253  *	is there a 1:1 mapping of (name,type,class)
254  *	in (buf1,eom1) and (buf2,eom2)?
255  *
256  * returns:
257  *\li	-1 : format error
258  *\li	0  : not a 1:1 mapping
259  *\li	>0 : is a 1:1 mapping
260  *
261  * author:
262  *\li	paul vixie, 29may94
263  */
264 int
265 res_queriesmatch(const u_char *buf1, const u_char *eom1,
266 		 const u_char *buf2, const u_char *eom2)
267 {
268 	const u_char *cp = buf1 + HFIXEDSZ;
269 	int qdcount = ntohs(((const HEADER*)buf1)->qdcount);
270 
271 	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
272 		return (-1);
273 
274 	/*
275 	 * Only header section present in replies to
276 	 * dynamic update packets.
277 	 */
278 	if ((((const HEADER *)buf1)->opcode == ns_o_update) &&
279 	    (((const HEADER *)buf2)->opcode == ns_o_update))
280 		return (1);
281 
282 	if (qdcount != ntohs(((const HEADER*)buf2)->qdcount))
283 		return (0);
284 	while (qdcount-- > 0) {
285 		char tname[MAXDNAME+1];
286 		int n, ttype, tclass;
287 
288 		n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
289 		if (n < 0)
290 			return (-1);
291 		cp += n;
292 		if (cp + 2 * INT16SZ > eom1)
293 			return (-1);
294 		ttype = ns_get16(cp);	cp += INT16SZ;
295 		tclass = ns_get16(cp); cp += INT16SZ;
296 		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
297 			return (0);
298 	}
299 	return (1);
300 }
301 
302 int
303 res_nsend(res_state statp,
304 	  const u_char *buf, int buflen, u_char *ans, int anssiz)
305 {
306 	int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
307 	char abuf[NI_MAXHOST];
308 
309 #ifdef USE_POLL
310 	highestFD = sysconf(_SC_OPEN_MAX) - 1;
311 #endif
312 
313 	/* No name servers or res_init() failure */
314 	if (statp->nscount == 0 || EXT(statp).ext == NULL) {
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 (getpeername(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) != 0U &&
388 	    (statp->options & RES_BLAST) == 0U) {
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 (tries = 0; tries < statp->retry; tries++) {
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 			tries = 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, tries, &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) == 0U) ||
503 		    (statp->options & RES_STAYOPEN) == 0U) {
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 #ifdef SO_NOSIGPIPE
615 	int on = 1;
616 #endif
617 
618 	nsap = get_nsaddr(statp, ns);
619 	nsaplen = get_salen(nsap);
620 
621 	connreset = 0;
622  same_ns:
623 	truncating = 0;
624 
625 	/* Are we still talking to whom we want to talk to? */
626 	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
627 		struct sockaddr_storage peer;
628 		ISC_SOCKLEN_T size = sizeof peer;
629 
630 		if (getpeername(statp->_vcsock,
631 				(struct sockaddr *)&peer, &size) < 0 ||
632 		    !sock_eq((struct sockaddr *)&peer, nsap)) {
633 			res_nclose(statp);
634 			statp->_flags &= ~RES_F_VC;
635 		}
636 	}
637 
638 	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
639 		if (statp->_vcsock >= 0)
640 			res_nclose(statp);
641 
642 		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
643 		if (statp->_vcsock > highestFD) {
644 			res_nclose(statp);
645 			errno = ENOTSOCK;
646 		}
647 		if (statp->_vcsock < 0) {
648 			switch (errno) {
649 			case EPROTONOSUPPORT:
650 #ifdef EPFNOSUPPORT
651 			case EPFNOSUPPORT:
652 #endif
653 			case EAFNOSUPPORT:
654 				Perror(statp, stderr, "socket(vc)", errno);
655 				return (0);
656 			default:
657 				*terrno = errno;
658 				Perror(statp, stderr, "socket(vc)", errno);
659 				return (-1);
660 			}
661 		}
662 #ifdef SO_NOSIGPIPE
663 		/*
664 		 * Disable generation of SIGPIPE when writing to a closed
665 		 * socket.  Write should return -1 and set errno to EPIPE
666 		 * instead.
667 		 *
668 		 * Push on even if setsockopt(SO_NOSIGPIPE) fails.
669 		 */
670 		(void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
671 				 sizeof(on));
672 #endif
673 #ifdef TCP_CONN_ABORT_THRESHOLD
674 		/*
675 		 * The default connection timeout is over two minutes.
676 		 * We need something more reasonable here.  The default
677 		 * retrans value is 5 sec., then 10, 20, 40, on retries.
678 		 * TCP connect does its own retries, so we want just one
679 		 * reasonable timeout value.  Using 2X retrans, which
680 		 * gives us a 10 sec. connect timeout.  If we're waiting
681 		 * that long to connect, we probably want to give up and
682 		 * try the next DNS server in our list.
683 		 *
684 		 * It might be reasonable to do this for all callers,
685 		 * but for now do it only when we see MS_INTEROP in the
686 		 * environment (set in smbd and idmapd)
687 		 */
688 		if (getenv("MS_INTEROP") != NULL) {
689 			int conn_tmo;
690 			conn_tmo = statp->retrans * 2000; /* mSec */
691 			(void)setsockopt(statp->_vcsock, IPPROTO_TCP,
692 			    TCP_CONN_ABORT_THRESHOLD, &conn_tmo,
693 			     sizeof(conn_tmo));
694 		}
695 #endif
696 		errno = 0;
697 		if (connect(statp->_vcsock, nsap, nsaplen) < 0) {
698 			*terrno = errno;
699 			Aerror(statp, stderr, "connect/vc", errno, nsap,
700 			    nsaplen);
701 			res_nclose(statp);
702 			return (0);
703 		}
704 		statp->_flags |= RES_F_VC;
705 	}
706 
707 	/*
708 	 * Send length & message
709 	 */
710 	ns_put16((u_short)buflen, (u_char*)&len);
711 	iov[0] = evConsIovec(&len, INT16SZ);
712 	DE_CONST(buf, tmp);
713 	iov[1] = evConsIovec(tmp, buflen);
714 	if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
715 		*terrno = errno;
716 		Perror(statp, stderr, "write failed", errno);
717 		res_nclose(statp);
718 		return (0);
719 	}
720 	/*
721 	 * Receive length & response
722 	 */
723  read_len:
724 	cp = ans;
725 	len = INT16SZ;
726 	while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
727 		cp += n;
728 		if ((len -= n) == 0)
729 			break;
730 	}
731 	if (n <= 0) {
732 		*terrno = errno;
733 		Perror(statp, stderr, "read failed", errno);
734 		res_nclose(statp);
735 		/*
736 		 * A long running process might get its TCP
737 		 * connection reset if the remote server was
738 		 * restarted.  Requery the server instead of
739 		 * trying a new one.  When there is only one
740 		 * server, this means that a query might work
741 		 * instead of failing.  We only allow one reset
742 		 * per query to prevent looping.
743 		 */
744 		if (*terrno == ECONNRESET && !connreset) {
745 			connreset = 1;
746 			res_nclose(statp);
747 			goto same_ns;
748 		}
749 		res_nclose(statp);
750 		return (0);
751 	}
752 	resplen = ns_get16(ans);
753 	if (resplen > anssiz) {
754 		Dprint(statp->options & RES_DEBUG,
755 		       (stdout, ";; response truncated\n")
756 		       );
757 		truncating = 1;
758 		len = anssiz;
759 	} else
760 		len = resplen;
761 	if (len < HFIXEDSZ) {
762 		/*
763 		 * Undersized message.
764 		 */
765 		Dprint(statp->options & RES_DEBUG,
766 		       (stdout, ";; undersized: %d\n", len));
767 		*terrno = EMSGSIZE;
768 		res_nclose(statp);
769 		return (0);
770 	}
771 	cp = ans;
772 	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
773 		cp += n;
774 		len -= n;
775 	}
776 	if (n <= 0) {
777 		*terrno = errno;
778 		Perror(statp, stderr, "read(vc)", errno);
779 		res_nclose(statp);
780 		return (0);
781 	}
782 	if (truncating) {
783 		/*
784 		 * Flush rest of answer so connection stays in synch.
785 		 */
786 		anhp->tc = 1;
787 		len = resplen - anssiz;
788 		while (len != 0) {
789 			char junk[PACKETSZ];
790 
791 			n = read(statp->_vcsock, junk,
792 				 (len > sizeof junk) ? sizeof junk : len);
793 			if (n > 0)
794 				len -= n;
795 			else
796 				break;
797 		}
798 	}
799 	/*
800 	 * If the calling applicating has bailed out of
801 	 * a previous call and failed to arrange to have
802 	 * the circuit closed or the server has got
803 	 * itself confused, then drop the packet and
804 	 * wait for the correct one.
805 	 */
806 	if (hp->id != anhp->id) {
807 		DprintQ((statp->options & RES_DEBUG) ||
808 			(statp->pfcode & RES_PRF_REPLY),
809 			(stdout, ";; old answer (unexpected):\n"),
810 			ans, (resplen > anssiz) ? anssiz: resplen);
811 		goto read_len;
812 	}
813 
814 	/*
815 	 * All is well, or the error is fatal.  Signal that the
816 	 * next nameserver ought not be tried.
817 	 */
818 	return (resplen);
819 }
820 
821 static int
822 send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
823 	int anssiz, int *terrno, int ns, int tries, int *v_circuit,
824 	int *gotsomewhere)
825 {
826 	const HEADER *hp = (const HEADER *) buf;
827 	HEADER *anhp = (HEADER *) ans;
828 	const struct sockaddr *nsap;
829 	int nsaplen;
830 	struct timespec now, timeout, finish;
831 	struct sockaddr_storage from;
832 	ISC_SOCKLEN_T fromlen;
833 	int resplen, seconds, n, s;
834 #ifdef USE_POLL
835 	int     polltimeout;
836 	struct pollfd   pollfd;
837 #else
838 	fd_set dsmask;
839 #endif
840 
841 	nsap = get_nsaddr(statp, ns);
842 	nsaplen = get_salen(nsap);
843 	if (EXT(statp).nssocks[ns] == -1) {
844 		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
845 		if (EXT(statp).nssocks[ns] > highestFD) {
846 			res_nclose(statp);
847 			errno = ENOTSOCK;
848 		}
849 		if (EXT(statp).nssocks[ns] < 0) {
850 			switch (errno) {
851 			case EPROTONOSUPPORT:
852 #ifdef EPFNOSUPPORT
853 			case EPFNOSUPPORT:
854 #endif
855 			case EAFNOSUPPORT:
856 				Perror(statp, stderr, "socket(dg)", errno);
857 				return (0);
858 			default:
859 				*terrno = errno;
860 				Perror(statp, stderr, "socket(dg)", errno);
861 				return (-1);
862 			}
863 		}
864 #ifndef CANNOT_CONNECT_DGRAM
865 		/*
866 		 * On a 4.3BSD+ machine (client and server,
867 		 * actually), sending to a nameserver datagram
868 		 * port with no nameserver will cause an
869 		 * ICMP port unreachable message to be returned.
870 		 * If our datagram socket is "connected" to the
871 		 * server, we get an ECONNREFUSED error on the next
872 		 * socket operation, and select returns if the
873 		 * error message is received.  We can thus detect
874 		 * the absence of a nameserver without timing out.
875 		 */
876 		if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {
877 			Aerror(statp, stderr, "connect(dg)", errno, nsap,
878 			    nsaplen);
879 			res_nclose(statp);
880 			return (0);
881 		}
882 #endif /* !CANNOT_CONNECT_DGRAM */
883 		Dprint(statp->options & RES_DEBUG,
884 		       (stdout, ";; new DG socket\n"))
885 	}
886 	s = EXT(statp).nssocks[ns];
887 #ifndef CANNOT_CONNECT_DGRAM
888 	if (send(s, (const char*)buf, buflen, 0) != buflen) {
889 		Perror(statp, stderr, "send", errno);
890 		res_nclose(statp);
891 		return (0);
892 	}
893 #else /* !CANNOT_CONNECT_DGRAM */
894 	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
895 	{
896 		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
897 		res_nclose(statp);
898 		return (0);
899 	}
900 #endif /* !CANNOT_CONNECT_DGRAM */
901 
902 	/*
903 	 * Wait for reply.
904 	 */
905 	seconds = (statp->retrans << tries);
906 	if (ns > 0)
907 		seconds /= statp->nscount;
908 	if (seconds <= 0)
909 		seconds = 1;
910 	now = evNowTime();
911 	timeout = evConsTime(seconds, 0);
912 	finish = evAddTime(now, timeout);
913 	goto nonow;
914  wait:
915 	now = evNowTime();
916  nonow:
917 #ifndef USE_POLL
918 	FD_ZERO(&dsmask);
919 	FD_SET(s, &dsmask);
920 	if (evCmpTime(finish, now) > 0)
921 		timeout = evSubTime(finish, now);
922 	else
923 		timeout = evConsTime(0, 0);
924 	n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
925 #else
926 	timeout = evSubTime(finish, now);
927 	if (timeout.tv_sec < 0)
928 		timeout = evConsTime(0, 0);
929 	polltimeout = 1000*timeout.tv_sec +
930 		timeout.tv_nsec/1000000;
931 	pollfd.fd = s;
932 	pollfd.events = POLLRDNORM;
933 	n = poll(&pollfd, 1, polltimeout);
934 #endif /* USE_POLL */
935 
936 	if (n == 0) {
937 		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
938 		*gotsomewhere = 1;
939 		return (0);
940 	}
941 	if (n < 0) {
942 		if (errno == EINTR)
943 			goto wait;
944 #ifndef USE_POLL
945 		Perror(statp, stderr, "select", errno);
946 #else
947 		Perror(statp, stderr, "poll", errno);
948 #endif /* USE_POLL */
949 		res_nclose(statp);
950 		return (0);
951 	}
952 	errno = 0;
953 	fromlen = sizeof(from);
954 	resplen = recvfrom(s, (char*)ans, anssiz,0,
955 			   (struct sockaddr *)&from, &fromlen);
956 	if (resplen <= 0) {
957 		Perror(statp, stderr, "recvfrom", errno);
958 		res_nclose(statp);
959 		return (0);
960 	}
961 	*gotsomewhere = 1;
962 	if (resplen < HFIXEDSZ) {
963 		/*
964 		 * Undersized message.
965 		 */
966 		Dprint(statp->options & RES_DEBUG,
967 		       (stdout, ";; undersized: %d\n",
968 			resplen));
969 		*terrno = EMSGSIZE;
970 		res_nclose(statp);
971 		return (0);
972 	}
973 	if (hp->id != anhp->id) {
974 		/*
975 		 * response from old query, ignore it.
976 		 * XXX - potential security hazard could
977 		 *	 be detected here.
978 		 */
979 		DprintQ((statp->options & RES_DEBUG) ||
980 			(statp->pfcode & RES_PRF_REPLY),
981 			(stdout, ";; old answer:\n"),
982 			ans, (resplen > anssiz) ? anssiz : resplen);
983 		goto wait;
984 	}
985 	if (!(statp->options & RES_INSECURE1) &&
986 	    !res_ourserver_p(statp, (struct sockaddr *)&from)) {
987 		/*
988 		 * response from wrong server? ignore it.
989 		 * XXX - potential security hazard could
990 		 *	 be detected here.
991 		 */
992 		DprintQ((statp->options & RES_DEBUG) ||
993 			(statp->pfcode & RES_PRF_REPLY),
994 			(stdout, ";; not our server:\n"),
995 			ans, (resplen > anssiz) ? anssiz : resplen);
996 		goto wait;
997 	}
998 #ifdef RES_USE_EDNS0
999 	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1000 		/*
1001 		 * Do not retry if the server do not understand EDNS0.
1002 		 * The case has to be captured here, as FORMERR packet do not
1003 		 * carry query section, hence res_queriesmatch() returns 0.
1004 		 */
1005 		DprintQ(statp->options & RES_DEBUG,
1006 			(stdout, "server rejected query with EDNS0:\n"),
1007 			ans, (resplen > anssiz) ? anssiz : resplen);
1008 		/* record the error */
1009 		statp->_flags |= RES_F_EDNS0ERR;
1010 		res_nclose(statp);
1011 		return (0);
1012 	}
1013 #endif
1014 	if (!(statp->options & RES_INSECURE2) &&
1015 	    !res_queriesmatch(buf, buf + buflen,
1016 			      ans, ans + anssiz)) {
1017 		/*
1018 		 * response contains wrong query? ignore it.
1019 		 * XXX - potential security hazard could
1020 		 *	 be detected here.
1021 		 */
1022 		DprintQ((statp->options & RES_DEBUG) ||
1023 			(statp->pfcode & RES_PRF_REPLY),
1024 			(stdout, ";; wrong query name:\n"),
1025 			ans, (resplen > anssiz) ? anssiz : resplen);
1026 		goto wait;
1027 	}
1028 	if (anhp->rcode == SERVFAIL ||
1029 	    anhp->rcode == NOTIMP ||
1030 	    anhp->rcode == REFUSED) {
1031 		DprintQ(statp->options & RES_DEBUG,
1032 			(stdout, "server rejected query:\n"),
1033 			ans, (resplen > anssiz) ? anssiz : resplen);
1034 		res_nclose(statp);
1035 		/* don't retry if called from dig */
1036 		if (!statp->pfcode)
1037 			return (0);
1038 	}
1039 	if (!(statp->options & RES_IGNTC) && anhp->tc) {
1040 		/*
1041 		 * To get the rest of answer,
1042 		 * use TCP with same server.
1043 		 */
1044 		Dprint(statp->options & RES_DEBUG,
1045 		       (stdout, ";; truncated answer\n"));
1046 		*v_circuit = 1;
1047 		res_nclose(statp);
1048 		return (1);
1049 	}
1050 	/*
1051 	 * All is well, or the error is fatal.  Signal that the
1052 	 * next nameserver ought not be tried.
1053 	 */
1054 	return (resplen);
1055 }
1056 
1057 static void
1058 Aerror(const res_state statp, FILE *file, const char *string, int error,
1059        const struct sockaddr *address, int alen)
1060 {
1061 	int save = errno;
1062 	char hbuf[NI_MAXHOST];
1063 	char sbuf[NI_MAXSERV];
1064 
1065 	alen = alen;
1066 
1067 	if ((statp->options & RES_DEBUG) != 0U) {
1068 		if (getnameinfo(address, alen, hbuf, sizeof(hbuf),
1069 		    sbuf, sizeof(sbuf), niflags)) {
1070 			strncpy(hbuf, "?", sizeof(hbuf) - 1);
1071 			hbuf[sizeof(hbuf) - 1] = '\0';
1072 			strncpy(sbuf, "?", sizeof(sbuf) - 1);
1073 			sbuf[sizeof(sbuf) - 1] = '\0';
1074 		}
1075 		fprintf(file, "res_send: %s ([%s].%s): %s\n",
1076 			string, hbuf, sbuf, strerror(error));
1077 	}
1078 	errno = save;
1079 }
1080 
1081 static void
1082 Perror(const res_state statp, FILE *file, const char *string, int error) {
1083 	int save = errno;
1084 
1085 	if ((statp->options & RES_DEBUG) != 0U)
1086 		fprintf(file, "res_send: %s: %s\n",
1087 			string, strerror(error));
1088 	errno = save;
1089 }
1090 
1091 static int
1092 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1093 	struct sockaddr_in *a4, *b4;
1094 	struct sockaddr_in6 *a6, *b6;
1095 
1096 	if (a->sa_family != b->sa_family)
1097 		return 0;
1098 	switch (a->sa_family) {
1099 	case AF_INET:
1100 		a4 = (struct sockaddr_in *)a;
1101 		b4 = (struct sockaddr_in *)b;
1102 		return a4->sin_port == b4->sin_port &&
1103 		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1104 	case AF_INET6:
1105 		a6 = (struct sockaddr_in6 *)a;
1106 		b6 = (struct sockaddr_in6 *)b;
1107 		return a6->sin6_port == b6->sin6_port &&
1108 #ifdef HAVE_SIN6_SCOPE_ID
1109 		    a6->sin6_scope_id == b6->sin6_scope_id &&
1110 #endif
1111 		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1112 	default:
1113 		return 0;
1114 	}
1115 }
1116 
1117 #if defined(NEED_PSELECT) && !defined(USE_POLL)
1118 /* XXX needs to move to the porting library. */
1119 static int
1120 pselect(int nfds, void *rfds, void *wfds, void *efds,
1121 	struct timespec *tsp, const sigset_t *sigmask)
1122 {
1123 	struct timeval tv, *tvp;
1124 	sigset_t sigs;
1125 	int n;
1126 
1127 	if (tsp) {
1128 		tvp = &tv;
1129 		tv = evTimeVal(*tsp);
1130 	} else
1131 		tvp = NULL;
1132 	if (sigmask)
1133 		sigprocmask(SIG_SETMASK, sigmask, &sigs);
1134 	n = select(nfds, rfds, wfds, efds, tvp);
1135 	if (sigmask)
1136 		sigprocmask(SIG_SETMASK, &sigs, NULL);
1137 	if (tsp)
1138 		*tsp = evTimeSpec(tv);
1139 	return (n);
1140 }
1141 #endif
1142