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