1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 1985, 1989, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 /* 40 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 41 * 42 * Permission to use, copy, modify, and distribute this software for any 43 * purpose with or without fee is hereby granted, provided that the above 44 * copyright notice and this permission notice appear in all copies, and that 45 * the name of Digital Equipment Corporation not be used in advertising or 46 * publicity pertaining to distribution of the document or software without 47 * specific, written prior permission. 48 * 49 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 50 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 51 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 52 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 53 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 54 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 55 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 56 * SOFTWARE. 57 */ 58 59 /* 60 * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 61 * 62 * Permission to use, copy, modify, and distribute this software for any 63 * purpose with or without fee is hereby granted, provided that the above 64 * copyright notice and this permission notice appear in all copies. 65 * 66 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 67 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 68 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 69 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 70 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 71 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 72 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 73 * SOFTWARE. 74 */ 75 76 #pragma ident "%Z%%M% %I% %E% SMI" 77 78 #if defined(LIBC_SCCS) && !defined(lint) 79 static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 80 static const char rcsid[] = "$Id: res_send.c,v 8.52 2003/04/29 02:13:08 marka Exp $"; 81 #endif /* LIBC_SCCS and not lint */ 82 83 /* 84 * Send query to name server and wait for reply. 85 */ 86 87 #include "port_before.h" 88 #include "fd_setsize.h" 89 90 #include <sys/types.h> 91 #include <sys/param.h> 92 #include <sys/time.h> 93 #include <sys/socket.h> 94 #include <sys/uio.h> 95 96 #include <netinet/in.h> 97 #include <arpa/nameser.h> 98 #include <arpa/inet.h> 99 100 #include <errno.h> 101 #include <netdb.h> 102 #include <resolv.h> 103 #include <signal.h> 104 #include <stdio.h> 105 #include <stdlib.h> 106 #include <string.h> 107 #include <unistd.h> 108 109 #include <isc/eventlib.h> 110 111 #include "port_after.h" 112 113 #ifdef SUNW_POLL 114 #include <stropts.h> 115 #include <poll.h> 116 #define pselect Pselect 117 #endif /* SUNW_POLL */ 118 119 /* Options. Leave them on. */ 120 #define DEBUG 121 #include "res_debug.h" 122 #include "res_private.h" 123 124 #define EXT(res) ((res)->_u._ext) 125 126 #ifdef ORIGINAL_ISC_CODE 127 static const int highestFD = FD_SETSIZE - 1; 128 #else 129 static int highestFD = 0; 130 #endif 131 132 /* Forward. */ 133 134 static int get_salen __P((const struct sockaddr *)); 135 static struct sockaddr * get_nsaddr __P((res_state, size_t)); 136 static int send_vc(res_state, const u_char *, int, 137 u_char *, int, int *, int); 138 static int send_dg(res_state, const u_char *, int, 139 u_char *, int, int *, int, 140 int *, int *); 141 static void Aerror(const res_state, FILE *, const char *, int, 142 const struct sockaddr *, int); 143 static void Perror(const res_state, FILE *, const char *, int); 144 static int sock_eq(struct sockaddr *, struct sockaddr *); 145 #ifdef NEED_PSELECT 146 static int pselect(int, void *, void *, void *, 147 struct timespec *, 148 const sigset_t *); 149 #endif 150 void res_pquery(const res_state, const u_char *, int, FILE *); 151 152 #ifdef ORIGINAL_ISC_CODE 153 #else 154 #pragma weak __res_nameinquery = res_nameinquery 155 #pragma weak __res_queriesmatch = res_queriesmatch 156 #pragma weak res_nisourserver = res_ourserver_p 157 #endif /* ORIGINAL_ISC_CODE */ 158 159 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 160 161 /* Public. */ 162 163 /* int 164 * res_isourserver(ina) 165 * looks up "ina" in _res.ns_addr_list[] 166 * returns: 167 * 0 : not found 168 * >0 : found 169 * author: 170 * paul vixie, 29may94 171 */ 172 int 173 res_ourserver_p(const res_state statp, const struct sockaddr *sa) { 174 const struct sockaddr_in *inp, *srv; 175 const struct sockaddr_in6 *in6p, *srv6; 176 int ns; 177 178 switch (sa->sa_family) { 179 case AF_INET: 180 inp = (const struct sockaddr_in *)sa; 181 for (ns = 0; ns < statp->nscount; ns++) { 182 srv = (struct sockaddr_in *)get_nsaddr(statp, ns); 183 if (srv->sin_family == inp->sin_family && 184 srv->sin_port == inp->sin_port && 185 (srv->sin_addr.s_addr == INADDR_ANY || 186 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) 187 return (1); 188 } 189 break; 190 case AF_INET6: 191 if (EXT(statp).ext == NULL) 192 break; 193 in6p = (const struct sockaddr_in6 *)sa; 194 for (ns = 0; ns < statp->nscount; ns++) { 195 srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); 196 if (srv6->sin6_family == in6p->sin6_family && 197 srv6->sin6_port == in6p->sin6_port && 198 #ifdef HAVE_SIN6_SCOPE_ID 199 (srv6->sin6_scope_id == 0 || 200 srv6->sin6_scope_id == in6p->sin6_scope_id) && 201 #endif 202 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || 203 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) 204 return (1); 205 } 206 break; 207 default: 208 break; 209 } 210 return (0); 211 } 212 213 /* int 214 * res_nameinquery(name, type, class, buf, eom) 215 * look for (name,type,class) in the query section of packet (buf,eom) 216 * requires: 217 * buf + HFIXEDSZ <= eom 218 * returns: 219 * -1 : format error 220 * 0 : not found 221 * >0 : found 222 * author: 223 * paul vixie, 29may94 224 */ 225 int 226 res_nameinquery(const char *name, int type, int class, 227 const u_char *buf, const u_char *eom) 228 { 229 const u_char *cp = buf + HFIXEDSZ; 230 int qdcount = ntohs(((const HEADER*)buf)->qdcount); 231 232 while (qdcount-- > 0) { 233 char tname[MAXDNAME+1]; 234 int n, ttype, tclass; 235 236 n = dn_expand(buf, eom, cp, tname, sizeof tname); 237 if (n < 0) 238 return (-1); 239 cp += n; 240 if (cp + 2 * INT16SZ > eom) 241 return (-1); 242 ttype = ns_get16(cp); cp += INT16SZ; 243 tclass = ns_get16(cp); cp += INT16SZ; 244 if (ttype == type && tclass == class && 245 ns_samename(tname, name) == 1) 246 return (1); 247 } 248 return (0); 249 } 250 251 /* int 252 * res_queriesmatch(buf1, eom1, buf2, eom2) 253 * is there a 1:1 mapping of (name,type,class) 254 * in (buf1,eom1) and (buf2,eom2)? 255 * returns: 256 * -1 : format error 257 * 0 : not a 1:1 mapping 258 * >0 : is a 1:1 mapping 259 * author: 260 * paul vixie, 29may94 261 */ 262 int 263 res_queriesmatch(const u_char *buf1, const u_char *eom1, 264 const u_char *buf2, const u_char *eom2) 265 { 266 const u_char *cp = buf1 + HFIXEDSZ; 267 int qdcount = ntohs(((const HEADER*)buf1)->qdcount); 268 269 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 270 return (-1); 271 272 /* 273 * Only header section present in replies to 274 * dynamic update packets. 275 */ 276 if ((((const HEADER *)buf1)->opcode == ns_o_update) && 277 (((const HEADER *)buf2)->opcode == ns_o_update)) 278 return (1); 279 280 if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) 281 return (0); 282 while (qdcount-- > 0) { 283 char tname[MAXDNAME+1]; 284 int n, ttype, tclass; 285 286 n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 287 if (n < 0) 288 return (-1); 289 cp += n; 290 if (cp + 2 * INT16SZ > eom1) 291 return (-1); 292 ttype = ns_get16(cp); cp += INT16SZ; 293 tclass = ns_get16(cp); cp += INT16SZ; 294 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 295 return (0); 296 } 297 return (1); 298 } 299 300 int 301 res_nsend(res_state statp, 302 const u_char *buf, int buflen, u_char *ans, int anssiz) 303 { 304 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; 305 char abuf[NI_MAXHOST]; 306 307 #ifdef SUNW_POLL 308 highestFD = sysconf(_SC_OPEN_MAX) - 1; 309 #endif 310 311 if (statp->nscount == 0) { 312 errno = ESRCH; 313 return (-1); 314 } 315 if (anssiz < HFIXEDSZ) { 316 errno = EINVAL; 317 return (-1); 318 } 319 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), 320 (stdout, ";; res_send()\n"), buf, buflen); 321 v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; 322 gotsomewhere = 0; 323 terrno = ETIMEDOUT; 324 325 /* 326 * If the ns_addr_list in the resolver context has changed, then 327 * invalidate our cached copy and the associated timing data. 328 */ 329 if (EXT(statp).nscount != 0) { 330 int needclose = 0; 331 struct sockaddr_storage peer; 332 ISC_SOCKLEN_T peerlen; 333 334 if (EXT(statp).nscount != statp->nscount) 335 needclose++; 336 else 337 for (ns = 0; ns < statp->nscount; ns++) { 338 if (statp->nsaddr_list[ns].sin_family && 339 !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], 340 (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { 341 needclose++; 342 break; 343 } 344 345 if (EXT(statp).nssocks[ns] == -1) 346 continue; 347 peerlen = sizeof(peer); 348 if (getsockname(EXT(statp).nssocks[ns], 349 (struct sockaddr *)&peer, &peerlen) < 0) { 350 needclose++; 351 break; 352 } 353 if (!sock_eq((struct sockaddr *)&peer, 354 get_nsaddr(statp, ns))) { 355 needclose++; 356 break; 357 } 358 } 359 if (needclose) { 360 res_nclose(statp); 361 EXT(statp).nscount = 0; 362 } 363 } 364 365 /* 366 * Maybe initialize our private copy of the ns_addr_list. 367 */ 368 if (EXT(statp).nscount == 0) { 369 for (ns = 0; ns < statp->nscount; ns++) { 370 EXT(statp).nstimes[ns] = RES_MAXTIME; 371 EXT(statp).nssocks[ns] = -1; 372 if (!statp->nsaddr_list[ns].sin_family) 373 continue; 374 EXT(statp).ext->nsaddrs[ns].sin = 375 statp->nsaddr_list[ns]; 376 } 377 EXT(statp).nscount = statp->nscount; 378 } 379 380 /* 381 * Some resolvers want to even out the load on their nameservers. 382 * Note that RES_BLAST overrides RES_ROTATE. 383 */ 384 if ((statp->options & RES_ROTATE) != 0 && 385 (statp->options & RES_BLAST) == 0) { 386 union res_sockaddr_union inu; 387 struct sockaddr_in ina; 388 int lastns = statp->nscount - 1; 389 int fd; 390 u_int16_t nstime; 391 392 if (EXT(statp).ext != NULL) 393 inu = EXT(statp).ext->nsaddrs[0]; 394 ina = statp->nsaddr_list[0]; 395 fd = EXT(statp).nssocks[0]; 396 nstime = EXT(statp).nstimes[0]; 397 for (ns = 0; ns < lastns; ns++) { 398 if (EXT(statp).ext != NULL) 399 EXT(statp).ext->nsaddrs[ns] = 400 EXT(statp).ext->nsaddrs[ns + 1]; 401 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; 402 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; 403 EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; 404 } 405 if (EXT(statp).ext != NULL) 406 EXT(statp).ext->nsaddrs[lastns] = inu; 407 statp->nsaddr_list[lastns] = ina; 408 EXT(statp).nssocks[lastns] = fd; 409 EXT(statp).nstimes[lastns] = nstime; 410 } 411 412 /* 413 * Send request, RETRY times, or until successful. 414 */ 415 for (try = 0; try < statp->retry; try++) { 416 for (ns = 0; ns < statp->nscount; ns++) { 417 struct sockaddr *nsap; 418 int nsaplen; 419 nsap = get_nsaddr(statp, ns); 420 nsaplen = get_salen(nsap); 421 statp->_flags &= ~RES_F_LASTMASK; 422 statp->_flags |= (ns << RES_F_LASTSHIFT); 423 same_ns: 424 if (statp->qhook) { 425 int done = 0, loops = 0; 426 427 do { 428 res_sendhookact act; 429 430 act = (*statp->qhook)(&nsap, &buf, &buflen, 431 ans, anssiz, &resplen); 432 switch (act) { 433 case res_goahead: 434 done = 1; 435 break; 436 case res_nextns: 437 res_nclose(statp); 438 goto next_ns; 439 case res_done: 440 return (resplen); 441 case res_modified: 442 /* give the hook another try */ 443 if (++loops < 42) /*doug adams*/ 444 break; 445 /*FALLTHROUGH*/ 446 case res_error: 447 /*FALLTHROUGH*/ 448 default: 449 goto fail; 450 } 451 } while (!done); 452 } 453 454 Dprint(((statp->options & RES_DEBUG) && 455 getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), 456 NULL, 0, niflags) == 0), 457 (stdout, ";; Querying server (# %d) address = %s\n", 458 ns + 1, abuf)); 459 460 461 if (v_circuit) { 462 /* Use VC; at most one attempt per server. */ 463 try = statp->retry; 464 n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 465 ns); 466 if (n < 0) 467 goto fail; 468 if (n == 0) 469 goto next_ns; 470 resplen = n; 471 } else { 472 /* Use datagrams. */ 473 n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, 474 ns, &v_circuit, &gotsomewhere); 475 if (n < 0) 476 goto fail; 477 if (n == 0) 478 goto next_ns; 479 if (v_circuit) 480 goto same_ns; 481 resplen = n; 482 } 483 484 Dprint((statp->options & RES_DEBUG) || 485 ((statp->pfcode & RES_PRF_REPLY) && 486 (statp->pfcode & RES_PRF_HEAD1)), 487 (stdout, ";; got answer:\n")); 488 489 DprintQ((statp->options & RES_DEBUG) || 490 (statp->pfcode & RES_PRF_REPLY), 491 (stdout, "%s", ""), 492 ans, (resplen > anssiz) ? anssiz : resplen); 493 494 /* 495 * If we have temporarily opened a virtual circuit, 496 * or if we haven't been asked to keep a socket open, 497 * close the socket. 498 */ 499 if ((v_circuit && (statp->options & RES_USEVC) == 0) || 500 (statp->options & RES_STAYOPEN) == 0) { 501 res_nclose(statp); 502 } 503 if (statp->rhook) { 504 int done = 0, loops = 0; 505 506 do { 507 res_sendhookact act; 508 509 act = (*statp->rhook)(nsap, buf, buflen, 510 ans, anssiz, &resplen); 511 switch (act) { 512 case res_goahead: 513 case res_done: 514 done = 1; 515 break; 516 case res_nextns: 517 res_nclose(statp); 518 goto next_ns; 519 case res_modified: 520 /* give the hook another try */ 521 if (++loops < 42) /*doug adams*/ 522 break; 523 /*FALLTHROUGH*/ 524 case res_error: 525 /*FALLTHROUGH*/ 526 default: 527 goto fail; 528 } 529 } while (!done); 530 531 } 532 return (resplen); 533 next_ns: ; 534 } /*foreach ns*/ 535 } /*foreach retry*/ 536 res_nclose(statp); 537 if (!v_circuit) { 538 if (!gotsomewhere) 539 errno = ECONNREFUSED; /* no nameservers found */ 540 else 541 errno = ETIMEDOUT; /* no answer obtained */ 542 } else 543 errno = terrno; 544 return (-1); 545 fail: 546 res_nclose(statp); 547 return (-1); 548 } 549 550 /* Private */ 551 552 static int 553 get_salen(sa) 554 const struct sockaddr *sa; 555 { 556 557 #ifdef HAVE_SA_LEN 558 /* There are people do not set sa_len. Be forgiving to them. */ 559 if (sa->sa_len) 560 return (sa->sa_len); 561 #endif 562 563 if (sa->sa_family == AF_INET) 564 return (sizeof(struct sockaddr_in)); 565 else if (sa->sa_family == AF_INET6) 566 return (sizeof(struct sockaddr_in6)); 567 else 568 return (0); /* unknown, die on connect */ 569 } 570 571 /* 572 * pick appropriate nsaddr_list for use. see res_init() for initialization. 573 */ 574 static struct sockaddr * 575 get_nsaddr(statp, n) 576 res_state statp; 577 size_t n; 578 { 579 580 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 581 /* 582 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 583 * than struct sockaddr, and 584 * - user code did not update statp->nsaddr_list[n]. 585 */ 586 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 587 } else { 588 /* 589 * - user code updated statp->nsaddr_list[n], or 590 * - statp->nsaddr_list[n] has the same content as 591 * EXT(statp).ext->nsaddrs[n]. 592 */ 593 return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 594 } 595 } 596 597 static int 598 send_vc(res_state statp, 599 const u_char *buf, int buflen, u_char *ans, int anssiz, 600 int *terrno, int ns) 601 { 602 const HEADER *hp = (const HEADER *) buf; 603 HEADER *anhp = (HEADER *) ans; 604 struct sockaddr *nsap; 605 int nsaplen; 606 int truncating, connreset, resplen, n; 607 struct iovec iov[2]; 608 u_short len; 609 u_char *cp; 610 void *tmp; 611 612 nsap = get_nsaddr(statp, ns); 613 nsaplen = get_salen(nsap); 614 615 connreset = 0; 616 same_ns: 617 truncating = 0; 618 619 /* Are we still talking to whom we want to talk to? */ 620 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 621 struct sockaddr_storage peer; 622 ISC_SOCKLEN_T size = sizeof peer; 623 624 if (getpeername(statp->_vcsock, 625 (struct sockaddr *)&peer, &size) < 0 || 626 !sock_eq((struct sockaddr *)&peer, nsap)) { 627 res_nclose(statp); 628 statp->_flags &= ~RES_F_VC; 629 } 630 } 631 632 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 633 if (statp->_vcsock >= 0) 634 res_nclose(statp); 635 636 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); 637 if (statp->_vcsock > highestFD) { 638 res_nclose(statp); 639 errno = ENOTSOCK; 640 } 641 if (statp->_vcsock < 0) { 642 *terrno = errno; 643 Perror(statp, stderr, "socket(vc)", errno); 644 return (-1); 645 } 646 errno = 0; 647 if (connect(statp->_vcsock, nsap, nsaplen) < 0) { 648 *terrno = errno; 649 Aerror(statp, stderr, "connect/vc", errno, nsap, 650 nsaplen); 651 res_nclose(statp); 652 return (0); 653 } 654 statp->_flags |= RES_F_VC; 655 } 656 657 /* 658 * Send length & message 659 */ 660 ns_put16((u_short)buflen, (u_char*)&len); 661 iov[0] = evConsIovec(&len, INT16SZ); 662 DE_CONST(buf, tmp); 663 iov[1] = evConsIovec(tmp, buflen); 664 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 665 *terrno = errno; 666 Perror(statp, stderr, "write failed", errno); 667 res_nclose(statp); 668 return (0); 669 } 670 /* 671 * Receive length & response 672 */ 673 read_len: 674 cp = ans; 675 len = INT16SZ; 676 while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { 677 cp += n; 678 if ((len -= n) <= 0) 679 break; 680 } 681 if (n <= 0) { 682 *terrno = errno; 683 Perror(statp, stderr, "read failed", errno); 684 res_nclose(statp); 685 /* 686 * A long running process might get its TCP 687 * connection reset if the remote server was 688 * restarted. Requery the server instead of 689 * trying a new one. When there is only one 690 * server, this means that a query might work 691 * instead of failing. We only allow one reset 692 * per query to prevent looping. 693 */ 694 if (*terrno == ECONNRESET && !connreset) { 695 connreset = 1; 696 res_nclose(statp); 697 goto same_ns; 698 } 699 res_nclose(statp); 700 return (0); 701 } 702 resplen = ns_get16(ans); 703 if (resplen > anssiz) { 704 Dprint(statp->options & RES_DEBUG, 705 (stdout, ";; response truncated\n") 706 ); 707 truncating = 1; 708 len = anssiz; 709 } else 710 len = resplen; 711 if (len < HFIXEDSZ) { 712 /* 713 * Undersized message. 714 */ 715 Dprint(statp->options & RES_DEBUG, 716 (stdout, ";; undersized: %d\n", len)); 717 *terrno = EMSGSIZE; 718 res_nclose(statp); 719 return (0); 720 } 721 cp = ans; 722 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ 723 cp += n; 724 len -= n; 725 } 726 if (n <= 0) { 727 *terrno = errno; 728 Perror(statp, stderr, "read(vc)", errno); 729 res_nclose(statp); 730 return (0); 731 } 732 if (truncating) { 733 /* 734 * Flush rest of answer so connection stays in synch. 735 */ 736 anhp->tc = 1; 737 len = resplen - anssiz; 738 /* 739 * Reset the value of resplen to anssiz, 740 * this is done because the caller assumes 741 * resplen contains the size of message read 742 * into the "ans" buffer passed in. 743 */ 744 resplen = anssiz; 745 746 while (len != 0) { 747 char junk[PACKETSZ]; 748 749 n = read(statp->_vcsock, junk, 750 (len > sizeof junk) ? sizeof junk : len); 751 if (n > 0) 752 len -= n; 753 else 754 break; 755 } 756 } 757 /* 758 * If the calling applicating has bailed out of 759 * a previous call and failed to arrange to have 760 * the circuit closed or the server has got 761 * itself confused, then drop the packet and 762 * wait for the correct one. 763 */ 764 if (hp->id != anhp->id) { 765 DprintQ((statp->options & RES_DEBUG) || 766 (statp->pfcode & RES_PRF_REPLY), 767 (stdout, ";; old answer (unexpected):\n"), 768 ans, (resplen > anssiz) ? anssiz: resplen); 769 goto read_len; 770 } 771 772 /* 773 * All is well, or the error is fatal. Signal that the 774 * next nameserver ought not be tried. 775 */ 776 return (resplen); 777 } 778 779 static int 780 send_dg(res_state statp, 781 const u_char *buf, int buflen, u_char *ans, int anssiz, 782 int *terrno, int ns, int *v_circuit, int *gotsomewhere) 783 { 784 const HEADER *hp = (const HEADER *) buf; 785 HEADER *anhp = (HEADER *) ans; 786 const struct sockaddr *nsap; 787 int nsaplen; 788 struct timespec now, timeout, finish; 789 fd_set dsmask; 790 struct sockaddr_storage from; 791 ISC_SOCKLEN_T fromlen; 792 int resplen, seconds, n, s; 793 #ifdef SUNW_POLL 794 int polltimeout; 795 struct pollfd pollfd; 796 #endif 797 798 nsap = get_nsaddr(statp, ns); 799 nsaplen = get_salen(nsap); 800 if (EXT(statp).nssocks[ns] == -1) { 801 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); 802 if (EXT(statp).nssocks[ns] > highestFD) { 803 res_nclose(statp); 804 errno = ENOTSOCK; 805 } 806 if (EXT(statp).nssocks[ns] < 0) { 807 *terrno = errno; 808 Perror(statp, stderr, "socket(dg)", errno); 809 return (-1); 810 } 811 #ifndef CANNOT_CONNECT_DGRAM 812 /* 813 * On a 4.3BSD+ machine (client and server, 814 * actually), sending to a nameserver datagram 815 * port with no nameserver will cause an 816 * ICMP port unreachable message to be returned. 817 * If our datagram socket is "connected" to the 818 * server, we get an ECONNREFUSED error on the next 819 * socket operation, and select returns if the 820 * error message is received. We can thus detect 821 * the absence of a nameserver without timing out. 822 */ 823 if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { 824 Aerror(statp, stderr, "connect(dg)", errno, nsap, 825 nsaplen); 826 res_nclose(statp); 827 return (0); 828 } 829 #endif /* !CANNOT_CONNECT_DGRAM */ 830 Dprint(statp->options & RES_DEBUG, 831 (stdout, ";; new DG socket\n")) 832 } 833 s = EXT(statp).nssocks[ns]; 834 #ifndef CANNOT_CONNECT_DGRAM 835 if (send(s, (const char*)buf, buflen, 0) != buflen) { 836 Perror(statp, stderr, "send", errno); 837 res_nclose(statp); 838 return (0); 839 } 840 #else /* !CANNOT_CONNECT_DGRAM */ 841 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 842 { 843 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 844 res_nclose(statp); 845 return (0); 846 } 847 #endif /* !CANNOT_CONNECT_DGRAM */ 848 849 /* 850 * Wait for reply. 851 */ 852 seconds = (statp->retrans << ns); 853 if (ns > 0) 854 seconds /= statp->nscount; 855 if (seconds <= 0) 856 seconds = 1; 857 now = evNowTime(); 858 timeout = evConsTime(seconds, 0); 859 finish = evAddTime(now, timeout); 860 goto nonow; 861 wait: 862 now = evNowTime(); 863 nonow: 864 #ifdef SUNW_POLL 865 timeout = evSubTime(finish, now); 866 if (timeout.tv_sec < 0) 867 timeout = evConsTime(0, 0); 868 polltimeout = 1000*timeout.tv_sec + 869 timeout.tv_nsec/1000000; 870 pollfd.fd = s; 871 pollfd.events = POLLRDNORM; 872 n = poll(&pollfd, 1, polltimeout); 873 #else 874 FD_ZERO(&dsmask); 875 FD_SET(s, &dsmask); 876 if (evCmpTime(finish, now) > 0) 877 timeout = evSubTime(finish, now); 878 else 879 timeout = evConsTime(0, 0); 880 n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); 881 #endif 882 if (n == 0) { 883 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 884 *gotsomewhere = 1; 885 return (0); 886 } 887 if (n < 0) { 888 if (errno == EINTR) 889 goto wait; 890 #ifdef SUNW_POLL 891 Perror(statp, stderr, "poll", errno); 892 #else 893 Perror(statp, stderr, "select", errno); 894 #endif 895 res_nclose(statp); 896 return (0); 897 } 898 errno = 0; 899 fromlen = sizeof(from); 900 resplen = recvfrom(s, (char*)ans, anssiz,0, 901 (struct sockaddr *)&from, &fromlen); 902 if (resplen <= 0) { 903 Perror(statp, stderr, "recvfrom", errno); 904 res_nclose(statp); 905 return (0); 906 } 907 *gotsomewhere = 1; 908 if (resplen < HFIXEDSZ) { 909 /* 910 * Undersized message. 911 */ 912 Dprint(statp->options & RES_DEBUG, 913 (stdout, ";; undersized: %d\n", 914 resplen)); 915 *terrno = EMSGSIZE; 916 res_nclose(statp); 917 return (0); 918 } 919 if (hp->id != anhp->id) { 920 /* 921 * response from old query, ignore it. 922 * XXX - potential security hazard could 923 * be detected here. 924 */ 925 DprintQ((statp->options & RES_DEBUG) || 926 (statp->pfcode & RES_PRF_REPLY), 927 (stdout, ";; old answer:\n"), 928 ans, (resplen > anssiz) ? anssiz : resplen); 929 goto wait; 930 } 931 if (!(statp->options & RES_INSECURE1) && 932 !res_ourserver_p(statp, (struct sockaddr *)&from)) { 933 /* 934 * response from wrong server? ignore it. 935 * XXX - potential security hazard could 936 * be detected here. 937 */ 938 DprintQ((statp->options & RES_DEBUG) || 939 (statp->pfcode & RES_PRF_REPLY), 940 (stdout, ";; not our server:\n"), 941 ans, (resplen > anssiz) ? anssiz : resplen); 942 goto wait; 943 } 944 #ifdef RES_USE_EDNS0 945 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) { 946 /* 947 * Do not retry if the server do not understand EDNS0. 948 * The case has to be captured here, as FORMERR packet do not 949 * carry query section, hence res_queriesmatch() returns 0. 950 */ 951 DprintQ(statp->options & RES_DEBUG, 952 (stdout, "server rejected query with EDNS0:\n"), 953 ans, (resplen > anssiz) ? anssiz : resplen); 954 /* record the error */ 955 statp->_flags |= RES_F_EDNS0ERR; 956 res_nclose(statp); 957 return (0); 958 } 959 #endif 960 if (!(statp->options & RES_INSECURE2) && 961 !res_queriesmatch(buf, buf + buflen, 962 ans, ans + anssiz)) { 963 /* 964 * response contains wrong query? ignore it. 965 * XXX - potential security hazard could 966 * be detected here. 967 */ 968 DprintQ((statp->options & RES_DEBUG) || 969 (statp->pfcode & RES_PRF_REPLY), 970 (stdout, ";; wrong query name:\n"), 971 ans, (resplen > anssiz) ? anssiz : resplen); 972 goto wait; 973 } 974 if (anhp->rcode == SERVFAIL || 975 anhp->rcode == NOTIMP || 976 anhp->rcode == REFUSED) { 977 DprintQ(statp->options & RES_DEBUG, 978 (stdout, "server rejected query:\n"), 979 ans, (resplen > anssiz) ? anssiz : resplen); 980 res_nclose(statp); 981 /* don't retry if called from dig */ 982 if (!statp->pfcode) 983 return (0); 984 } 985 if (!(statp->options & RES_IGNTC) && anhp->tc) { 986 /* 987 * To get the rest of answer, 988 * use TCP with same server. 989 */ 990 Dprint(statp->options & RES_DEBUG, 991 (stdout, ";; truncated answer\n")); 992 *v_circuit = 1; 993 res_nclose(statp); 994 return (1); 995 } 996 /* 997 * All is well, or the error is fatal. Signal that the 998 * next nameserver ought not be tried. 999 */ 1000 return (resplen); 1001 } 1002 1003 static void 1004 Aerror(const res_state statp, FILE *file, const char *string, int error, 1005 const struct sockaddr *address, int alen) 1006 { 1007 int save = errno; 1008 char hbuf[NI_MAXHOST]; 1009 char sbuf[NI_MAXSERV]; 1010 1011 alen = alen; 1012 1013 if ((statp->options & RES_DEBUG) != 0) { 1014 if (getnameinfo(address, alen, hbuf, sizeof(hbuf), 1015 sbuf, sizeof(sbuf), niflags)) { 1016 strncpy(hbuf, "?", sizeof(hbuf) - 1); 1017 hbuf[sizeof(hbuf) - 1] = '\0'; 1018 strncpy(sbuf, "?", sizeof(sbuf) - 1); 1019 sbuf[sizeof(sbuf) - 1] = '\0'; 1020 } 1021 fprintf(file, "res_send: %s ([%s].%s): %s\n", 1022 string, hbuf, sbuf, strerror(error)); 1023 } 1024 errno = save; 1025 } 1026 1027 static void 1028 Perror(const res_state statp, FILE *file, const char *string, int error) { 1029 int save = errno; 1030 1031 if ((statp->options & RES_DEBUG) != 0) 1032 fprintf(file, "res_send: %s: %s\n", 1033 string, strerror(error)); 1034 errno = save; 1035 } 1036 1037 static int 1038 sock_eq(struct sockaddr *a, struct sockaddr *b) { 1039 struct sockaddr_in *a4, *b4; 1040 struct sockaddr_in6 *a6, *b6; 1041 1042 if (a->sa_family != b->sa_family) 1043 return 0; 1044 switch (a->sa_family) { 1045 case AF_INET: 1046 a4 = (struct sockaddr_in *)a; 1047 b4 = (struct sockaddr_in *)b; 1048 return a4->sin_port == b4->sin_port && 1049 a4->sin_addr.s_addr == b4->sin_addr.s_addr; 1050 case AF_INET6: 1051 a6 = (struct sockaddr_in6 *)a; 1052 b6 = (struct sockaddr_in6 *)b; 1053 return a6->sin6_port == b6->sin6_port && 1054 #ifdef HAVE_SIN6_SCOPE_ID 1055 a6->sin6_scope_id == b6->sin6_scope_id && 1056 #endif 1057 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 1058 default: 1059 return 0; 1060 } 1061 } 1062 1063 #ifdef NEED_PSELECT 1064 /* XXX needs to move to the porting library. */ 1065 static int 1066 pselect(int nfds, void *rfds, void *wfds, void *efds, 1067 struct timespec *tsp, const sigset_t *sigmask) 1068 { 1069 struct timeval tv, *tvp; 1070 sigset_t sigs; 1071 int n; 1072 1073 if (tsp) { 1074 tvp = &tv; 1075 tv = evTimeVal(*tsp); 1076 } else 1077 tvp = NULL; 1078 if (sigmask) 1079 sigprocmask(SIG_SETMASK, sigmask, &sigs); 1080 n = select(nfds, rfds, wfds, efds, tvp); 1081 if (sigmask) 1082 sigprocmask(SIG_SETMASK, &sigs, NULL); 1083 if (tsp) 1084 *tsp = evTimeSpec(tv); 1085 return (n); 1086 } 1087 #endif 1088