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