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