1 /* 2 * Copyright (c) 1985, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Portions copyright (c) 1999, 2000 6 * Intel Corporation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * 23 * This product includes software developed by the University of 24 * California, Berkeley, Intel Corporation, and its contributors. 25 * 26 * 4. Neither the name of University, Intel Corporation, or their respective 27 * contributors may be used to endorse or promote products derived from 28 * this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND 31 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 32 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS, 34 * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 * 42 */ 43 44 /* 45 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 46 * 47 * Permission to use, copy, modify, and distribute this software for any 48 * purpose with or without fee is hereby granted, provided that the above 49 * copyright notice and this permission notice appear in all copies, and that 50 * the name of Digital Equipment Corporation not be used in advertising or 51 * publicity pertaining to distribution of the document or software without 52 * specific, written prior permission. 53 * 54 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 55 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 57 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 58 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 59 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 60 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 61 * SOFTWARE. 62 */ 63 64 /* 65 * Portions Copyright (c) 1996 by Internet Software Consortium. 66 * 67 * Permission to use, copy, modify, and distribute this software for any 68 * purpose with or without fee is hereby granted, provided that the above 69 * copyright notice and this permission notice appear in all copies. 70 * 71 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 72 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 73 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 74 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 75 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 76 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 77 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 78 * SOFTWARE. 79 */ 80 81 #if defined(LIBC_SCCS) && !defined(lint) 82 static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 83 static char orig_rcsid[] = "From: Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $"; 84 static char rcsid[] = "$Id: res_send.c,v 1.1.1.1 2003/11/19 01:51:39 kyu3 Exp $"; 85 #endif /* LIBC_SCCS and not lint */ 86 87 /* 88 * Send query to name server and wait for reply. 89 */ 90 91 #include <sys/types.h> 92 #include <sys/param.h> 93 #include <sys/select.h> 94 #include <sys/socket.h> 95 #include <sys/time.h> 96 #include <sys/uio.h> 97 98 #include <netinet/in.h> 99 #include <arpa/nameser.h> 100 #include <arpa/inet.h> 101 102 #include <errno.h> 103 #include <netdb.h> 104 #include <resolv.h> 105 #include <stdio.h> 106 #include <stdlib.h> 107 #include <string.h> 108 #include <unistd.h> 109 110 #include "res_config.h" 111 112 #ifndef _ORG_FREEBSD_ 113 #define NOPOLL 114 #endif 115 116 #ifdef NOPOLL /* libc_r doesn't wrap poll yet() */ 117 #else 118 #include <poll.h> 119 static int use_poll = 1; /* adapt to poll() syscall availability */ 120 /* 0 = not present, 1 = try it, 2 = exists */ 121 #endif 122 123 static int s = -1; /* socket used for communications */ 124 static int connected = 0; /* is the socket connected */ 125 static int vc = 0; /* is the socket a virtual circuit? */ 126 static res_send_qhook Qhook = NULL; 127 static res_send_rhook Rhook = NULL; 128 129 130 #define CAN_RECONNECT 1 131 132 #ifndef DEBUG 133 # define Dprint(cond, args) /*empty*/ 134 # define DprintQ(cond, args, query, size) /*empty*/ 135 # define Aerror(file, string, error, address) /*empty*/ 136 # define Perror(file, string, error) /*empty*/ 137 #else 138 # define Dprint(cond, args) if (cond) {fprintf args;} else {} 139 # define DprintQ(cond, args, query, size) if (cond) {\ 140 fprintf args;\ 141 __fp_nquery(query, size, stdout);\ 142 } else {} 143 144 static void 145 Aerror( 146 FILE *file, 147 char *string, 148 int error, 149 struct sockaddr_in address 150 ) 151 { 152 int save = errno; 153 154 if (_res.options & RES_DEBUG) { 155 fprintf(file, "res_send: %s ([%s].%u): %s\n", 156 string, 157 inet_ntoa(address.sin_addr), 158 ntohs(address.sin_port), 159 strerror(error)); 160 } 161 errno = save; 162 } 163 164 165 static void 166 Perror( 167 FILE *file, 168 char *string, 169 int error 170 ) 171 { 172 int save = errno; 173 174 if (_res.options & RES_DEBUG) { 175 fprintf(file, "res_send: %s: %s\n", 176 string, strerror(error)); 177 } 178 errno = save; 179 } 180 #endif 181 182 void 183 res_send_setqhook( 184 res_send_qhook hook 185 ) 186 { 187 188 Qhook = hook; 189 } 190 191 void 192 res_send_setrhook( 193 res_send_rhook hook 194 ) 195 { 196 197 Rhook = hook; 198 } 199 200 /* int 201 * res_isourserver(ina) 202 * looks up "ina" in _res.ns_addr_list[] 203 * returns: 204 * 0 : not found 205 * >0 : found 206 * author: 207 * paul vixie, 29may94 208 */ 209 int 210 res_isourserver( 211 const struct sockaddr_in *inp 212 ) 213 { 214 struct sockaddr_in ina; 215 int ns, ret; 216 217 ina = *inp; 218 ret = 0; 219 for (ns = 0; ns < _res.nscount; ns++) { 220 const struct sockaddr_in *srv = &_res.nsaddr_list[ns]; 221 222 if (srv->sin_family == ina.sin_family && 223 srv->sin_port == ina.sin_port && 224 (srv->sin_addr.s_addr == INADDR_ANY || 225 srv->sin_addr.s_addr == ina.sin_addr.s_addr)) { 226 ret++; 227 break; 228 } 229 } 230 return (ret); 231 } 232 233 /* int 234 * res_nameinquery(name, type, class, buf, eom) 235 * look for (name,type,class) in the query section of packet (buf,eom) 236 * requires: 237 * buf + HFIXEDSZ <= eom 238 * returns: 239 * -1 : format error 240 * 0 : not found 241 * >0 : found 242 * author: 243 * paul vixie, 29may94 244 */ 245 int 246 res_nameinquery( 247 const char *name, 248 int type, 249 int class, 250 const u_char *buf, 251 const u_char *eom 252 ) 253 { 254 const u_char *cp = buf + HFIXEDSZ; 255 int qdcount = ntohs(((HEADER*)buf)->qdcount); 256 257 while (qdcount-- > 0) { 258 char tname[MAXDNAME+1]; 259 int n, ttype, tclass; 260 261 n = dn_expand(buf, eom, cp, tname, sizeof tname); 262 if (n < 0) 263 return (-1); 264 cp += n; 265 if (cp + 2 * INT16SZ > eom) 266 return (-1); 267 ttype = ns_get16(cp); cp += INT16SZ; 268 tclass = ns_get16(cp); cp += INT16SZ; 269 if (ttype == type && 270 tclass == class && 271 strcasecmp(tname, name) == 0) 272 return (1); 273 } 274 return (0); 275 } 276 277 /* int 278 * res_queriesmatch(buf1, eom1, buf2, eom2) 279 * is there a 1:1 mapping of (name,type,class) 280 * in (buf1,eom1) and (buf2,eom2)? 281 * returns: 282 * -1 : format error 283 * 0 : not a 1:1 mapping 284 * >0 : is a 1:1 mapping 285 * author: 286 * paul vixie, 29may94 287 */ 288 int 289 res_queriesmatch( 290 const u_char *buf1, 291 const u_char *eom1, 292 const u_char *buf2, 293 const u_char *eom2 294 ) 295 { 296 const u_char *cp = buf1 + HFIXEDSZ; 297 int qdcount = ntohs(((HEADER*)buf1)->qdcount); 298 299 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 300 return (-1); 301 302 /* 303 * Only header section present in replies to 304 * dynamic update packets. 305 */ 306 if ( (((HEADER *)buf1)->opcode == ns_o_update) && 307 (((HEADER *)buf2)->opcode == ns_o_update) ) 308 return (1); 309 310 if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) 311 return (0); 312 while (qdcount-- > 0) { 313 char tname[MAXDNAME+1]; 314 int n, ttype, tclass; 315 316 n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 317 if (n < 0) 318 return (-1); 319 cp += n; 320 if (cp + 2 * INT16SZ > eom1) 321 return (-1); 322 ttype = ns_get16(cp); cp += INT16SZ; 323 tclass = ns_get16(cp); cp += INT16SZ; 324 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 325 return (0); 326 } 327 return (1); 328 } 329 330 int 331 res_send( 332 const u_char *buf, 333 int buflen, 334 u_char *ans, 335 int anssiz 336 ) 337 { 338 HEADER *hp = (HEADER *) buf; 339 HEADER *anhp = (HEADER *) ans; 340 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; 341 ssize_t n; 342 u_int32_t badns; /* XXX NSMAX can't exceed #/bits in this variable */ 343 344 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 345 /* errno should have been set by res_init() in this case. */ 346 return (-1); 347 } 348 if (anssiz < HFIXEDSZ) { 349 errno = EINVAL; 350 return (-1); 351 } 352 DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), 353 (stdout, ";; res_send()\n"), buf, buflen); 354 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 355 gotsomewhere = 0; 356 connreset = 0; 357 terrno = ETIMEDOUT; 358 badns = 0; 359 360 /* 361 * Send request, RETRY times, or until successful 362 */ 363 for (try = 0; try < _res.retry; try++) { 364 for (ns = 0; ns < _res.nscount; ns++) { 365 struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; 366 same_ns: 367 if (badns & (1 << ns)) { 368 res_close(); 369 goto next_ns; 370 } 371 372 if (Qhook) { 373 int done = 0, loops = 0; 374 375 do { 376 res_sendhookact act; 377 378 act = (*Qhook)(&nsap, &buf, &buflen, 379 ans, anssiz, &resplen); 380 switch (act) { 381 case res_goahead: 382 done = 1; 383 break; 384 case res_nextns: 385 res_close(); 386 goto next_ns; 387 case res_done: 388 return (resplen); 389 case res_modified: 390 /* give the hook another try */ 391 if (++loops < 42) /*doug adams*/ 392 break; 393 /*FALLTHROUGH*/ 394 case res_error: 395 /*FALLTHROUGH*/ 396 default: 397 return (-1); 398 } 399 } while (!done); 400 } 401 402 Dprint(_res.options & RES_DEBUG, 403 (stdout, ";; Querying server (# %d) address = %s\n", 404 ns + 1, inet_ntoa(nsap->sin_addr))); 405 406 if (v_circuit) { 407 int truncated; 408 struct iovec iov[2]; 409 u_short len; 410 u_char *cp; 411 412 /* 413 * Use virtual circuit; 414 * at most one attempt per server. 415 */ 416 try = _res.retry; 417 truncated = 0; 418 if (s < 0 || !vc || hp->opcode == ns_o_update) { 419 if (s >= 0) 420 res_close(); 421 422 s = socket(PF_INET, SOCK_STREAM, 0); 423 if (s < 0) { 424 terrno = errno; 425 Perror(stderr, "socket(vc)", errno); 426 return (-1); 427 } 428 errno = 0; 429 nsap->sin_len = sizeof ( *nsap ); 430 if (connect(s, (struct sockaddr *)nsap, 431 sizeof *nsap) < 0) { 432 terrno = errno; 433 Aerror(stderr, "connect/vc", 434 errno, *nsap); 435 badns |= (1 << ns); 436 res_close(); 437 goto next_ns; 438 } 439 vc = 1; 440 } 441 /* 442 * Send length & message 443 */ 444 putshort((u_short)buflen, (u_char*)&len); 445 iov[0].iov_base = (caddr_t)&len; 446 iov[0].iov_len = INT16SZ; 447 iov[1].iov_base = (caddr_t)buf; 448 iov[1].iov_len = buflen; 449 if (writev(s, iov, 2) != (INT16SZ + buflen)) { 450 terrno = errno; 451 Perror(stderr, "write failed", errno); 452 badns |= (1 << ns); 453 res_close(); 454 goto next_ns; 455 } 456 /* 457 * Receive length & response 458 */ 459 read_len: 460 cp = ans; 461 len = INT16SZ; 462 while ((n = read(s, (char *)cp, (int)len)) > 0) { 463 cp += n; 464 len = (u_short)( len - n ); 465 if (len <= 0) 466 break; 467 } 468 if (n <= 0) { 469 terrno = errno; 470 Perror(stderr, "read failed", errno); 471 res_close(); 472 /* 473 * A long running process might get its TCP 474 * connection reset if the remote server was 475 * restarted. Requery the server instead of 476 * trying a new one. When there is only one 477 * server, this means that a query might work 478 * instead of failing. We only allow one reset 479 * per query to prevent looping. 480 */ 481 if (terrno == ECONNRESET && !connreset) { 482 connreset = 1; 483 res_close(); 484 goto same_ns; 485 } 486 res_close(); 487 goto next_ns; 488 } 489 resplen = ns_get16(ans); 490 if (resplen > anssiz) { 491 Dprint(_res.options & RES_DEBUG, 492 (stdout, ";; response truncated\n") 493 ); 494 truncated = 1; 495 len = (ushort)anssiz; 496 } else 497 len = (ushort)resplen; 498 if (len < HFIXEDSZ) { 499 /* 500 * Undersized message. 501 */ 502 Dprint(_res.options & RES_DEBUG, 503 (stdout, ";; undersized: %d\n", len)); 504 terrno = EMSGSIZE; 505 badns |= (1 << ns); 506 res_close(); 507 goto next_ns; 508 } 509 cp = ans; 510 while (len != 0 && 511 (n = read(s, (char *)cp, (int)len)) > 0) { 512 cp += n; 513 len = (u_short)( len - n ); 514 } 515 if (n <= 0) { 516 terrno = errno; 517 Perror(stderr, "read(vc)", errno); 518 res_close(); 519 goto next_ns; 520 } 521 if (truncated) { 522 /* 523 * Flush rest of answer 524 * so connection stays in synch. 525 */ 526 anhp->tc = 1; 527 len = (ushort)( resplen - anssiz ); 528 while (len != 0) { 529 char junk[PACKETSZ]; 530 531 n = (len > sizeof(junk) 532 ? sizeof(junk) 533 : len); 534 if ((n = read(s, junk, n)) > 0) 535 len = (u_short)( len - n ); 536 else 537 break; 538 } 539 } 540 /* 541 * The calling applicating has bailed out of 542 * a previous call and failed to arrange to have 543 * the circuit closed or the server has got 544 * itself confused. Anyway drop the packet and 545 * wait for the correct one. 546 */ 547 if (hp->id != anhp->id) { 548 DprintQ((_res.options & RES_DEBUG) || 549 (_res.pfcode & RES_PRF_REPLY), 550 (stdout, ";; old answer (unexpected):\n"), 551 ans, (resplen>anssiz)?anssiz:resplen); 552 goto read_len; 553 } 554 } else { 555 /* 556 * Use datagrams. 557 */ 558 #ifndef NOPOLL 559 struct pollfd pfd; 560 int msec; 561 #endif 562 struct timeval timeout; 563 fd_set dsmask, *dsmaskp; 564 int dsmasklen; 565 struct sockaddr_in from; 566 int fromlen; 567 568 if ((s < 0) || vc) { 569 if (vc) 570 res_close(); 571 s = socket(PF_INET, SOCK_DGRAM, 0); 572 if (s < 0) { 573 #ifndef CAN_RECONNECT 574 bad_dg_sock: 575 #endif 576 terrno = errno; 577 Perror(stderr, "socket(dg)", errno); 578 return (-1); 579 } 580 connected = 0; 581 } 582 #ifndef CANNOT_CONNECT_DGRAM 583 /* 584 * On a 4.3BSD+ machine (client and server, 585 * actually), sending to a nameserver datagram 586 * port with no nameserver will cause an 587 * ICMP port unreachable message to be returned. 588 * If our datagram socket is "connected" to the 589 * server, we get an ECONNREFUSED error on the next 590 * socket operation, and select returns if the 591 * error message is received. We can thus detect 592 * the absence of a nameserver without timing out. 593 * If we have sent queries to at least two servers, 594 * however, we don't want to remain connected, 595 * as we wish to receive answers from the first 596 * server to respond. 597 */ 598 if (_res.nscount == 1 || (try == 0 && ns == 0)) { 599 /* 600 * Connect only if we are sure we won't 601 * receive a response from another server. 602 */ 603 if (!connected) { 604 nsap->sin_len = sizeof ( *nsap ); 605 if (connect(s, (struct sockaddr *)nsap, 606 sizeof *nsap 607 ) < 0) { 608 Aerror(stderr, 609 "connect(dg)", 610 errno, *nsap); 611 badns |= (1 << ns); 612 res_close(); 613 goto next_ns; 614 } 615 connected = 1; 616 } 617 if (send(s, (char*)buf, buflen, 0) != buflen) { 618 Perror(stderr, "send", errno); 619 badns |= (1 << ns); 620 res_close(); 621 goto next_ns; 622 } 623 } else { 624 /* 625 * Disconnect if we want to listen 626 * for responses from more than one server. 627 */ 628 if (connected) { 629 #ifdef CAN_RECONNECT 630 struct sockaddr_in no_addr; 631 632 no_addr.sin_family = AF_INET; 633 no_addr.sin_addr.s_addr = INADDR_ANY; 634 no_addr.sin_port = 0; 635 (void) connect(s, 636 (struct sockaddr *) 637 &no_addr, 638 sizeof no_addr); 639 #else 640 int s1 = socket(PF_INET, SOCK_DGRAM,0); 641 if (s1 < 0) 642 goto bad_dg_sock; 643 (void) dup2(s1, s); 644 (void) close(s1); 645 Dprint(_res.options & RES_DEBUG, 646 (stdout, ";; new DG socket\n")) 647 #endif /* CAN_RECONNECT */ 648 connected = 0; 649 errno = 0; 650 } 651 #endif /* !CANNOT_CONNECT_DGRAM */ 652 if (sendto(s, (char*)buf, buflen, 0, 653 (struct sockaddr *)nsap, 654 sizeof *nsap) 655 != buflen) { 656 Aerror(stderr, "sendto", errno, *nsap); 657 badns |= (1 << ns); 658 res_close(); 659 goto next_ns; 660 } 661 #ifndef CANNOT_CONNECT_DGRAM 662 } 663 #endif /* !CANNOT_CONNECT_DGRAM */ 664 665 /* 666 * Wait for reply 667 */ 668 #ifndef NOPOLL 669 othersyscall: 670 if (use_poll) { 671 msec = (_res.retrans << try) * 1000; 672 if (try > 0) 673 msec /= _res.nscount; 674 if (msec <= 0) 675 msec = 1000; 676 } else { 677 #endif 678 timeout.tv_sec = (_res.retrans << try); 679 if (try > 0) 680 timeout.tv_sec /= _res.nscount; 681 if ((long) timeout.tv_sec <= 0) 682 timeout.tv_sec = 1; 683 timeout.tv_usec = 0; 684 #ifndef NOPOLL 685 } 686 #endif 687 wait: 688 if (s < 0) { 689 Perror(stderr, "s out-of-bounds", EMFILE); 690 res_close(); 691 goto next_ns; 692 } 693 #ifndef NOPOLL 694 if (use_poll) { 695 struct sigaction sa, osa; 696 int sigsys_installed = 0; 697 698 pfd.fd = s; 699 pfd.events = POLLIN; 700 if (use_poll == 1) { 701 bzero(&sa, sizeof(sa)); 702 sa.sa_handler = SIG_IGN; 703 if (sigaction(SIGSYS, &sa, &osa) >= 0) 704 sigsys_installed = 1; 705 } 706 n = poll(&pfd, 1, msec); 707 if (sigsys_installed == 1) { 708 int oerrno = errno; 709 sigaction(SIGSYS, &osa, NULL); 710 errno = oerrno; 711 } 712 /* XXX why does nosys() return EINVAL? */ 713 if (n < 0 && (errno == ENOSYS || 714 errno == EINVAL)) { 715 use_poll = 0; 716 goto othersyscall; 717 } else if (use_poll == 1) 718 use_poll = 2; 719 if (n < 0) { 720 if (errno == EINTR) 721 goto wait; 722 Perror(stderr, "poll", errno); 723 res_close(); 724 goto next_ns; 725 } 726 } else { 727 #endif 728 dsmasklen = howmany(s + 1, NFDBITS) * 729 sizeof(fd_mask); 730 if (dsmasklen > sizeof(fd_set)) { 731 dsmaskp = (fd_set *)malloc(dsmasklen); 732 if (dsmaskp == NULL) { 733 res_close(); 734 goto next_ns; 735 } 736 } else 737 dsmaskp = &dsmask; 738 /* only zero what we need */ 739 memset((char *)dsmaskp, 0, dsmasklen); 740 FD_SET(s, dsmaskp); 741 n = select(s + 1, dsmaskp, (fd_set *)NULL, 742 (fd_set *)NULL, &timeout); 743 if (dsmaskp != &dsmask) 744 free(dsmaskp); 745 if (n < 0) { 746 if (errno == EINTR) 747 goto wait; 748 Perror(stderr, "select", errno); 749 res_close(); 750 goto next_ns; 751 } 752 #ifndef NOPOLL 753 } 754 #endif 755 756 if (n == 0) { 757 /* 758 * timeout 759 */ 760 Dprint(_res.options & RES_DEBUG, 761 (stdout, ";; timeout\n")); 762 gotsomewhere = 1; 763 res_close(); 764 goto next_ns; 765 } 766 errno = 0; 767 fromlen = sizeof(struct sockaddr_in); 768 resplen = (int)recvfrom(s, (char*)ans, anssiz, 0, 769 (struct sockaddr *)&from, (socklen_t *)&fromlen); 770 if (resplen <= 0) { 771 Perror(stderr, "recvfrom", errno); 772 res_close(); 773 goto next_ns; 774 } 775 gotsomewhere = 1; 776 if (resplen < HFIXEDSZ) { 777 /* 778 * Undersized message. 779 */ 780 Dprint(_res.options & RES_DEBUG, 781 (stdout, ";; undersized: %d\n", 782 resplen)); 783 terrno = EMSGSIZE; 784 badns |= (1 << ns); 785 res_close(); 786 goto next_ns; 787 } 788 if (hp->id != anhp->id) { 789 /* 790 * response from old query, ignore it. 791 * XXX - potential security hazard could 792 * be detected here. 793 */ 794 DprintQ((_res.options & RES_DEBUG) || 795 (_res.pfcode & RES_PRF_REPLY), 796 (stdout, ";; old answer:\n"), 797 ans, (resplen>anssiz)?anssiz:resplen); 798 goto wait; 799 } 800 #ifdef CHECK_SRVR_ADDR 801 if (!(_res.options & RES_INSECURE1) && 802 !res_isourserver(&from)) { 803 /* 804 * response from wrong server? ignore it. 805 * XXX - potential security hazard could 806 * be detected here. 807 */ 808 DprintQ((_res.options & RES_DEBUG) || 809 (_res.pfcode & RES_PRF_REPLY), 810 (stdout, ";; not our server:\n"), 811 ans, (resplen>anssiz)?anssiz:resplen); 812 goto wait; 813 } 814 #endif 815 if (!(_res.options & RES_INSECURE2) && 816 !res_queriesmatch(buf, buf + buflen, 817 ans, ans + anssiz)) { 818 /* 819 * response contains wrong query? ignore it. 820 * XXX - potential security hazard could 821 * be detected here. 822 */ 823 DprintQ((_res.options & RES_DEBUG) || 824 (_res.pfcode & RES_PRF_REPLY), 825 (stdout, ";; wrong query name:\n"), 826 ans, (resplen>anssiz)?anssiz:resplen); 827 goto wait; 828 } 829 if (anhp->rcode == SERVFAIL || 830 anhp->rcode == NOTIMP || 831 anhp->rcode == REFUSED) { 832 DprintQ(_res.options & RES_DEBUG, 833 (stdout, "server rejected query:\n"), 834 ans, (resplen>anssiz)?anssiz:resplen); 835 badns |= (1 << ns); 836 res_close(); 837 /* don't retry if called from dig */ 838 if (!_res.pfcode) 839 goto next_ns; 840 } 841 if (!(_res.options & RES_IGNTC) && anhp->tc) { 842 /* 843 * get rest of answer; 844 * use TCP with same server. 845 */ 846 Dprint(_res.options & RES_DEBUG, 847 (stdout, ";; truncated answer\n")); 848 v_circuit = 1; 849 res_close(); 850 goto same_ns; 851 } 852 } /*if vc/dg*/ 853 Dprint((_res.options & RES_DEBUG) || 854 ((_res.pfcode & RES_PRF_REPLY) && 855 (_res.pfcode & RES_PRF_HEAD1)), 856 (stdout, ";; got answer:\n")); 857 if((_res.options & RES_DEBUG) || 858 (_res.pfcode & RES_PRF_REPLY)) { 859 __fp_nquery(ans, (resplen>anssiz)?anssiz:resplen, stdout); 860 } 861 /* 862 * If using virtual circuits, we assume that the first server 863 * is preferred over the rest (i.e. it is on the local 864 * machine) and only keep that one open. 865 * If we have temporarily opened a virtual circuit, 866 * or if we haven't been asked to keep a socket open, 867 * close the socket. 868 */ 869 if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || 870 !(_res.options & RES_STAYOPEN)) { 871 res_close(); 872 } 873 if (Rhook) { 874 int done = 0, loops = 0; 875 876 do { 877 res_sendhookact act; 878 879 act = (*Rhook)(nsap, buf, buflen, 880 ans, anssiz, &resplen); 881 switch (act) { 882 case res_goahead: 883 case res_done: 884 done = 1; 885 break; 886 case res_nextns: 887 res_close(); 888 goto next_ns; 889 case res_modified: 890 /* give the hook another try */ 891 if (++loops < 42) /*doug adams*/ 892 break; 893 /*FALLTHROUGH*/ 894 case res_error: 895 /*FALLTHROUGH*/ 896 default: 897 return (-1); 898 } 899 } while (!done); 900 901 } 902 return (resplen); 903 next_ns: ; 904 } /*foreach ns*/ 905 } /*foreach retry*/ 906 res_close(); 907 if (!v_circuit) { 908 if (!gotsomewhere) 909 errno = ECONNREFUSED; /* no nameservers found */ 910 else 911 errno = ETIMEDOUT; /* no answer obtained */ 912 } else 913 errno = terrno; 914 return (-1); 915 } 916 917 /* 918 * This routine is for closing the socket if a virtual circuit is used and 919 * the program wants to close it. This provides support for endhostent() 920 * which expects to close the socket. 921 * 922 * This routine is not expected to be user visible. 923 */ 924 void 925 res_close() 926 { 927 if (s >= 0) { 928 (void) close(s); 929 s = -1; 930 connected = 0; 931 vc = 0; 932 } 933 } 934