1/*
2 * Copyright (c) 1985, 1989, 1993
3 *    The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 * 	This product includes software developed by the University of
16 * 	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/*
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
36 *
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
43 *
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51 * SOFTWARE.
52 */
53
54/*
55 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
56 *
57 * Permission to use, copy, modify, and distribute this software for any
58 * purpose with or without fee is hereby granted, provided that the above
59 * copyright notice and this permission notice appear in all copies.
60 *
61 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
62 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
64 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
65 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
66 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
67 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
68 * SOFTWARE.
69 */
70
71#if defined(LIBC_SCCS) && !defined(lint)
72static const char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
73static const char rcsid[] = "$Id: res_send.c,v 1.1 2006/03/01 19:01:38 majka Exp $";
74#endif /* LIBC_SCCS and not lint */
75
76/*
77 * Send query to name server and wait for reply.
78 */
79
80#ifndef __APPLE__
81#include "port_before.h"
82#include "fd_setsize.h"
83#endif
84
85/*
86 * internal_recvfrom uses RFC 2292 API (IPV6_PKTINFO)
87 * __APPLE_USE_RFC_2292 selects the appropriate API in <netinet6/in6.h>
88 */
89#define __APPLE_USE_RFC_2292
90
91#include <sys/types.h>
92#include <sys/param.h>
93#include <sys/time.h>
94#include <sys/socket.h>
95#include <sys/uio.h>
96
97#include <netinet/in.h>
98#include <arpa/nameser.h>
99#include <arpa/inet.h>
100
101#include <errno.h>
102#include <netdb.h>
103#include <resolv.h>
104#include <signal.h>
105#include <stdio.h>
106#include <stdlib.h>
107#include <notify.h>
108#include <pthread.h>
109#include <string.h>
110#include <unistd.h>
111#include <ifaddrs.h>
112#include <net/if.h>
113#include <net/if_dl.h>
114#include "res_private.h"
115
116#ifndef __APPLE__
117#include <isc/eventlib.h>
118#include "port_after.h"
119#endif
120
121#ifdef __APPLE__
122#define ISC_SOCKLEN_T unsigned int
123#endif
124
125/* Options.  Leave them on. */
126#define DEBUG
127#define CANNOT_CONNECT_DGRAM
128#ifdef __APPLE__
129#define MULTICAST
130#endif
131
132#include "res_debug.h"
133#include "res_private.h"
134#include <sys/fcntl.h>
135
136#define EXT(res) ((res)->_u._ext)
137
138static const int highestFD = FD_SETSIZE - 1;
139
140#define MAX_HOOK_RETRIES 42
141
142/* port randomization */
143#define RANDOM_BIND_MAX_TRIES 16
144#define RANDOM_BIND_FIRST IPPORT_HIFIRSTAUTO
145#define RANDOM_BIND_LAST IPPORT_HILASTAUTO
146
147/* Forward. */
148
149static int		get_salen __P((const struct sockaddr *));
150static int		send_vc(res_state, const u_char *, int, u_char *, int *, int *, int, struct sockaddr *, int *, int);
151static int		send_dg(res_state, const u_char *, int, u_char *, int *, int *, int, int *, int *, struct sockaddr *, int *, int);
152static void		Aerror(const res_state, FILE *, const char *, int, const struct sockaddr *, int);
153static void		Perror(const res_state, FILE *, const char *, int);
154static int		sock_eq(struct sockaddr *, struct sockaddr *);
155#ifdef USE_DNS_PSELECT
156static int		dns_pselect(int, void *, void *, void *, struct timespec *, const sigset_t *);
157#endif
158
159static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
160
161/* interrupt mechanism is shared with res_query.c */
162int interrupt_pipe_enabled = 0;
163pthread_key_t interrupt_pipe_key;
164
165static int
166bind_random(int sock)
167{
168	int i, status;
169	uint16_t src_port;
170	struct sockaddr_in local;
171
172	src_port = 0;
173	status = -1;
174
175	for (i = 0; (i < RANDOM_BIND_MAX_TRIES) && (status < 0); i++)
176	{
177		/* random port in the range RANDOM_BIND_FIRST to RANDOM_BIND_LAST */
178		src_port = (res_randomid() % (RANDOM_BIND_LAST - RANDOM_BIND_FIRST)) + RANDOM_BIND_FIRST;
179		memset(&local, 0, sizeof(struct sockaddr_in));
180		local.sin_port = htons(src_port);
181
182		status = bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_in));
183	}
184
185	return status;
186}
187
188void
189res_delete_interrupt_token(void *token)
190{
191	int *interrupt_pipe;
192
193	interrupt_pipe = token;
194	if (interrupt_pipe == NULL) return;
195
196	if (interrupt_pipe[0] >= 0)
197	{
198		close(interrupt_pipe[0]);
199		interrupt_pipe[0] = -1;
200	}
201
202	if (interrupt_pipe[1] >= 0)
203	{
204		close(interrupt_pipe[1]);
205		interrupt_pipe[1] = -1;
206	}
207
208	pthread_setspecific(interrupt_pipe_key, NULL);
209	free(interrupt_pipe);
210}
211
212void *
213res_init_interrupt_token(void)
214{
215	int *interrupt_pipe;
216
217	interrupt_pipe = (int *)malloc(2 * sizeof(int));
218	if (interrupt_pipe == NULL) return NULL;
219
220	if (pipe(interrupt_pipe) < 0)
221	{
222		/* this shouldn't happen */
223		interrupt_pipe[0] = -1;
224		interrupt_pipe[1] = -1;
225	}
226	else
227	{
228		fcntl(interrupt_pipe[0], F_SETFD, FD_CLOEXEC | O_NONBLOCK);
229		fcntl(interrupt_pipe[1], F_SETFD, FD_CLOEXEC | O_NONBLOCK);
230	}
231
232	pthread_setspecific(interrupt_pipe_key, interrupt_pipe);
233
234	return interrupt_pipe;
235}
236
237void
238res_interrupt_requests_enable(void)
239{
240	interrupt_pipe_enabled = 1;
241	pthread_key_create(&interrupt_pipe_key, NULL);
242}
243
244void
245res_interrupt_requests_disable(void)
246{
247	interrupt_pipe_enabled = 0;
248	pthread_key_delete(interrupt_pipe_key);
249}
250
251void
252res_interrupt_request(void *token)
253{
254	int oldwrite;
255	int *interrupt_pipe;
256
257	interrupt_pipe = token;
258
259	if ((interrupt_pipe == NULL) || (interrupt_pipe_enabled == 0)) return;
260
261	oldwrite = interrupt_pipe[1];
262	interrupt_pipe[1] = -1;
263
264	if (oldwrite >= 0) close(oldwrite);
265}
266
267#ifdef __APPLE__
268static struct iovec
269evConsIovec(void *buf, size_t cnt)
270{
271	struct iovec ret;
272
273	memset(&ret, 0xf5, sizeof ret);
274	ret.iov_base = buf;
275	ret.iov_len = cnt;
276	return (ret);
277}
278
279static struct timespec
280evConsTime(time_t sec, long nsec)
281{
282	struct timespec x;
283
284	x.tv_sec = sec;
285	x.tv_nsec = nsec;
286	return (x);
287}
288
289static struct timespec
290evTimeSpec(struct timeval tv)
291{
292	struct timespec ts;
293
294	ts.tv_sec = tv.tv_sec;
295	ts.tv_nsec = tv.tv_usec * 1000;
296	return (ts);
297}
298
299static struct timespec
300evNowTime()
301{
302	struct timeval now;
303
304	if (gettimeofday(&now, NULL) < 0) return (evConsTime(0, 0));
305	return (evTimeSpec(now));
306}
307
308#ifdef USE_DNS_PSELECT
309static struct timeval
310evTimeVal(struct timespec ts)
311{
312	struct timeval tv;
313
314	tv.tv_sec = ts.tv_sec;
315	tv.tv_usec = ts.tv_nsec / 1000;
316	return (tv);
317}
318#endif
319
320#define BILLION 1000000000
321static struct timespec
322evAddTime(struct timespec addend1, struct timespec addend2)
323{
324	struct timespec x;
325
326	x.tv_sec = addend1.tv_sec + addend2.tv_sec;
327	x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
328	if (x.tv_nsec >= BILLION)
329	{
330		x.tv_sec++;
331		x.tv_nsec -= BILLION;
332	}
333
334	return (x);
335}
336
337static struct timespec
338evSubTime(struct timespec minuend, struct timespec subtrahend)
339{
340	struct timespec x;
341
342	x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
343	if (minuend.tv_nsec >= subtrahend.tv_nsec)
344	{
345		x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
346	}
347	else
348	{
349		x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
350		x.tv_sec--;
351	}
352
353	return (x);
354}
355
356static int
357evCmpTime(struct timespec a, struct timespec b)
358{
359	long x = a.tv_sec - b.tv_sec;
360
361	if (x == 0L) x = a.tv_nsec - b.tv_nsec;
362	return (x < 0L ? (-1) : x > 0L ? (1) : (0));
363}
364
365#endif /* __APPLE__ */
366
367/* Public. */
368
369/* int
370 * res_isourserver(ina)
371 *	looks up "ina" in _res.ns_addr_list[]
372 * returns:
373 *	0  : not found
374 *	>0 : found
375 * author:
376 *	paul vixie, 29may94
377 */
378int
379res_ourserver_p(const res_state statp, const struct sockaddr *sa)
380{
381	const struct sockaddr_in *inp, *srv;
382	const struct sockaddr_in6 *in6p, *srv6;
383	int ns;
384
385	switch (sa->sa_family)
386	{
387		case AF_INET:
388			inp = (const struct sockaddr_in *)sa;
389			for (ns = 0;  ns < statp->nscount;  ns++)
390			{
391				srv = (struct sockaddr_in *)get_nsaddr(statp, ns);
392				if (srv->sin_family == inp->sin_family &&
393					srv->sin_port == inp->sin_port &&
394					(srv->sin_addr.s_addr == INADDR_ANY ||
395					 srv->sin_addr.s_addr == inp->sin_addr.s_addr))
396					return (1);
397			}
398			break;
399		case AF_INET6:
400			if (EXT(statp).ext == NULL) break;
401			in6p = (const struct sockaddr_in6 *)sa;
402			for (ns = 0;  ns < statp->nscount;  ns++)
403			{
404				srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns);
405				if (srv6->sin6_family == in6p->sin6_family &&
406					srv6->sin6_port == in6p->sin6_port &&
407					(IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
408					 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
409					return (1);
410			}
411			break;
412		default:
413			break;
414	}
415	return (0);
416}
417
418/* int
419 * res_nameinquery(name, type, class, buf, eom)
420 *	look for (name,type,class) in the query section of packet (buf,eom)
421 * requires:
422 *	buf + NS_HFIXEDSZ <= eom
423 * returns:
424 *	-1 : format error
425 *	0  : not found
426 *	>0 : found
427 * author:
428 *	paul vixie, 29may94
429 */
430int
431res_nameinquery(const char *name, int type, int class, const u_char *buf, const u_char *eom)
432{
433	const u_char *cp = buf + NS_HFIXEDSZ;
434	int qdcount = ntohs(((const HEADER*)buf)->qdcount);
435
436	while (qdcount-- > 0)
437	{
438		char tname[NS_MAXDNAME+1];
439		int n, ttype, tclass;
440
441		n = dn_expand(buf, eom, cp, tname, sizeof tname);
442		if (n < 0) return (-1);
443
444		cp += n;
445		if (cp + 2 * NS_INT16SZ > eom) return (-1);
446
447		ttype = ns_get16(cp); cp += NS_INT16SZ;
448		tclass = ns_get16(cp); cp += NS_INT16SZ;
449		if (ttype == type && tclass == class && ns_samename(tname, name) == 1) return (1);
450	}
451
452	return (0);
453}
454
455/* int
456 * res_queriesmatch(buf1, eom1, buf2, eom2)
457 *	is there a 1:1 mapping of (name,type,class)
458 *	in (buf1,eom1) and (buf2,eom2)?
459 * returns:
460 *	-1 : format error
461 *	0  : not a 1:1 mapping
462 *	>0 : is a 1:1 mapping
463 * author:
464 *	paul vixie, 29may94
465 */
466int
467res_queriesmatch(const u_char *buf1, const u_char *eom1, const u_char *buf2, const u_char *eom2)
468{
469	const u_char *cp = buf1 + NS_HFIXEDSZ;
470	int qdcount = ntohs(((const HEADER*)buf1)->qdcount);
471
472	if (buf1 + NS_HFIXEDSZ > eom1 || buf2 + NS_HFIXEDSZ > eom2)
473		return (-1);
474
475	/*
476	 * Only header section present in replies to
477	 * dynamic update packets.
478	 */
479	if ((((const HEADER *)buf1)->opcode == ns_o_update) &&
480		(((const HEADER *)buf2)->opcode == ns_o_update))
481		return (1);
482
483	if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) return (0);
484
485	while (qdcount-- > 0)
486	{
487		char tname[NS_MAXDNAME+1];
488		int n, ttype, tclass;
489
490		n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
491		if (n < 0) return (-1);
492
493		cp += n;
494		if (cp + 2 * NS_INT16SZ > eom1) return (-1);
495
496		ttype = ns_get16(cp);	cp += NS_INT16SZ;
497		tclass = ns_get16(cp); cp += NS_INT16SZ;
498		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) return (0);
499	}
500
501	return (1);
502}
503
504int
505dns_res_send(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz, struct sockaddr *from, int *fromlen)
506{
507	int gotsomewhere, terrno, try, v_circuit, resplen, ns;
508	char abuf[NI_MAXHOST];
509	char *notify_name;
510	int notify_token, status, send_status, reply_buf_size;
511	uint64_t exit_requested;
512
513	if (statp->nscount == 0)
514	{
515		errno = ESRCH;
516		return DNS_RES_STATUS_INVALID_RES_STATE;
517	}
518
519	reply_buf_size = *anssiz;
520	if (reply_buf_size < NS_HFIXEDSZ)
521	{
522		errno = EINVAL;
523		return DNS_RES_STATUS_INVALID_ARGUMENT;
524	}
525
526	DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), (stdout, ";; res_send()\n"), buf, buflen);
527
528	v_circuit = (statp->options & RES_USEVC) || (buflen > NS_PACKETSZ);
529	gotsomewhere = 0;
530	send_status = 0;
531	terrno = ETIMEDOUT;
532
533	/*
534	 * If the ns_addr_list in the resolver context has changed, then
535	 * invalidate our cached copy and the associated timing data.
536	 */
537	if (EXT(statp).nscount != 0)
538	{
539		int needclose = 0;
540		struct sockaddr_storage peer;
541		ISC_SOCKLEN_T peerlen;
542
543		if (EXT(statp).nscount != statp->nscount)
544		{
545			needclose++;
546		}
547		else
548		{
549			for (ns = 0; ns < statp->nscount; ns++)
550			{
551				if ((statp->nsaddr_list[ns].sin_family) && (EXT(statp).ext != NULL) && (!sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])))
552				{
553					needclose++;
554					break;
555				}
556
557				if (EXT(statp).nssocks[ns] == -1) continue;
558
559				peerlen = sizeof(peer);
560				if (getsockname(EXT(statp).nssocks[ns], (struct sockaddr *)&peer, &peerlen) < 0)
561				{
562					needclose++;
563					break;
564				}
565
566				if (!sock_eq((struct sockaddr *)&peer, get_nsaddr(statp, ns)))
567				{
568					needclose++;
569					break;
570				}
571			}
572		}
573
574		if (needclose)
575		{
576			res_nclose(statp);
577			EXT(statp).nscount = 0;
578		}
579	}
580
581	/*
582	 * Maybe initialize our private copy of the ns_addr_list.
583	 */
584	if (EXT(statp).nscount == 0)
585	{
586		for (ns = 0; ns < statp->nscount; ns++)
587		{
588			EXT(statp).nstimes[ns] = RES_MAXTIME;
589			EXT(statp).nssocks[ns] = -1;
590			if (!statp->nsaddr_list[ns].sin_family) continue;
591			if (EXT(statp).ext != NULL) EXT(statp).ext->nsaddrs[ns].sin = statp->nsaddr_list[ns];
592		}
593
594		EXT(statp).nscount = statp->nscount;
595	}
596
597	/*
598	 * Some resolvers want to even out the load on their nameservers.
599	 * Note that RES_BLAST overrides RES_ROTATE.
600	 */
601	if (((statp->options & RES_ROTATE) != 0) && ((statp->options & RES_BLAST) == 0))
602	{
603		union res_sockaddr_union inu;
604		struct sockaddr_in ina;
605		int lastns = statp->nscount - 1;
606		int fd;
607		u_int16_t nstime;
608
609		if (EXT(statp).ext != NULL) inu = EXT(statp).ext->nsaddrs[0];
610		ina = statp->nsaddr_list[0];
611		fd = EXT(statp).nssocks[0];
612		nstime = EXT(statp).nstimes[0];
613
614		for (ns = 0; ns < lastns; ns++)
615		{
616			if (EXT(statp).ext != NULL)
617			{
618				EXT(statp).ext->nsaddrs[ns] =EXT(statp).ext->nsaddrs[ns + 1];
619			}
620
621			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
622			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
623			EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
624		}
625
626		if (EXT(statp).ext != NULL) EXT(statp).ext->nsaddrs[lastns] = inu;
627		statp->nsaddr_list[lastns] = ina;
628		EXT(statp).nssocks[lastns] = fd;
629		EXT(statp).nstimes[lastns] = nstime;
630	}
631
632	/*
633	 * Get notification token
634	 * we use a self-notification token to allow a caller
635	 * to signal the thread doing this DNS query to quit.
636	 */
637	notify_name = NULL;
638	notify_token = -1;
639
640	asprintf(&notify_name, "self.thread.%lu", (unsigned long)pthread_self());
641	if (notify_name != NULL)
642	{
643		status = notify_register_plain(notify_name, &notify_token);
644		free(notify_name);
645	}
646
647	/*
648	 * Send request, RETRY times, or until successful.
649	 */
650	for (try = 0; try < statp->retry; try++)
651	{
652		for (ns = 0; ns < statp->nscount; ns++)
653		{
654			struct sockaddr *nsap;
655			int nsaplen;
656			nsap = get_nsaddr(statp, ns);
657			nsaplen = get_salen(nsap);
658
659send_same_ns:
660
661			if (statp->qhook)
662			{
663				int done = 0, loops = 0;
664
665				do
666				{
667					res_sendhookact act;
668
669					act = (*statp->qhook)(&nsap, &buf, &buflen, ans, reply_buf_size, &resplen);
670					switch (act)
671					{
672						case res_goahead:
673							done = 1;
674							break;
675						case res_nextns:
676							res_nclose(statp);
677							goto send_next_ns;
678						case res_done:
679							if (notify_token != -1) notify_cancel(notify_token);
680							return DNS_RES_STATUS_CANCELLED;
681						case res_modified:
682							/* give the hook another try */
683							if (++loops < MAX_HOOK_RETRIES) break;
684							/*FALLTHROUGH*/
685						case res_error:
686							/*FALLTHROUGH*/
687						default:
688							if (notify_token != -1) notify_cancel(notify_token);
689							return DNS_RES_STATUS_CANCELLED;
690					}
691				} while (!done);
692			}
693
694			if (notify_token != -1)
695			{
696				exit_requested = 0;
697				status = notify_get_state(notify_token, &exit_requested);
698				if (exit_requested == ThreadStateExitRequested)
699				{
700					Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
701					res_nclose(statp);
702					notify_cancel(notify_token);
703					return DNS_RES_STATUS_CANCELLED;
704				}
705			}
706
707			Dprint(((statp->options & RES_DEBUG) && getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), NULL, 0, niflags) == 0), (stdout, ";; Querying server (# %d) address = %s\n", ns + 1, abuf));
708
709			send_status = ns_r_noerror;
710
711			if (v_circuit != 0)
712			{
713				/* Use VC; at most one attempt per server. */
714				try = statp->retry;
715
716				*anssiz = reply_buf_size;
717				send_status = send_vc(statp, buf, buflen, ans, anssiz, &terrno, ns, from, fromlen, notify_token);
718			}
719			else
720			{
721				/* Use datagrams. */
722				send_status = send_dg(statp, buf, buflen, ans, anssiz, &terrno, ns, &v_circuit, &gotsomewhere, from, fromlen, notify_token);
723				if (v_circuit != 0) goto send_same_ns;
724			}
725
726			if ((send_status == DNS_RES_STATUS_SYSTEM_ERROR) || (send_status == DNS_RES_STATUS_CANCELLED))
727			{
728				res_nclose(statp);
729				if (notify_token != -1) notify_cancel(notify_token);
730				return send_status;
731			}
732
733			if (send_status != ns_r_noerror) goto send_next_ns;
734
735			Dprint((statp->options & RES_DEBUG) || ((statp->pfcode & RES_PRF_REPLY) && (statp->pfcode & RES_PRF_HEAD1)), (stdout, ";; got answer:\n"));
736			DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), (stdout, "%s", ""), ans, (*anssiz > reply_buf_size) ? reply_buf_size : *anssiz);
737
738			/*
739			 * If we have temporarily opened a virtual circuit,
740			 * or if we haven't been asked to keep a socket open,
741			 * close the socket.
742			 */
743			if (((v_circuit != 0) && (statp->options & RES_USEVC) == 0) || (statp->options & RES_STAYOPEN) == 0)  res_nclose(statp);
744
745			if (statp->rhook)
746			{
747				int done = 0, loops = 0;
748
749				do
750				{
751					res_sendhookact act;
752
753					act = (*statp->rhook)(nsap, buf, buflen, ans, *anssiz, &resplen);
754					switch (act)
755					{
756						case res_goahead:
757						case res_done:
758							done = 1;
759							break;
760						case res_nextns:
761							res_nclose(statp);
762							goto send_next_ns;
763						case res_modified:
764							/* give the hook another try */
765							if (++loops < MAX_HOOK_RETRIES) break;
766							/*FALLTHROUGH*/
767						case res_error:
768							/*FALLTHROUGH*/
769						default:
770							res_nclose(statp);
771							if (notify_token != -1) notify_cancel(notify_token);
772							return DNS_RES_STATUS_CANCELLED;
773					}
774				} while (!done);
775
776			}
777
778			if (notify_token != -1) notify_cancel(notify_token);
779			return ns_r_noerror;
780
781send_next_ns: ;
782		} /* foreach ns */
783	} /* foreach retry */
784
785	res_nclose(statp);
786	if (notify_token != -1) notify_cancel(notify_token);
787
788	if (v_circuit == 0)
789	{
790		/* used datagrams */
791		if (gotsomewhere != 0)
792		{
793			errno = ECONNREFUSED;
794			return DNS_RES_STATUS_CONNECTION_REFUSED;
795		}
796
797		errno = ETIMEDOUT;
798		return DNS_RES_STATUS_TIMEOUT;
799	}
800
801	/* used v_circuit */
802	errno = terrno;
803	return send_status;
804}
805
806int
807res_nsend_2(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz, struct sockaddr *from, int *fromlen)
808{
809	int len, status;
810
811	len = anssiz;
812	status = dns_res_send(statp, buf, buflen, ans, &len, from, fromlen);
813	if (status != ns_r_noerror) len = -1;
814	return len;
815}
816
817int
818res_nsend(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz)
819{
820	struct sockaddr_storage from;
821	int fromlen;
822
823	fromlen = sizeof(struct sockaddr_storage);
824
825	return res_nsend_2(statp, buf, buflen, ans, anssiz, (struct sockaddr *)&from, &fromlen);
826}
827
828/* Private */
829
830static int
831get_salen(const struct sockaddr *sa)
832{
833#ifdef HAVE_SA_LEN
834	/* There are people do not set sa_len.  Be forgiving to them. */
835	if (sa->sa_len) return (sa->sa_len);
836#endif
837
838	if (sa->sa_family == AF_INET) return (sizeof(struct sockaddr_in));
839	else if (sa->sa_family == AF_INET6) return (sizeof(struct sockaddr_in6));
840	else return (0);	/* unknown, die on connect */
841}
842
843/*
844 * pick appropriate nsaddr_list for use.  see res_init() for initialization.
845 */
846struct sockaddr *
847get_nsaddr(res_state statp, size_t n)
848{
849	if ((!statp->nsaddr_list[n].sin_family) && (EXT(statp).ext != NULL))
850	{
851		/*
852		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
853		 *   than struct sockaddr, and
854		 * - user code did not update statp->nsaddr_list[n].
855		 */
856		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
857	}
858	else
859	{
860		/*
861		 * - user code updated statp->nsaddr_list[n], or
862		 * - statp->nsaddr_list[n] has the same content as
863		 *   EXT(statp).ext->nsaddrs[n].
864		 */
865		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
866	}
867}
868
869static int
870send_vc(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz, int *terrno, int ns, struct sockaddr *from, int *fromlen, int notify_token)
871{
872	const HEADER *hp = (const HEADER *) buf;
873	HEADER *anhp = (HEADER *) ans;
874	struct sockaddr *nsap;
875	int nsaplen;
876	int truncating, connreset, resplen, n;
877	struct iovec iov[2];
878	u_short len;
879	u_char *cp;
880	void *tmp;
881	int status;
882	uint64_t exit_requested;
883
884	nsap = get_nsaddr(statp, ns);
885	nsaplen = get_salen(nsap);
886
887	connreset = 0;
888
889vc_same_ns:
890
891	if (notify_token != -1)
892	{
893		exit_requested = 0;
894		status = notify_get_state(notify_token, &exit_requested);
895		if (exit_requested == ThreadStateExitRequested)
896		{
897			Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
898			*terrno = EINTR;
899			return DNS_RES_STATUS_CANCELLED;
900		}
901	}
902
903	truncating = 0;
904
905	/* Are we still talking to whom we want to talk? */
906	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0)
907	{
908		struct sockaddr_storage peer;
909		ISC_SOCKLEN_T size = sizeof peer;
910
911		if (getpeername(statp->_vcsock, (struct sockaddr *)&peer, &size) < 0 || !sock_eq((struct sockaddr *)&peer, nsap))
912		{
913			res_nclose(statp);
914			statp->_flags &= ~RES_F_VC;
915		}
916	}
917
918	if ((statp->_vcsock < 0) || ((statp->_flags & RES_F_VC) == 0))
919	{
920		if (statp->_vcsock >= 0) res_nclose(statp);
921
922		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
923		if (statp->_vcsock > highestFD)
924		{
925			res_nclose(statp);
926			errno = ENOTSOCK;
927		}
928
929		if (statp->_vcsock < 0)
930		{
931			*terrno = errno;
932			Perror(statp, stderr, "socket(vc)", errno);
933			return DNS_RES_STATUS_SYSTEM_ERROR;
934		}
935
936		errno = 0;
937		if (connect(statp->_vcsock, nsap, nsaplen) < 0)
938		{
939			*terrno = errno;
940			Aerror(statp, stderr, "connect(vc)", errno, nsap, nsaplen);
941			res_nclose(statp);
942			return DNS_RES_STATUS_CONNECTION_REFUSED;
943		}
944
945		statp->_flags |= RES_F_VC;
946	}
947
948	/*
949	 * Send length & message
950	 */
951	putshort((u_short)buflen, (u_char*)&len);
952	iov[0] = evConsIovec(&len, NS_INT16SZ);
953#ifdef __APPLE__
954	tmp = (char *)buf;
955#else
956	DE_CONST(buf, tmp);
957#endif
958	iov[1] = evConsIovec(tmp, buflen);
959	if (writev(statp->_vcsock, iov, 2) != (NS_INT16SZ + buflen))
960	{
961		*terrno = errno;
962		Perror(statp, stderr, "write failed", errno);
963		res_nclose(statp);
964		return DNS_RES_STATUS_CONNECTION_FAILED;
965	}
966
967	/*
968	 * Receive length & response
969	 */
970 read_len:
971
972	if (notify_token != -1)
973	{
974		exit_requested = 0;
975		status = notify_get_state(notify_token, &exit_requested);
976		if (exit_requested == ThreadStateExitRequested)
977		{
978			Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
979			*terrno = EINTR;
980			return DNS_RES_STATUS_CANCELLED;
981		}
982	}
983
984	cp = ans;
985	len = NS_INT16SZ;
986	while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0)
987	{
988		cp += n;
989		if ((len -= n) <= 0) break;
990	}
991
992	if (n <= 0)
993	{
994		*terrno = errno;
995		Perror(statp, stderr, "read failed", errno);
996		res_nclose(statp);
997
998		/*
999		 * A long running process might get its TCP
1000		 * connection reset if the remote server was
1001		 * restarted.  Requery the server instead of
1002		 * trying a new one.  When there is only one
1003		 * server, this means that a query might work
1004		 * instead of failing.  We only allow one reset
1005		 * per query to prevent looping.
1006		 */
1007		if (*terrno == ECONNRESET && !connreset)
1008		{
1009			connreset = 1;
1010			res_nclose(statp);
1011			goto vc_same_ns;
1012		}
1013
1014		res_nclose(statp);
1015		return DNS_RES_STATUS_CONNECTION_FAILED;
1016	}
1017
1018	resplen = ns_get16(ans);
1019	if (resplen > *anssiz)
1020	{
1021		Dprint(statp->options & RES_DEBUG, (stdout, ";; response truncated\n"));
1022		truncating = 1;
1023		len = *anssiz;
1024	}
1025	else
1026	{
1027		len = resplen;
1028	}
1029
1030	if (len < NS_HFIXEDSZ)
1031	{
1032		/*
1033		 * Undersized message.
1034		 */
1035		Dprint(statp->options & RES_DEBUG, (stdout, ";; undersized: %d\n", len));
1036		*terrno = EMSGSIZE;
1037		res_nclose(statp);
1038		*anssiz = 0;
1039		return DNS_RES_STATUS_INVALID_REPLY;
1040	}
1041
1042	cp = ans;
1043	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0)
1044	{
1045		cp += n;
1046		len -= n;
1047	}
1048
1049	if (n <= 0)
1050	{
1051		*terrno = errno;
1052		Perror(statp, stderr, "read(vc)", errno);
1053		res_nclose(statp);
1054		return DNS_RES_STATUS_CONNECTION_FAILED;
1055	}
1056
1057	if (truncating)
1058	{
1059		/*
1060		 * Flush rest of answer so connection stays in synch.
1061		 */
1062		anhp->tc = 1;
1063		len = resplen - *anssiz;
1064		while (len != 0)
1065		{
1066			char junk[NS_PACKETSZ];
1067
1068			n = read(statp->_vcsock, junk, (len > sizeof junk) ? sizeof junk : len);
1069			if (n > 0) len -= n;
1070			else break;
1071		}
1072	}
1073
1074	/*
1075	 * If the calling applicating has bailed out of
1076	 * a previous call and failed to arrange to have
1077	 * the circuit closed or the server has got
1078	 * itself confused, then drop the packet and
1079	 * wait for the correct one.
1080	 */
1081	if (hp->id != anhp->id)
1082	{
1083		DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), (stdout, ";; old answer (unexpected):\n"), ans, (resplen > *anssiz) ? *anssiz : resplen);
1084		goto read_len;
1085	}
1086
1087	/*
1088	 * All is well, or the error is fatal.  Signal that the
1089	 * next nameserver ought not be tried.
1090	 */
1091
1092	*fromlen = sizeof(nsap);
1093	memcpy(from, &nsap, *fromlen);
1094	*anssiz = resplen;
1095	return ns_r_noerror;
1096}
1097
1098static ssize_t
1099internal_recvfrom(int s, void *buf, size_t len, struct sockaddr *from, int *fromlen, int *iface)
1100{
1101	struct sockaddr_dl *sdl;
1102	struct iovec databuffers = { buf, len };
1103	struct msghdr msg;
1104	ssize_t n;
1105	struct cmsghdr *cmp;
1106	char ancillary[1024], ifname[IF_NAMESIZE];
1107	struct in6_pktinfo *ip6_info;
1108	struct sockaddr_in *s4;
1109	struct sockaddr_in6 *s6;
1110
1111	memset(&msg, 0, sizeof(struct msghdr));
1112	msg.msg_name = (caddr_t)from;
1113	msg.msg_namelen = *fromlen;
1114	msg.msg_iov = &databuffers;
1115	msg.msg_iovlen = 1;
1116	msg.msg_control = (caddr_t)&ancillary;
1117	msg.msg_controllen = sizeof(ancillary);
1118
1119	/* Receive the data */
1120	n = recvmsg(s, &msg, 0);
1121	if ((n < 0) || (msg.msg_controllen < sizeof(struct cmsghdr)) || (msg.msg_flags & MSG_CTRUNC))
1122	{
1123		return n;
1124	}
1125
1126	*fromlen = msg.msg_namelen;
1127
1128	s4 = (struct sockaddr_in *)from;
1129	s6 = (struct sockaddr_in6 *)from;
1130
1131	for (cmp = CMSG_FIRSTHDR(&msg); cmp; cmp = CMSG_NXTHDR(&msg, cmp))
1132	{
1133		if ((cmp->cmsg_level == IPPROTO_IP) && (cmp->cmsg_type == IP_RECVIF))
1134		{
1135			sdl = (struct sockaddr_dl *)CMSG_DATA(cmp);
1136			if (sdl->sdl_nlen < IF_NAMESIZE)
1137			{
1138				memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
1139				ifname[sdl->sdl_nlen] = 0;
1140				*iface = if_nametoindex(ifname);
1141			}
1142		}
1143		else if ((cmp->cmsg_level == IPPROTO_IPV6) && (cmp->cmsg_type == IPV6_PKTINFO))
1144		{
1145			ip6_info = (struct in6_pktinfo *)CMSG_DATA(cmp);
1146			*iface = ip6_info->ipi6_ifindex;
1147		}
1148	}
1149
1150	return n;
1151}
1152
1153static int
1154send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz, int *terrno, int ns, int *v_circuit, int *gotsomewhere, struct sockaddr *from, int *fromlen, int notify_token)
1155{
1156	const HEADER *hp = (const HEADER *) buf;
1157	HEADER *anhp = (HEADER *) ans;
1158	const struct sockaddr *nsap;
1159	int nsaplen, nfds;
1160	struct timespec now, timeout, finish;
1161	fd_set dsmask;
1162	int iface, rif, status;
1163	uint64_t exit_requested;
1164	int *interrupt_pipe;
1165#ifndef __APPLE__
1166	struct sockaddr_storage from;
1167	ISC_SOCKLEN_T fromlen;
1168#endif
1169	int resplen, seconds, ntry, n, s;
1170#ifdef MULTICAST
1171	int multicast;
1172#endif
1173
1174	interrupt_pipe = NULL;
1175
1176	nsap = get_nsaddr(statp, ns);
1177	nsaplen = get_salen(nsap);
1178	if (EXT(statp).nssocks[ns] == -1)
1179	{
1180		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
1181		if (EXT(statp).nssocks[ns] > highestFD)
1182		{
1183			res_nclose(statp);
1184			errno = ENOTSOCK;
1185		}
1186
1187		if (EXT(statp).nssocks[ns] < 0)
1188		{
1189			*terrno = errno;
1190			Perror(statp, stderr, "socket(dg)", errno);
1191			return DNS_RES_STATUS_SYSTEM_ERROR;
1192		}
1193
1194		bind_random(EXT(statp).nssocks[ns]);
1195
1196#ifndef CANNOT_CONNECT_DGRAM
1197		/*
1198		 * On a 4.3BSD+ machine (client and server,
1199		 * actually), sending to a nameserver datagram
1200		 * port with no nameserver will cause an
1201		 * ICMP port unreachable message to be returned.
1202		 * If our datagram socket is "connected" to the
1203		 * server, we get an ECONNREFUSED error on the next
1204		 * socket operation, and select returns if the
1205		 * error message is received.  We can thus detect
1206		 * the absence of a nameserver without timing out.
1207		 */
1208		if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0)
1209		{
1210			Aerror(statp, stderr, "connect(dg)", errno, nsap, nsaplen);
1211			res_nclose(statp);
1212			return DNS_RES_STATUS_CONNECTION_REFUSED;
1213		}
1214
1215#endif /* !CANNOT_CONNECT_DGRAM */
1216		Dprint(statp->options & RES_DEBUG, (stdout, ";; new DG socket\n"))
1217	}
1218
1219	s = EXT(statp).nssocks[ns];
1220	rif = 1;
1221	setsockopt(s, IPPROTO_IP, IP_RECVIF, &rif, sizeof(int));
1222	setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &rif, sizeof(int));
1223
1224#ifdef MULTICAST
1225	multicast = 0;
1226
1227	if ((nsap->sa_family == AF_INET) && (IN_MULTICAST(ntohl(((struct sockaddr_in *)nsap)->sin_addr.s_addr)))) multicast = AF_INET;
1228	else if ((nsap->sa_family == AF_INET6) && (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)nsap)->sin6_addr))) multicast = AF_INET6;
1229
1230	if (multicast != 0)
1231	{
1232		struct ifaddrs *ifa, *p;
1233		struct sockaddr_in *sin4;
1234		struct sockaddr_in6 *sin6;
1235		int i, ifnum;
1236
1237		if (getifaddrs(&ifa) < 0)
1238		{
1239				Aerror(statp, stderr, "getifaddrs", errno, nsap, nsaplen);
1240				res_nclose(statp);
1241				return DNS_RES_STATUS_SYSTEM_ERROR;
1242		}
1243
1244		for (p = ifa; p != NULL; p = p->ifa_next)
1245		{
1246			if (p->ifa_addr == NULL) continue;
1247			if ((p->ifa_flags & IFF_UP) == 0) continue;
1248			if (p->ifa_addr->sa_family != multicast) continue;
1249			if ((p->ifa_flags & IFF_MULTICAST) == 0) continue;
1250			if ((p->ifa_flags & IFF_POINTOPOINT) != 0)
1251			{
1252				if ((multicast == AF_INET) && (ntohl(((struct sockaddr_in *)nsap)->sin_addr.s_addr) <= INADDR_MAX_LOCAL_GROUP)) continue;
1253			}
1254
1255			sin4 = (struct sockaddr_in *)p->ifa_addr;
1256			sin6 = (struct sockaddr_in6 *)p->ifa_addr;
1257			i = -1;
1258			if (multicast == AF_INET) i = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &sin4->sin_addr, sizeof(sin4->sin_addr));
1259			else if (multicast == AF_INET6)
1260			{
1261				ifnum = if_nametoindex(p->ifa_name);
1262				((struct sockaddr_in6 *)nsap)->sin6_scope_id = ifnum;
1263				i = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifnum, sizeof(ifnum));
1264			}
1265
1266			if (i < 0)
1267			{
1268				Aerror(statp, stderr, "setsockopt", errno, nsap, nsaplen);
1269				if (multicast == AF_INET6) ((struct sockaddr_in6 *)nsap)->sin6_scope_id = 0;
1270
1271				continue;
1272			}
1273
1274			if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
1275			{
1276				Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
1277				if (multicast == AF_INET6) ((struct sockaddr_in6 *)nsap)->sin6_scope_id = 0;
1278				continue;
1279			}
1280
1281			if (multicast == AF_INET6) ((struct sockaddr_in6 *)nsap)->sin6_scope_id = 0;
1282		}
1283
1284
1285		freeifaddrs(ifa);
1286	}
1287	else
1288	{
1289#endif /* MULTICAST */
1290
1291#ifndef CANNOT_CONNECT_DGRAM
1292	if (send(s, (const char*)buf, buflen, 0) != buflen)
1293	{
1294		Perror(statp, stderr, "send", errno);
1295		res_nclose(statp);
1296		return DNS_RES_STATUS_CONNECTION_FAILED;
1297	}
1298
1299#else /* !CANNOT_CONNECT_DGRAM */
1300	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
1301	{
1302		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
1303		res_nclose(statp);
1304		return DNS_RES_STATUS_CONNECTION_FAILED;
1305	}
1306#endif /* !CANNOT_CONNECT_DGRAM */
1307
1308#ifdef MULTICAST
1309	}
1310#endif /* MULTICAST */
1311
1312	/*
1313	 * Wait for reply.
1314	 */
1315#ifdef __APPLE__
1316	ntry = statp->nscount * statp->retry;
1317	seconds = statp->retrans / ntry;
1318	if (seconds <= 0) seconds = 1;
1319	timeout.tv_sec = seconds;
1320	timeout.tv_nsec = ((statp->retrans - (seconds * ntry)) * 1000) / ntry;
1321	timeout.tv_nsec *= 1000000;
1322	now = evNowTime();
1323	finish = evAddTime(now, timeout);
1324
1325	if (interrupt_pipe_enabled != 0) interrupt_pipe = pthread_getspecific(interrupt_pipe_key);
1326#else
1327	seconds = (statp->retrans << ns);
1328	if (ns > 0) seconds /= statp->nscount;
1329	if (seconds <= 0) seconds = 1;
1330	now = evNowTime();
1331	timeout = evConsTime(seconds, 0);
1332	finish = evAddTime(now, timeout);
1333#endif /* __APPLE__ */
1334	goto nonow;
1335
1336wait:
1337	now = evNowTime();
1338
1339nonow:
1340
1341	if (notify_token != -1)
1342	{
1343		exit_requested = 0;
1344		status = notify_get_state(notify_token, &exit_requested);
1345		if (exit_requested == ThreadStateExitRequested)
1346		{
1347			Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
1348			return DNS_RES_STATUS_CANCELLED;
1349		}
1350	}
1351
1352	FD_ZERO(&dsmask);
1353	FD_SET(s, &dsmask);
1354
1355	nfds = s + 1;
1356	if ((interrupt_pipe_enabled != 0) && (interrupt_pipe != NULL))
1357	{
1358		if (interrupt_pipe[0] >= 0)
1359		{
1360			FD_SET(interrupt_pipe[0], &dsmask);
1361			nfds = MAX(s, interrupt_pipe[0]) + 1;
1362		}
1363	}
1364
1365	if (evCmpTime(finish, now) > 0) timeout = evSubTime(finish, now);
1366	else timeout = evConsTime(0, 0);
1367
1368#ifdef USE_DNS_PSELECT
1369	n = dns_pselect(nfds, &dsmask, NULL, NULL, &timeout, NULL);
1370#else
1371	n = pselect(nfds, &dsmask, NULL, NULL, &timeout, NULL);
1372#endif
1373	if (n == 0)
1374	{
1375		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1376		*gotsomewhere = 1;
1377		return DNS_RES_STATUS_TIMEOUT;
1378	}
1379
1380	if (n < 0)
1381	{
1382		if (errno == EINTR) goto wait;
1383		Perror(statp, stderr, "select", errno);
1384		res_nclose(statp);
1385		return DNS_RES_STATUS_SYSTEM_ERROR;
1386	}
1387
1388	/* socket s and/or interrupt pipe got data */
1389	if ((interrupt_pipe_enabled != 0) && (interrupt_pipe != NULL) && ((interrupt_pipe[0] < 0) || (FD_ISSET(interrupt_pipe[0], &dsmask))))
1390	{
1391		Dprint(statp->options & RES_DEBUG, (stdout, ";; cancelled\n"));
1392		return DNS_RES_STATUS_CANCELLED;
1393	}
1394
1395	errno = 0;
1396	iface = 0;
1397	resplen = internal_recvfrom(s, (char *)ans, *anssiz, from, fromlen, &iface);
1398	if (resplen <= 0)
1399	{
1400		Perror(statp, stderr, "recvfrom", errno);
1401		res_nclose(statp);
1402		return DNS_RES_STATUS_CONNECTION_FAILED;
1403	}
1404
1405	if (nsap->sa_family == AF_INET) memcpy(((struct sockaddr_in *)from)->sin_zero, &iface, 4);
1406	else if (nsap->sa_family == AF_INET6) ((struct sockaddr_in6 *)from)->sin6_scope_id = iface;
1407
1408	*gotsomewhere = 1;
1409	if (resplen < NS_HFIXEDSZ)
1410	{
1411		/*
1412		 * Undersized message.
1413		 */
1414		Dprint(statp->options & RES_DEBUG, (stdout, ";; undersized: %d\n", resplen));
1415		*terrno = EMSGSIZE;
1416		res_nclose(statp);
1417		return DNS_RES_STATUS_INVALID_REPLY;
1418	}
1419
1420	if (hp->id != anhp->id)
1421	{
1422		/*
1423		 * response from old query, ignore it.
1424		 * XXX - potential security hazard could
1425		 *	 be detected here.
1426		 */
1427		DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), (stdout, ";; old answer:\n"), ans, (resplen > *anssiz) ? *anssiz : resplen);
1428		goto wait;
1429	}
1430
1431#ifdef MULTICAST
1432	if (multicast == 0)
1433	{
1434#endif /* MULTICAST */
1435
1436	if (!(statp->options & RES_INSECURE1) && !res_ourserver_p(statp, from))
1437	{
1438		/*
1439		 * response from wrong server? ignore it.
1440		 * XXX - potential security hazard could
1441		 *	 be detected here.
1442		 */
1443		DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), (stdout, ";; not our server:\n"), ans, (resplen > *anssiz) ? *anssiz : resplen);
1444		goto wait;
1445	}
1446
1447#ifdef MULTICAST
1448	}
1449#endif /* MULTICAST */
1450
1451#ifdef RES_USE_EDNS0
1452	if (anhp->rcode == ns_r_formerr && (statp->options & RES_USE_EDNS0) != 0)
1453	{
1454		/*
1455		 * Do not retry if the server do not understand EDNS0.
1456		 * The case has to be captured here, as FORMERR packet do not
1457		 * carry query section, hence res_queriesmatch() returns 0.
1458		 */
1459		DprintQ(statp->options & RES_DEBUG, (stdout, "server rejected query with EDNS0:\n"), ans, (resplen > *anssiz) ? *anssiz : resplen);
1460		/* record the error */
1461		statp->_flags |= RES_F_EDNS0ERR;
1462		res_nclose(statp);
1463		return DNS_RES_STATUS_CONNECTION_REFUSED;
1464	}
1465#endif
1466
1467	if (!(statp->options & RES_INSECURE2) && !res_queriesmatch(buf, buf + buflen, ans, ans + *anssiz))
1468	{
1469		/*
1470		 * response contains wrong query? ignore it.
1471		 * XXX - potential security hazard could
1472		 *	 be detected here.
1473		 */
1474		DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), (stdout, ";; wrong query name:\n"), ans, (resplen > *anssiz) ? *anssiz : resplen);
1475		res_nclose(statp);
1476		return DNS_RES_STATUS_INVALID_REPLY;
1477	}
1478
1479	if (anhp->rcode == ns_r_servfail || anhp->rcode == ns_r_notimpl || anhp->rcode == ns_r_refused)
1480	{
1481		DprintQ(statp->options & RES_DEBUG, (stdout, "server rejected query:\n"), ans, (resplen > *anssiz) ? *anssiz : resplen);
1482		res_nclose(statp);
1483		/* don't retry if called from dig */
1484		if (!statp->pfcode) return anhp->rcode;
1485	}
1486
1487	if (!(statp->options & RES_IGNTC) && anhp->tc)
1488	{
1489		/*
1490		 * To get the rest of answer,
1491		 * use TCP with same server.
1492		 */
1493		Dprint(statp->options & RES_DEBUG, (stdout, ";; truncated answer\n"));
1494		*v_circuit = 1;
1495		res_nclose(statp);
1496		return ns_r_noerror;
1497	}
1498
1499	/*
1500	 * All is well, or the error is fatal.  Signal that the
1501	 * next nameserver ought not be tried.
1502	 */
1503	*anssiz = resplen;
1504	return ns_r_noerror;
1505}
1506
1507static void
1508Aerror(const res_state statp, FILE *file, const char *string, int error, const struct sockaddr *address, int alen)
1509{
1510	int save = errno;
1511	char hbuf[NI_MAXHOST];
1512	char sbuf[NI_MAXSERV];
1513
1514	if ((statp->options & RES_DEBUG) != 0)
1515	{
1516		if (getnameinfo(address, alen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), niflags))
1517		{
1518			strncpy(hbuf, "?", sizeof(hbuf) - 1);
1519			hbuf[sizeof(hbuf) - 1] = '\0';
1520			strncpy(sbuf, "?", sizeof(sbuf) - 1);
1521			sbuf[sizeof(sbuf) - 1] = '\0';
1522		}
1523
1524		fprintf(file, "res_send: %s ([%s].%s): %s\n", string, hbuf, sbuf, strerror(error));
1525	}
1526
1527	errno = save;
1528}
1529
1530static void
1531Perror(const res_state statp, FILE *file, const char *string, int error)
1532{
1533	int save = errno;
1534
1535	if ((statp->options & RES_DEBUG) != 0) fprintf(file, "res_send: %s: %s\n", string, strerror(error));
1536	errno = save;
1537}
1538
1539static int
1540sock_eq(struct sockaddr *a, struct sockaddr *b)
1541{
1542	struct sockaddr_in *a4, *b4;
1543	struct sockaddr_in6 *a6, *b6;
1544
1545	if (a->sa_family != b->sa_family) return 0;
1546
1547	switch (a->sa_family)
1548	{
1549		case AF_INET:
1550			a4 = (struct sockaddr_in *)a;
1551			b4 = (struct sockaddr_in *)b;
1552			return a4->sin_port == b4->sin_port &&	a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1553		case AF_INET6:
1554			a6 = (struct sockaddr_in6 *)a;
1555			b6 = (struct sockaddr_in6 *)b;
1556			return a6->sin6_port == b6->sin6_port &&
1557#ifdef HAVE_SIN6_SCOPE_ID
1558				a6->sin6_scope_id == b6->sin6_scope_id &&
1559#endif
1560				IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1561		default:
1562			return 0;
1563	}
1564}
1565
1566#ifdef USE_DNS_PSELECT
1567static int
1568dns_pselect(int nfds, void *rfds, void *wfds, void *efds, struct timespec *tsp, const sigset_t *sigmask)
1569{
1570	struct timeval tv, *tvp = NULL;
1571	sigset_t sigs;
1572	int n;
1573
1574	if (tsp)
1575	{
1576		tvp = &tv;
1577		tv = evTimeVal(*tsp);
1578	}
1579
1580	if (sigmask) sigprocmask(SIG_SETMASK, sigmask, &sigs);
1581	n = select(nfds, rfds, wfds, efds, tvp);
1582	if (sigmask) sigprocmask(SIG_SETMASK, &sigs, NULL);
1583	if (tsp) *tsp = evTimeSpec(tv);
1584	return n;
1585}
1586#endif
1587