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