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