1 /* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */ 2 3 /* 4 * Copyright 2008 Android Open Source Project (source port randomization) 5 * Copyright (c) 1985, 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 /* 38 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 39 * 40 * Permission to use, copy, modify, and distribute this software for any 41 * purpose with or without fee is hereby granted, provided that the above 42 * copyright notice and this permission notice appear in all copies, and that 43 * the name of Digital Equipment Corporation not be used in advertising or 44 * publicity pertaining to distribution of the document or software without 45 * specific, written prior permission. 46 * 47 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 48 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 49 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 50 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 51 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 52 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 53 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 54 * SOFTWARE. 55 */ 56 57 /* 58 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 59 * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 60 * 61 * Permission to use, copy, modify, and distribute this software for any 62 * purpose with or without fee is hereby granted, provided that the above 63 * copyright notice and this permission notice appear in all copies. 64 * 65 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 66 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 67 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 68 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 69 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 70 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 71 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 72 */ 73 74 #include <sys/cdefs.h> 75 #if defined(LIBC_SCCS) && !defined(lint) 76 #ifdef notdef 77 static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 78 static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp"; 79 #else 80 __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $"); 81 #endif 82 #endif /* LIBC_SCCS and not lint */ 83 84 /* set to 1 to use our small/simple/limited DNS cache */ 85 #define USE_RESOLV_CACHE 1 86 87 /* 88 * Send query to name server and wait for reply. 89 */ 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 <fcntl.h> 103 #include <netdb.h> 104 #ifdef ANDROID_CHANGES 105 #include "resolv_private.h" 106 #else 107 #include <resolv.h> 108 #endif 109 #include <signal.h> 110 #include <stdio.h> 111 #include <stdlib.h> 112 #include <string.h> 113 #include <time.h> 114 #include <unistd.h> 115 116 #include <isc/eventlib.h> 117 118 #if USE_RESOLV_CACHE 119 # include <resolv_cache.h> 120 #endif 121 122 #include "libc_logging.h" 123 124 #ifndef DE_CONST 125 #define DE_CONST(c,v) v = ((c) ? \ 126 strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL) 127 #endif 128 129 /* Options. Leave them on. */ 130 #ifndef DEBUG 131 #define DEBUG 132 #endif 133 #include "res_debug.h" 134 #include "res_private.h" 135 136 #define EXT(res) ((res)->_u._ext) 137 #define DBG 0 138 139 static const int highestFD = FD_SETSIZE - 1; 140 141 /* Forward. */ 142 143 static int get_salen __P((const struct sockaddr *)); 144 static struct sockaddr * get_nsaddr __P((res_state, size_t)); 145 static int send_vc(res_state, const u_char *, int, 146 u_char *, int, int *, int); 147 static int send_dg(res_state, const u_char *, int, 148 u_char *, int, int *, int, 149 int *, int *); 150 static void Aerror(const res_state, FILE *, const char *, int, 151 const struct sockaddr *, int); 152 static void Perror(const res_state, FILE *, const char *, int); 153 static int sock_eq(struct sockaddr *, struct sockaddr *); 154 #ifdef NEED_PSELECT 155 static int pselect(int, void *, void *, void *, 156 struct timespec *, 157 const sigset_t *); 158 #endif 159 void res_pquery(const res_state, const u_char *, int, FILE *); 160 static int connect_with_timeout(int sock, const struct sockaddr *nsap, 161 socklen_t salen, int sec); 162 static int retrying_select(const int sock, fd_set *readset, fd_set *writeset, 163 const struct timespec *finish); 164 165 /* BIONIC-BEGIN: implement source port randomization */ 166 typedef union { 167 struct sockaddr sa; 168 struct sockaddr_in sin; 169 struct sockaddr_in6 sin6; 170 } _sockaddr_union; 171 172 static int 173 random_bind( int s, int family ) 174 { 175 _sockaddr_union u; 176 int j; 177 socklen_t slen; 178 179 /* clear all, this also sets the IP4/6 address to 'any' */ 180 memset( &u, 0, sizeof u ); 181 182 switch (family) { 183 case AF_INET: 184 u.sin.sin_family = family; 185 slen = sizeof u.sin; 186 break; 187 case AF_INET6: 188 u.sin6.sin6_family = family; 189 slen = sizeof u.sin6; 190 break; 191 default: 192 errno = EPROTO; 193 return -1; 194 } 195 196 /* first try to bind to a random source port a few times */ 197 for (j = 0; j < 10; j++) { 198 /* find a random port between 1025 .. 65534 */ 199 int port = 1025 + (res_randomid() % (65535-1025)); 200 if (family == AF_INET) 201 u.sin.sin_port = htons(port); 202 else 203 u.sin6.sin6_port = htons(port); 204 205 if ( !bind( s, &u.sa, slen ) ) 206 return 0; 207 } 208 209 /* nothing after 10 tries, our network table is probably busy */ 210 /* let the system decide which port is best */ 211 if (family == AF_INET) 212 u.sin.sin_port = 0; 213 else 214 u.sin6.sin6_port = 0; 215 216 return bind( s, &u.sa, slen ); 217 } 218 /* BIONIC-END */ 219 220 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 221 222 /* Public. */ 223 224 /* int 225 * res_isourserver(ina) 226 * looks up "ina" in _res.ns_addr_list[] 227 * returns: 228 * 0 : not found 229 * >0 : found 230 * author: 231 * paul vixie, 29may94 232 */ 233 __LIBC_HIDDEN__ int 234 res_ourserver_p(const res_state statp, const struct sockaddr *sa) { 235 const struct sockaddr_in *inp, *srv; 236 const struct sockaddr_in6 *in6p, *srv6; 237 int ns; 238 239 switch (sa->sa_family) { 240 case AF_INET: 241 inp = (const struct sockaddr_in *)(const void *)sa; 242 for (ns = 0; ns < statp->nscount; ns++) { 243 srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns); 244 if (srv->sin_family == inp->sin_family && 245 srv->sin_port == inp->sin_port && 246 (srv->sin_addr.s_addr == INADDR_ANY || 247 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) 248 return (1); 249 } 250 break; 251 case AF_INET6: 252 if (EXT(statp).ext == NULL) 253 break; 254 in6p = (const struct sockaddr_in6 *)(const void *)sa; 255 for (ns = 0; ns < statp->nscount; ns++) { 256 srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns); 257 if (srv6->sin6_family == in6p->sin6_family && 258 srv6->sin6_port == in6p->sin6_port && 259 #ifdef HAVE_SIN6_SCOPE_ID 260 (srv6->sin6_scope_id == 0 || 261 srv6->sin6_scope_id == in6p->sin6_scope_id) && 262 #endif 263 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || 264 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) 265 return (1); 266 } 267 break; 268 default: 269 break; 270 } 271 return (0); 272 } 273 274 /* int 275 * res_nameinquery(name, type, class, buf, eom) 276 * look for (name,type,class) in the query section of packet (buf,eom) 277 * requires: 278 * buf + HFIXEDSZ <= eom 279 * returns: 280 * -1 : format error 281 * 0 : not found 282 * >0 : found 283 * author: 284 * paul vixie, 29may94 285 */ 286 int 287 res_nameinquery(const char *name, int type, int class, 288 const u_char *buf, const u_char *eom) 289 { 290 const u_char *cp = buf + HFIXEDSZ; 291 int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount); 292 293 while (qdcount-- > 0) { 294 char tname[MAXDNAME+1]; 295 int n, ttype, tclass; 296 297 n = dn_expand(buf, eom, cp, tname, sizeof tname); 298 if (n < 0) 299 return (-1); 300 cp += n; 301 if (cp + 2 * INT16SZ > eom) 302 return (-1); 303 ttype = ns_get16(cp); cp += INT16SZ; 304 tclass = ns_get16(cp); cp += INT16SZ; 305 if (ttype == type && tclass == class && 306 ns_samename(tname, name) == 1) 307 return (1); 308 } 309 return (0); 310 } 311 312 /* int 313 * res_queriesmatch(buf1, eom1, buf2, eom2) 314 * is there a 1:1 mapping of (name,type,class) 315 * in (buf1,eom1) and (buf2,eom2)? 316 * returns: 317 * -1 : format error 318 * 0 : not a 1:1 mapping 319 * >0 : is a 1:1 mapping 320 * author: 321 * paul vixie, 29may94 322 */ 323 int 324 res_queriesmatch(const u_char *buf1, const u_char *eom1, 325 const u_char *buf2, const u_char *eom2) 326 { 327 const u_char *cp = buf1 + HFIXEDSZ; 328 int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount); 329 330 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 331 return (-1); 332 333 /* 334 * Only header section present in replies to 335 * dynamic update packets. 336 */ 337 if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) && 338 (((const HEADER *)(const void *)buf2)->opcode == ns_o_update)) 339 return (1); 340 341 if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount)) 342 return (0); 343 while (qdcount-- > 0) { 344 char tname[MAXDNAME+1]; 345 int n, ttype, tclass; 346 347 n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 348 if (n < 0) 349 return (-1); 350 cp += n; 351 if (cp + 2 * INT16SZ > eom1) 352 return (-1); 353 ttype = ns_get16(cp); cp += INT16SZ; 354 tclass = ns_get16(cp); cp += INT16SZ; 355 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 356 return (0); 357 } 358 return (1); 359 } 360 361 362 int 363 res_nsend(res_state statp, 364 const u_char *buf, int buflen, u_char *ans, int anssiz) 365 { 366 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; 367 char abuf[NI_MAXHOST]; 368 #if USE_RESOLV_CACHE 369 struct resolv_cache* cache; 370 ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED; 371 #endif 372 373 #if !USE_RESOLV_CACHE 374 if (statp->nscount == 0) { 375 errno = ESRCH; 376 return (-1); 377 } 378 #endif 379 380 if (anssiz < HFIXEDSZ) { 381 errno = EINVAL; 382 return (-1); 383 } 384 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), 385 (stdout, ";; res_send()\n"), buf, buflen); 386 v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; 387 gotsomewhere = 0; 388 terrno = ETIMEDOUT; 389 390 #if USE_RESOLV_CACHE 391 // get the cache associated with the interface 392 cache = __get_res_cache(statp->iface); 393 if (cache != NULL) { 394 int anslen = 0; 395 cache_status = _resolv_cache_lookup( 396 cache, buf, buflen, 397 ans, anssiz, &anslen); 398 399 if (cache_status == RESOLV_CACHE_FOUND) { 400 return anslen; 401 } else { 402 // had a cache miss for a known interface, so populate the thread private 403 // data so the normal resolve path can do its thing 404 _resolv_populate_res_for_iface(statp); 405 } 406 } 407 408 if (statp->nscount == 0) { 409 errno = ESRCH; 410 return (-1); 411 } 412 #endif 413 414 /* 415 * If the ns_addr_list in the resolver context has changed, then 416 * invalidate our cached copy and the associated timing data. 417 */ 418 if (EXT(statp).nscount != 0) { 419 int needclose = 0; 420 struct sockaddr_storage peer; 421 socklen_t peerlen; 422 423 if (EXT(statp).nscount != statp->nscount) 424 needclose++; 425 else 426 for (ns = 0; ns < statp->nscount; ns++) { 427 if (statp->nsaddr_list[ns].sin_family && 428 !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns], 429 (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) { 430 needclose++; 431 break; 432 } 433 434 if (EXT(statp).nssocks[ns] == -1) 435 continue; 436 peerlen = sizeof(peer); 437 if (getpeername(EXT(statp).nssocks[ns], 438 (struct sockaddr *)(void *)&peer, &peerlen) < 0) { 439 needclose++; 440 break; 441 } 442 if (!sock_eq((struct sockaddr *)(void *)&peer, 443 get_nsaddr(statp, (size_t)ns))) { 444 needclose++; 445 break; 446 } 447 } 448 if (needclose) { 449 res_nclose(statp); 450 EXT(statp).nscount = 0; 451 } 452 } 453 454 /* 455 * Maybe initialize our private copy of the ns_addr_list. 456 */ 457 if (EXT(statp).nscount == 0) { 458 for (ns = 0; ns < statp->nscount; ns++) { 459 EXT(statp).nstimes[ns] = RES_MAXTIME; 460 EXT(statp).nssocks[ns] = -1; 461 if (!statp->nsaddr_list[ns].sin_family) 462 continue; 463 EXT(statp).ext->nsaddrs[ns].sin = 464 statp->nsaddr_list[ns]; 465 } 466 EXT(statp).nscount = statp->nscount; 467 } 468 469 /* 470 * Some resolvers want to even out the load on their nameservers. 471 * Note that RES_BLAST overrides RES_ROTATE. 472 */ 473 if ((statp->options & RES_ROTATE) != 0U && 474 (statp->options & RES_BLAST) == 0U) { 475 union res_sockaddr_union inu; 476 struct sockaddr_in ina; 477 int lastns = statp->nscount - 1; 478 int fd; 479 u_int16_t nstime; 480 481 if (EXT(statp).ext != NULL) 482 inu = EXT(statp).ext->nsaddrs[0]; 483 ina = statp->nsaddr_list[0]; 484 fd = EXT(statp).nssocks[0]; 485 nstime = EXT(statp).nstimes[0]; 486 for (ns = 0; ns < lastns; ns++) { 487 if (EXT(statp).ext != NULL) 488 EXT(statp).ext->nsaddrs[ns] = 489 EXT(statp).ext->nsaddrs[ns + 1]; 490 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; 491 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; 492 EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; 493 } 494 if (EXT(statp).ext != NULL) 495 EXT(statp).ext->nsaddrs[lastns] = inu; 496 statp->nsaddr_list[lastns] = ina; 497 EXT(statp).nssocks[lastns] = fd; 498 EXT(statp).nstimes[lastns] = nstime; 499 } 500 501 /* 502 * Send request, RETRY times, or until successful. 503 */ 504 for (try = 0; try < statp->retry; try++) { 505 for (ns = 0; ns < statp->nscount; ns++) { 506 struct sockaddr *nsap; 507 int nsaplen; 508 nsap = get_nsaddr(statp, (size_t)ns); 509 nsaplen = get_salen(nsap); 510 statp->_flags &= ~RES_F_LASTMASK; 511 statp->_flags |= (ns << RES_F_LASTSHIFT); 512 same_ns: 513 if (statp->qhook) { 514 int done = 0, loops = 0; 515 516 do { 517 res_sendhookact act; 518 519 act = (*statp->qhook)(&nsap, &buf, &buflen, 520 ans, anssiz, &resplen); 521 switch (act) { 522 case res_goahead: 523 done = 1; 524 break; 525 case res_nextns: 526 res_nclose(statp); 527 goto next_ns; 528 case res_done: 529 return (resplen); 530 case res_modified: 531 /* give the hook another try */ 532 if (++loops < 42) /*doug adams*/ 533 break; 534 /*FALLTHROUGH*/ 535 case res_error: 536 /*FALLTHROUGH*/ 537 default: 538 goto fail; 539 } 540 } while (!done); 541 } 542 543 Dprint(((statp->options & RES_DEBUG) && 544 getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), 545 NULL, 0, niflags) == 0), 546 (stdout, ";; Querying server (# %d) address = %s\n", 547 ns + 1, abuf)); 548 549 550 if (v_circuit) { 551 /* Use VC; at most one attempt per server. */ 552 try = statp->retry; 553 554 n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 555 ns); 556 557 if (DBG) { 558 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 559 "used send_vc %d\n", n); 560 } 561 562 if (n < 0) 563 goto fail; 564 if (n == 0) 565 goto next_ns; 566 resplen = n; 567 } else { 568 /* Use datagrams. */ 569 if (DBG) { 570 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n"); 571 } 572 573 n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, 574 ns, &v_circuit, &gotsomewhere); 575 if (DBG) { 576 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n); 577 } 578 579 if (n < 0) 580 goto fail; 581 if (n == 0) 582 goto next_ns; 583 if (DBG) { 584 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n", 585 time(NULL)); 586 } 587 if (v_circuit) 588 goto same_ns; 589 resplen = n; 590 } 591 592 Dprint((statp->options & RES_DEBUG) || 593 ((statp->pfcode & RES_PRF_REPLY) && 594 (statp->pfcode & RES_PRF_HEAD1)), 595 (stdout, ";; got answer:\n")); 596 597 DprintQ((statp->options & RES_DEBUG) || 598 (statp->pfcode & RES_PRF_REPLY), 599 (stdout, "%s", ""), 600 ans, (resplen > anssiz) ? anssiz : resplen); 601 602 #if USE_RESOLV_CACHE 603 if (cache_status == RESOLV_CACHE_NOTFOUND) { 604 _resolv_cache_add(cache, buf, buflen, 605 ans, resplen); 606 } 607 #endif 608 /* 609 * If we have temporarily opened a virtual circuit, 610 * or if we haven't been asked to keep a socket open, 611 * close the socket. 612 */ 613 if ((v_circuit && (statp->options & RES_USEVC) == 0U) || 614 (statp->options & RES_STAYOPEN) == 0U) { 615 res_nclose(statp); 616 } 617 if (statp->rhook) { 618 int done = 0, loops = 0; 619 620 do { 621 res_sendhookact act; 622 623 act = (*statp->rhook)(nsap, buf, buflen, 624 ans, anssiz, &resplen); 625 switch (act) { 626 case res_goahead: 627 case res_done: 628 done = 1; 629 break; 630 case res_nextns: 631 res_nclose(statp); 632 goto next_ns; 633 case res_modified: 634 /* give the hook another try */ 635 if (++loops < 42) /*doug adams*/ 636 break; 637 /*FALLTHROUGH*/ 638 case res_error: 639 /*FALLTHROUGH*/ 640 default: 641 goto fail; 642 } 643 } while (!done); 644 645 } 646 return (resplen); 647 next_ns: ; 648 } /*foreach ns*/ 649 } /*foreach retry*/ 650 res_nclose(statp); 651 if (!v_circuit) { 652 if (!gotsomewhere) 653 errno = ECONNREFUSED; /* no nameservers found */ 654 else 655 errno = ETIMEDOUT; /* no answer obtained */ 656 } else 657 errno = terrno; 658 659 #if USE_RESOLV_CACHE 660 _resolv_cache_query_failed(cache, buf, buflen); 661 #endif 662 663 return (-1); 664 fail: 665 #if USE_RESOLV_CACHE 666 _resolv_cache_query_failed(cache, buf, buflen); 667 #endif 668 res_nclose(statp); 669 return (-1); 670 } 671 672 /* Private */ 673 674 static int 675 get_salen(sa) 676 const struct sockaddr *sa; 677 { 678 679 #ifdef HAVE_SA_LEN 680 /* There are people do not set sa_len. Be forgiving to them. */ 681 if (sa->sa_len) 682 return (sa->sa_len); 683 #endif 684 685 if (sa->sa_family == AF_INET) 686 return (sizeof(struct sockaddr_in)); 687 else if (sa->sa_family == AF_INET6) 688 return (sizeof(struct sockaddr_in6)); 689 else 690 return (0); /* unknown, die on connect */ 691 } 692 693 /* 694 * pick appropriate nsaddr_list for use. see res_init() for initialization. 695 */ 696 static struct sockaddr * 697 get_nsaddr(statp, n) 698 res_state statp; 699 size_t n; 700 { 701 702 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 703 /* 704 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 705 * than struct sockaddr, and 706 * - user code did not update statp->nsaddr_list[n]. 707 */ 708 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 709 } else { 710 /* 711 * - user code updated statp->nsaddr_list[n], or 712 * - statp->nsaddr_list[n] has the same content as 713 * EXT(statp).ext->nsaddrs[n]. 714 */ 715 return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 716 } 717 } 718 719 static int get_timeout(const res_state statp, const int ns) 720 { 721 int timeout = (statp->retrans << ns); 722 if (ns > 0) { 723 timeout /= statp->nscount; 724 } 725 if (timeout <= 0) { 726 timeout = 1; 727 } 728 if (DBG) { 729 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d sec\n", timeout); 730 } 731 732 return timeout; 733 } 734 735 static int 736 send_vc(res_state statp, 737 const u_char *buf, int buflen, u_char *ans, int anssiz, 738 int *terrno, int ns) 739 { 740 const HEADER *hp = (const HEADER *)(const void *)buf; 741 HEADER *anhp = (HEADER *)(void *)ans; 742 struct sockaddr *nsap; 743 int nsaplen; 744 int truncating, connreset, resplen, n; 745 struct iovec iov[2]; 746 u_short len; 747 u_char *cp; 748 void *tmp; 749 750 if (DBG) { 751 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n"); 752 } 753 754 nsap = get_nsaddr(statp, (size_t)ns); 755 nsaplen = get_salen(nsap); 756 757 connreset = 0; 758 same_ns: 759 truncating = 0; 760 761 /* Are we still talking to whom we want to talk to? */ 762 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 763 struct sockaddr_storage peer; 764 socklen_t size = sizeof peer; 765 int old_mark; 766 int mark_size = sizeof(old_mark); 767 if (getpeername(statp->_vcsock, 768 (struct sockaddr *)(void *)&peer, &size) < 0 || 769 !sock_eq((struct sockaddr *)(void *)&peer, nsap) || 770 getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 || 771 old_mark != statp->_mark) { 772 res_nclose(statp); 773 statp->_flags &= ~RES_F_VC; 774 } 775 } 776 777 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 778 if (statp->_vcsock >= 0) 779 res_nclose(statp); 780 781 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); 782 if (statp->_vcsock > highestFD) { 783 res_nclose(statp); 784 errno = ENOTSOCK; 785 } 786 if (statp->_vcsock < 0) { 787 switch (errno) { 788 case EPROTONOSUPPORT: 789 #ifdef EPFNOSUPPORT 790 case EPFNOSUPPORT: 791 #endif 792 case EAFNOSUPPORT: 793 Perror(statp, stderr, "socket(vc)", errno); 794 return (0); 795 default: 796 *terrno = errno; 797 Perror(statp, stderr, "socket(vc)", errno); 798 return (-1); 799 } 800 } 801 if (statp->_mark != 0) { 802 if (setsockopt(statp->_vcsock, SOL_SOCKET, 803 SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) { 804 *terrno = errno; 805 Perror(statp, stderr, "setsockopt", errno); 806 return -1; 807 } 808 } 809 errno = 0; 810 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) { 811 *terrno = errno; 812 Aerror(statp, stderr, "bind/vc", errno, nsap, 813 nsaplen); 814 res_nclose(statp); 815 return (0); 816 } 817 if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen, 818 get_timeout(statp, ns)) < 0) { 819 *terrno = errno; 820 Aerror(statp, stderr, "connect/vc", errno, nsap, 821 nsaplen); 822 res_nclose(statp); 823 return (0); 824 } 825 statp->_flags |= RES_F_VC; 826 } 827 828 /* 829 * Send length & message 830 */ 831 ns_put16((u_short)buflen, (u_char*)(void *)&len); 832 iov[0] = evConsIovec(&len, INT16SZ); 833 DE_CONST(buf, tmp); 834 iov[1] = evConsIovec(tmp, (size_t)buflen); 835 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 836 *terrno = errno; 837 Perror(statp, stderr, "write failed", errno); 838 res_nclose(statp); 839 return (0); 840 } 841 /* 842 * Receive length & response 843 */ 844 read_len: 845 cp = ans; 846 len = INT16SZ; 847 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) { 848 cp += n; 849 if ((len -= n) == 0) 850 break; 851 } 852 if (n <= 0) { 853 *terrno = errno; 854 Perror(statp, stderr, "read failed", errno); 855 res_nclose(statp); 856 /* 857 * A long running process might get its TCP 858 * connection reset if the remote server was 859 * restarted. Requery the server instead of 860 * trying a new one. When there is only one 861 * server, this means that a query might work 862 * instead of failing. We only allow one reset 863 * per query to prevent looping. 864 */ 865 if (*terrno == ECONNRESET && !connreset) { 866 connreset = 1; 867 res_nclose(statp); 868 goto same_ns; 869 } 870 res_nclose(statp); 871 return (0); 872 } 873 resplen = ns_get16(ans); 874 if (resplen > anssiz) { 875 Dprint(statp->options & RES_DEBUG, 876 (stdout, ";; response truncated\n") 877 ); 878 truncating = 1; 879 len = anssiz; 880 } else 881 len = resplen; 882 if (len < HFIXEDSZ) { 883 /* 884 * Undersized message. 885 */ 886 Dprint(statp->options & RES_DEBUG, 887 (stdout, ";; undersized: %d\n", len)); 888 *terrno = EMSGSIZE; 889 res_nclose(statp); 890 return (0); 891 } 892 cp = ans; 893 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){ 894 cp += n; 895 len -= n; 896 } 897 if (n <= 0) { 898 *terrno = errno; 899 Perror(statp, stderr, "read(vc)", errno); 900 res_nclose(statp); 901 return (0); 902 } 903 if (truncating) { 904 /* 905 * Flush rest of answer so connection stays in synch. 906 */ 907 anhp->tc = 1; 908 len = resplen - anssiz; 909 while (len != 0) { 910 char junk[PACKETSZ]; 911 912 n = read(statp->_vcsock, junk, 913 (len > sizeof junk) ? sizeof junk : len); 914 if (n > 0) 915 len -= n; 916 else 917 break; 918 } 919 } 920 /* 921 * If the calling applicating has bailed out of 922 * a previous call and failed to arrange to have 923 * the circuit closed or the server has got 924 * itself confused, then drop the packet and 925 * wait for the correct one. 926 */ 927 if (hp->id != anhp->id) { 928 DprintQ((statp->options & RES_DEBUG) || 929 (statp->pfcode & RES_PRF_REPLY), 930 (stdout, ";; old answer (unexpected):\n"), 931 ans, (resplen > anssiz) ? anssiz: resplen); 932 goto read_len; 933 } 934 935 /* 936 * All is well, or the error is fatal. Signal that the 937 * next nameserver ought not be tried. 938 */ 939 return (resplen); 940 } 941 942 /* return -1 on error (errno set), 0 on success */ 943 static int 944 connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int sec) 945 { 946 int res, origflags; 947 fd_set rset, wset; 948 struct timespec now, timeout, finish; 949 950 origflags = fcntl(sock, F_GETFL, 0); 951 fcntl(sock, F_SETFL, origflags | O_NONBLOCK); 952 953 res = connect(sock, nsap, salen); 954 if (res < 0 && errno != EINPROGRESS) { 955 res = -1; 956 goto done; 957 } 958 if (res != 0) { 959 now = evNowTime(); 960 timeout = evConsTime((long)sec, 0L); 961 finish = evAddTime(now, timeout); 962 if (DBG) { 963 __libc_format_log(ANDROID_LOG_DEBUG, "libc", " %d send_vc\n", sock); 964 } 965 966 res = retrying_select(sock, &rset, &wset, &finish); 967 if (res <= 0) { 968 res = -1; 969 } 970 } 971 done: 972 fcntl(sock, F_SETFL, origflags); 973 if (DBG) { 974 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 975 " %d connect_with_timeout returning %d\n", sock, res); 976 } 977 return res; 978 } 979 980 static int 981 retrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct timespec *finish) 982 { 983 struct timespec now, timeout; 984 int n, error; 985 socklen_t len; 986 987 988 retry: 989 if (DBG) { 990 __libc_format_log(ANDROID_LOG_DEBUG, "libc", " %d retying_select\n", sock); 991 } 992 993 now = evNowTime(); 994 if (readset) { 995 FD_ZERO(readset); 996 FD_SET(sock, readset); 997 } 998 if (writeset) { 999 FD_ZERO(writeset); 1000 FD_SET(sock, writeset); 1001 } 1002 if (evCmpTime(*finish, now) > 0) 1003 timeout = evSubTime(*finish, now); 1004 else 1005 timeout = evConsTime(0L, 0L); 1006 1007 n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL); 1008 if (n == 0) { 1009 if (DBG) { 1010 __libc_format_log(ANDROID_LOG_DEBUG, " libc", 1011 " %d retrying_select timeout\n", sock); 1012 } 1013 errno = ETIMEDOUT; 1014 return 0; 1015 } 1016 if (n < 0) { 1017 if (errno == EINTR) 1018 goto retry; 1019 if (DBG) { 1020 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 1021 " %d retrying_select got error %d\n",sock, n); 1022 } 1023 return n; 1024 } 1025 if ((readset && FD_ISSET(sock, readset)) || (writeset && FD_ISSET(sock, writeset))) { 1026 len = sizeof(error); 1027 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) { 1028 errno = error; 1029 if (DBG) { 1030 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 1031 " %d retrying_select dot error2 %d\n", sock, errno); 1032 } 1033 1034 return -1; 1035 } 1036 } 1037 if (DBG) { 1038 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 1039 " %d retrying_select returning %d\n",sock, n); 1040 } 1041 1042 return n; 1043 } 1044 1045 1046 static int 1047 send_dg(res_state statp, 1048 const u_char *buf, int buflen, u_char *ans, int anssiz, 1049 int *terrno, int ns, int *v_circuit, int *gotsomewhere) 1050 { 1051 const HEADER *hp = (const HEADER *)(const void *)buf; 1052 HEADER *anhp = (HEADER *)(void *)ans; 1053 const struct sockaddr *nsap; 1054 int nsaplen; 1055 struct timespec now, timeout, finish; 1056 fd_set dsmask; 1057 struct sockaddr_storage from; 1058 socklen_t fromlen; 1059 int resplen, seconds, n, s; 1060 1061 nsap = get_nsaddr(statp, (size_t)ns); 1062 nsaplen = get_salen(nsap); 1063 if (EXT(statp).nssocks[ns] == -1) { 1064 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); 1065 if (EXT(statp).nssocks[ns] > highestFD) { 1066 res_nclose(statp); 1067 errno = ENOTSOCK; 1068 } 1069 if (EXT(statp).nssocks[ns] < 0) { 1070 switch (errno) { 1071 case EPROTONOSUPPORT: 1072 #ifdef EPFNOSUPPORT 1073 case EPFNOSUPPORT: 1074 #endif 1075 case EAFNOSUPPORT: 1076 Perror(statp, stderr, "socket(dg)", errno); 1077 return (0); 1078 default: 1079 *terrno = errno; 1080 Perror(statp, stderr, "socket(dg)", errno); 1081 return (-1); 1082 } 1083 } 1084 1085 if (statp->_mark != 0) { 1086 if (setsockopt(EXT(statp).nssocks[ns], SOL_SOCKET, 1087 SO_MARK, &(statp->_mark), sizeof(statp->_mark)) < 0) { 1088 res_nclose(statp); 1089 return -1; 1090 } 1091 } 1092 #ifndef CANNOT_CONNECT_DGRAM 1093 /* 1094 * On a 4.3BSD+ machine (client and server, 1095 * actually), sending to a nameserver datagram 1096 * port with no nameserver will cause an 1097 * ICMP port unreachable message to be returned. 1098 * If our datagram socket is "connected" to the 1099 * server, we get an ECONNREFUSED error on the next 1100 * socket operation, and select returns if the 1101 * error message is received. We can thus detect 1102 * the absence of a nameserver without timing out. 1103 */ 1104 if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) { 1105 Aerror(statp, stderr, "bind(dg)", errno, nsap, 1106 nsaplen); 1107 res_nclose(statp); 1108 return (0); 1109 } 1110 if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) { 1111 Aerror(statp, stderr, "connect(dg)", errno, nsap, 1112 nsaplen); 1113 res_nclose(statp); 1114 return (0); 1115 } 1116 #endif /* !CANNOT_CONNECT_DGRAM */ 1117 Dprint(statp->options & RES_DEBUG, 1118 (stdout, ";; new DG socket\n")) 1119 1120 } 1121 s = EXT(statp).nssocks[ns]; 1122 #ifndef CANNOT_CONNECT_DGRAM 1123 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) { 1124 Perror(statp, stderr, "send", errno); 1125 res_nclose(statp); 1126 return (0); 1127 } 1128 #else /* !CANNOT_CONNECT_DGRAM */ 1129 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 1130 { 1131 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 1132 res_nclose(statp); 1133 return (0); 1134 } 1135 #endif /* !CANNOT_CONNECT_DGRAM */ 1136 1137 /* 1138 * Wait for reply. 1139 */ 1140 seconds = get_timeout(statp, ns); 1141 now = evNowTime(); 1142 timeout = evConsTime((long)seconds, 0L); 1143 finish = evAddTime(now, timeout); 1144 retry: 1145 n = retrying_select(s, &dsmask, NULL, &finish); 1146 1147 if (n == 0) { 1148 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 1149 *gotsomewhere = 1; 1150 return (0); 1151 } 1152 if (n < 0) { 1153 Perror(statp, stderr, "select", errno); 1154 res_nclose(statp); 1155 return (0); 1156 } 1157 errno = 0; 1158 fromlen = sizeof(from); 1159 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0, 1160 (struct sockaddr *)(void *)&from, &fromlen); 1161 if (resplen <= 0) { 1162 Perror(statp, stderr, "recvfrom", errno); 1163 res_nclose(statp); 1164 return (0); 1165 } 1166 *gotsomewhere = 1; 1167 if (resplen < HFIXEDSZ) { 1168 /* 1169 * Undersized message. 1170 */ 1171 Dprint(statp->options & RES_DEBUG, 1172 (stdout, ";; undersized: %d\n", 1173 resplen)); 1174 *terrno = EMSGSIZE; 1175 res_nclose(statp); 1176 return (0); 1177 } 1178 if (hp->id != anhp->id) { 1179 /* 1180 * response from old query, ignore it. 1181 * XXX - potential security hazard could 1182 * be detected here. 1183 */ 1184 #ifdef ANDROID_CHANGES 1185 __libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_OLD_RESPONSE); 1186 #endif 1187 DprintQ((statp->options & RES_DEBUG) || 1188 (statp->pfcode & RES_PRF_REPLY), 1189 (stdout, ";; old answer:\n"), 1190 ans, (resplen > anssiz) ? anssiz : resplen); 1191 goto retry; 1192 } 1193 if (!(statp->options & RES_INSECURE1) && 1194 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) { 1195 /* 1196 * response from wrong server? ignore it. 1197 * XXX - potential security hazard could 1198 * be detected here. 1199 */ 1200 #ifdef ANDROID_CHANGES 1201 __libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_SERVER); 1202 #endif 1203 DprintQ((statp->options & RES_DEBUG) || 1204 (statp->pfcode & RES_PRF_REPLY), 1205 (stdout, ";; not our server:\n"), 1206 ans, (resplen > anssiz) ? anssiz : resplen); 1207 goto retry; 1208 } 1209 #ifdef RES_USE_EDNS0 1210 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { 1211 /* 1212 * Do not retry if the server do not understand EDNS0. 1213 * The case has to be captured here, as FORMERR packet do not 1214 * carry query section, hence res_queriesmatch() returns 0. 1215 */ 1216 DprintQ(statp->options & RES_DEBUG, 1217 (stdout, "server rejected query with EDNS0:\n"), 1218 ans, (resplen > anssiz) ? anssiz : resplen); 1219 /* record the error */ 1220 statp->_flags |= RES_F_EDNS0ERR; 1221 res_nclose(statp); 1222 return (0); 1223 } 1224 #endif 1225 if (!(statp->options & RES_INSECURE2) && 1226 !res_queriesmatch(buf, buf + buflen, 1227 ans, ans + anssiz)) { 1228 /* 1229 * response contains wrong query? ignore it. 1230 * XXX - potential security hazard could 1231 * be detected here. 1232 */ 1233 #ifdef ANDROID_CHANGES 1234 __libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_QUERY); 1235 #endif 1236 DprintQ((statp->options & RES_DEBUG) || 1237 (statp->pfcode & RES_PRF_REPLY), 1238 (stdout, ";; wrong query name:\n"), 1239 ans, (resplen > anssiz) ? anssiz : resplen); 1240 goto retry;; 1241 } 1242 if (anhp->rcode == SERVFAIL || 1243 anhp->rcode == NOTIMP || 1244 anhp->rcode == REFUSED) { 1245 DprintQ(statp->options & RES_DEBUG, 1246 (stdout, "server rejected query:\n"), 1247 ans, (resplen > anssiz) ? anssiz : resplen); 1248 res_nclose(statp); 1249 /* don't retry if called from dig */ 1250 if (!statp->pfcode) 1251 return (0); 1252 } 1253 if (!(statp->options & RES_IGNTC) && anhp->tc) { 1254 /* 1255 * To get the rest of answer, 1256 * use TCP with same server. 1257 */ 1258 Dprint(statp->options & RES_DEBUG, 1259 (stdout, ";; truncated answer\n")); 1260 *v_circuit = 1; 1261 res_nclose(statp); 1262 return (1); 1263 } 1264 /* 1265 * All is well, or the error is fatal. Signal that the 1266 * next nameserver ought not be tried. 1267 */ 1268 return (resplen); 1269 } 1270 1271 static void 1272 Aerror(const res_state statp, FILE *file, const char *string, int error, 1273 const struct sockaddr *address, int alen) 1274 { 1275 int save = errno; 1276 char hbuf[NI_MAXHOST]; 1277 char sbuf[NI_MAXSERV]; 1278 1279 alen = alen; 1280 1281 if ((statp->options & RES_DEBUG) != 0U) { 1282 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf), 1283 sbuf, sizeof(sbuf), niflags)) { 1284 strncpy(hbuf, "?", sizeof(hbuf) - 1); 1285 hbuf[sizeof(hbuf) - 1] = '\0'; 1286 strncpy(sbuf, "?", sizeof(sbuf) - 1); 1287 sbuf[sizeof(sbuf) - 1] = '\0'; 1288 } 1289 fprintf(file, "res_send: %s ([%s].%s): %s\n", 1290 string, hbuf, sbuf, strerror(error)); 1291 } 1292 errno = save; 1293 } 1294 1295 static void 1296 Perror(const res_state statp, FILE *file, const char *string, int error) { 1297 int save = errno; 1298 1299 if ((statp->options & RES_DEBUG) != 0U) 1300 fprintf(file, "res_send: %s: %s\n", 1301 string, strerror(error)); 1302 errno = save; 1303 } 1304 1305 static int 1306 sock_eq(struct sockaddr *a, struct sockaddr *b) { 1307 struct sockaddr_in *a4, *b4; 1308 struct sockaddr_in6 *a6, *b6; 1309 1310 if (a->sa_family != b->sa_family) 1311 return 0; 1312 switch (a->sa_family) { 1313 case AF_INET: 1314 a4 = (struct sockaddr_in *)(void *)a; 1315 b4 = (struct sockaddr_in *)(void *)b; 1316 return a4->sin_port == b4->sin_port && 1317 a4->sin_addr.s_addr == b4->sin_addr.s_addr; 1318 case AF_INET6: 1319 a6 = (struct sockaddr_in6 *)(void *)a; 1320 b6 = (struct sockaddr_in6 *)(void *)b; 1321 return a6->sin6_port == b6->sin6_port && 1322 #ifdef HAVE_SIN6_SCOPE_ID 1323 a6->sin6_scope_id == b6->sin6_scope_id && 1324 #endif 1325 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 1326 default: 1327 return 0; 1328 } 1329 } 1330 1331 #ifdef NEED_PSELECT 1332 /* XXX needs to move to the porting library. */ 1333 static int 1334 pselect(int nfds, void *rfds, void *wfds, void *efds, 1335 struct timespec *tsp, const sigset_t *sigmask) 1336 { 1337 struct timeval tv, *tvp; 1338 sigset_t sigs; 1339 int n; 1340 1341 if (tsp) { 1342 tvp = &tv; 1343 tv = evTimeVal(*tsp); 1344 } else 1345 tvp = NULL; 1346 if (sigmask) 1347 sigprocmask(SIG_SETMASK, sigmask, &sigs); 1348 n = select(nfds, rfds, wfds, efds, tvp); 1349 if (sigmask) 1350 sigprocmask(SIG_SETMASK, &sigs, NULL); 1351 if (tsp) 1352 *tsp = evTimeSpec(tv); 1353 return (n); 1354 } 1355 #endif 1356