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