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