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