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