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(¬ify_name, "self.thread.%lu", (unsigned long)pthread_self()); 641 if (notify_name != NULL) 642 { 643 status = notify_register_plain(notify_name, ¬ify_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