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