res_send.c revision 228537
136865Sdfr/* 236865Sdfr * Copyright (c) 1985, 1989, 1993 336865Sdfr * The Regents of the University of California. All rights reserved. 436865Sdfr * 536865Sdfr * Redistribution and use in source and binary forms, with or without 636865Sdfr * modification, are permitted provided that the following conditions 736865Sdfr * are met: 836865Sdfr * 1. Redistributions of source code must retain the above copyright 936865Sdfr * notice, this list of conditions and the following disclaimer. 1036865Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1136865Sdfr * notice, this list of conditions and the following disclaimer in the 1236865Sdfr * documentation and/or other materials provided with the distribution. 1336865Sdfr * 4. Neither the name of the University nor the names of its contributors 1436865Sdfr * may be used to endorse or promote products derived from this software 1536865Sdfr * without specific prior written permission. 1636865Sdfr * 1736865Sdfr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1836865Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1936865Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2036865Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2136865Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2236865Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2336865Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2436865Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2536865Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2636865Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2736865Sdfr * SUCH DAMAGE. 2836865Sdfr */ 2936865Sdfr 3036865Sdfr/* 3136865Sdfr * Portions Copyright (c) 1993 by Digital Equipment Corporation. 3236865Sdfr * 3336865Sdfr * Permission to use, copy, modify, and distribute this software for any 3436865Sdfr * purpose with or without fee is hereby granted, provided that the above 3536865Sdfr * copyright notice and this permission notice appear in all copies, and that 3636865Sdfr * the name of Digital Equipment Corporation not be used in advertising or 3736865Sdfr * publicity pertaining to distribution of the document or software without 3836865Sdfr * specific, written prior permission. 3936865Sdfr * 4036865Sdfr * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 4150477Speter * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 4236865Sdfr * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 43139825Simp * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 4436865Sdfr * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 4536865Sdfr * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 4636865Sdfr * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4736865Sdfr * SOFTWARE. 48126474Sgrehan */ 4936865Sdfr 5036865Sdfr/* 5136865Sdfr * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC") 5236865Sdfr * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 5336865Sdfr * 54126474Sgrehan * Permission to use, copy, modify, and distribute this software for any 55126474Sgrehan * purpose with or without fee is hereby granted, provided that the above 56126474Sgrehan * copyright notice and this permission notice appear in all copies. 5736865Sdfr * 58126474Sgrehan * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 5936865Sdfr * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 6036865Sdfr * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 6136865Sdfr * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 6236865Sdfr * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 6336865Sdfr * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 6436865Sdfr * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6536865Sdfr */ 6636865Sdfr 6736865Sdfr#if defined(LIBC_SCCS) && !defined(lint) 6836865Sdfrstatic const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 6936865Sdfrstatic const char rcsid[] = "$Id: res_send.c,v 1.9.18.10 2008/01/27 02:06:26 marka Exp $"; 7036865Sdfr#endif /* LIBC_SCCS and not lint */ 7136865Sdfr#include <sys/cdefs.h> 7236865Sdfr__FBSDID("$FreeBSD: head/lib/libc/resolv/res_send.c 228537 2011-12-15 20:10:12Z dim $"); 7336865Sdfr 7460041Sphk/*! \file 7536865Sdfr * \brief 7685201Smp * Send query to name server and wait for reply. 7785201Smp */ 7867365Sjhb 7936865Sdfr#include "port_before.h" 8036865Sdfr#ifndef USE_KQUEUE 8136865Sdfr#include "fd_setsize.h" 82119563Salc#endif 83122780Salc 8436865Sdfr#include "namespace.h" 85199135Skib#include <sys/types.h> 8654207Speter#include <sys/param.h> 8736865Sdfr#include <sys/time.h> 8836865Sdfr#include <sys/socket.h> 8941499Sdfr#include <sys/uio.h> 9097397Sbenno 9136865Sdfr#include <netinet/in.h> 92138129Sdas#include <arpa/nameser.h> 9336865Sdfr#include <arpa/inet.h> 9478342Sbenno 9578342Sbenno#include <errno.h> 9636865Sdfr#include <netdb.h> 9736865Sdfr#include <resolv.h> 9836865Sdfr#include <signal.h> 9936865Sdfr#include <stdio.h> 10036865Sdfr#include <stdlib.h> 10136865Sdfr#include <string.h> 10236865Sdfr#include <unistd.h> 10336865Sdfr 104190681Snwhitehorn#include <isc/eventlib.h> 105190681Snwhitehorn 106190681Snwhitehorn#include "port_after.h" 107190681Snwhitehorn 108190681Snwhitehorn#ifdef USE_KQUEUE 109190681Snwhitehorn#include <sys/event.h> 110190681Snwhitehorn#else 111256792Snwhitehorn#ifdef USE_POLL 112190681Snwhitehorn#ifdef HAVE_STROPTS_H 113190681Snwhitehorn#include <stropts.h> 114255786Sglebius#endif 115255786Sglebius#include <poll.h> 116255786Sglebius#endif /* USE_POLL */ 117255786Sglebius#endif 118255786Sglebius 119255786Sglebius#include "un-namespace.h" 120255786Sglebius 121255786Sglebius/* Options. Leave them on. */ 122255786Sglebius#define DEBUG 123255786Sglebius#include "res_debug.h" 124255786Sglebius#include "res_private.h" 125190681Snwhitehorn 126190681Snwhitehorn#define EXT(res) ((res)->_u._ext) 127190681Snwhitehorn 128190681Snwhitehorn#if !defined(USE_POLL) && !defined(USE_KQUEUE) 129190681Snwhitehornstatic const int highestFD = FD_SETSIZE - 1; 130190681Snwhitehorn#endif 131190681Snwhitehorn 132190681Snwhitehorn/* Forward. */ 133190681Snwhitehorn 134190681Snwhitehornstatic int get_salen(const struct sockaddr *); 135190681Snwhitehornstatic struct sockaddr * get_nsaddr(res_state, size_t); 136190681Snwhitehornstatic int send_vc(res_state, const u_char *, int, 137190681Snwhitehorn u_char *, int, int *, int); 138190681Snwhitehornstatic int send_dg(res_state, 139190681Snwhitehorn#ifdef USE_KQUEUE 140190681Snwhitehorn int kq, 141190681Snwhitehorn#endif 142190681Snwhitehorn const u_char *, int, 143190681Snwhitehorn u_char *, int, int *, int, int, 144209975Snwhitehorn int *, int *); 145209975Snwhitehornstatic void Aerror(const res_state, FILE *, const char *, int, 146209975Snwhitehorn const struct sockaddr *, int); 147190681Snwhitehornstatic void Perror(const res_state, FILE *, const char *, int); 148209975Snwhitehornstatic int sock_eq(struct sockaddr *, struct sockaddr *); 149190681Snwhitehorn#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) 15036865Sdfrstatic int pselect(int, void *, void *, void *, 15136865Sdfr struct timespec *, 15236865Sdfr const sigset_t *); 15336865Sdfr#endif 15436865Sdfrvoid res_pquery(const res_state, const u_char *, int, FILE *); 15590361Sjulian 15636865Sdfrstatic const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 15784977Sbenno 15884977Sbenno/* Public. */ 15990643Sbenno 16084977Sbenno/*% 16191467Sbenno * looks up "ina" in _res.ns_addr_list[] 16290643Sbenno * 163209975Snwhitehorn * returns: 164209975Snwhitehorn *\li 0 : not found 16584977Sbenno *\li >0 : found 16684977Sbenno * 16784977Sbenno * author: 16884977Sbenno *\li paul vixie, 29may94 169127582Speter */ 170209975Snwhitehornint 17190643Sbennores_ourserver_p(const res_state statp, const struct sockaddr *sa) { 17284977Sbenno const struct sockaddr_in *inp, *srv; 17390643Sbenno const struct sockaddr_in6 *in6p, *srv6; 17490643Sbenno int ns; 17584977Sbenno 17684977Sbenno switch (sa->sa_family) { 17790643Sbenno case AF_INET: 17884977Sbenno inp = (const struct sockaddr_in *)sa; 17984977Sbenno for (ns = 0; ns < statp->nscount; ns++) { 18084977Sbenno srv = (struct sockaddr_in *)get_nsaddr(statp, ns); 18190643Sbenno if (srv->sin_family == inp->sin_family && 18290643Sbenno srv->sin_port == inp->sin_port && 18384977Sbenno (srv->sin_addr.s_addr == INADDR_ANY || 18497397Sbenno srv->sin_addr.s_addr == inp->sin_addr.s_addr)) 18597397Sbenno return (1); 18697397Sbenno } 18797397Sbenno break; 18890643Sbenno case AF_INET6: 18990643Sbenno if (EXT(statp).ext == NULL) 19090643Sbenno break; 19190643Sbenno in6p = (const struct sockaddr_in6 *)sa; 192132520Sgrehan for (ns = 0; ns < statp->nscount; ns++) { 193209975Snwhitehorn srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); 194209975Snwhitehorn if (srv6->sin6_family == in6p->sin6_family && 195209975Snwhitehorn srv6->sin6_port == in6p->sin6_port && 19691467Sbenno#ifdef HAVE_SIN6_SCOPE_ID 19791467Sbenno (srv6->sin6_scope_id == 0 || 19891467Sbenno srv6->sin6_scope_id == in6p->sin6_scope_id) && 19984977Sbenno#endif 20091467Sbenno (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || 201255273Snwhitehorn IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) 202209975Snwhitehorn return (1); 203209975Snwhitehorn } 204209975Snwhitehorn break; 205209975Snwhitehorn default: 20691467Sbenno break; 207209975Snwhitehorn } 208256792Snwhitehorn return (0); 209209975Snwhitehorn} 210256792Snwhitehorn 21184977Sbenno/*% 212170305Sjeff * look for (name,type,class) in the query section of packet (buf,eom) 213144637Sjhb * 214144637Sjhb * requires: 215144637Sjhb *\li buf + HFIXEDSZ <= eom 21690643Sbenno * 21790643Sbenno * returns: 21890643Sbenno *\li -1 : format error 21936865Sdfr *\li 0 : not found 22036865Sdfr *\li >0 : found 22136865Sdfr * 22236865Sdfr * author: 22336865Sdfr *\li paul vixie, 29may94 22436865Sdfr */ 22536865Sdfrint 22636865Sdfrres_nameinquery(const char *name, int type, int class, 22736865Sdfr const u_char *buf, const u_char *eom) 228256792Snwhitehorn{ 22936865Sdfr const u_char *cp = buf + HFIXEDSZ; 230256792Snwhitehorn int qdcount = ntohs(((const HEADER*)buf)->qdcount); 23184977Sbenno 232209975Snwhitehorn while (qdcount-- > 0) { 233209975Snwhitehorn char tname[MAXDNAME+1]; 23484977Sbenno int n, ttype, tclass; 23591467Sbenno 23684977Sbenno n = dn_expand(buf, eom, cp, tname, sizeof tname); 23791467Sbenno if (n < 0) 23891467Sbenno return (-1); 23936865Sdfr cp += n; 24036865Sdfr if (cp + 2 * INT16SZ > eom) 24136865Sdfr return (-1); 242256792Snwhitehorn ttype = ns_get16(cp); cp += INT16SZ; 24336865Sdfr tclass = ns_get16(cp); cp += INT16SZ; 244256792Snwhitehorn if (ttype == type && tclass == class && 24536865Sdfr ns_samename(tname, name) == 1) 24636865Sdfr return (1); 24736865Sdfr } 248190681Snwhitehorn return (0); 249119563Salc} 250190681Snwhitehorn 251190681Snwhitehorn/*% 252190681Snwhitehorn * is there a 1:1 mapping of (name,type,class) 253256792Snwhitehorn * in (buf1,eom1) and (buf2,eom2)? 254256792Snwhitehorn * 255256792Snwhitehorn * returns: 256190681Snwhitehorn *\li -1 : format error 257190681Snwhitehorn *\li 0 : not a 1:1 mapping 258190681Snwhitehorn *\li >0 : is a 1:1 mapping 259190681Snwhitehorn * 260190681Snwhitehorn * author: 261256792Snwhitehorn *\li paul vixie, 29may94 262256792Snwhitehorn */ 263190681Snwhitehornint 264256792Snwhitehornres_queriesmatch(const u_char *buf1, const u_char *eom1, 265256792Snwhitehorn const u_char *buf2, const u_char *eom2) 266256792Snwhitehorn{ 267256792Snwhitehorn const u_char *cp = buf1 + HFIXEDSZ; 268256792Snwhitehorn int qdcount = ntohs(((const HEADER*)buf1)->qdcount); 269190681Snwhitehorn 270256792Snwhitehorn if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 271256792Snwhitehorn return (-1); 272256792Snwhitehorn 273256792Snwhitehorn /* 274256792Snwhitehorn * Only header section present in replies to 275256792Snwhitehorn * dynamic update packets. 276190681Snwhitehorn */ 277190681Snwhitehorn if ((((const HEADER *)buf1)->opcode == ns_o_update) && 278190681Snwhitehorn (((const HEADER *)buf2)->opcode == ns_o_update)) 279190681Snwhitehorn return (1); 280190681Snwhitehorn 281119563Salc if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) 282190681Snwhitehorn return (0); 283119563Salc while (qdcount-- > 0) { 284256792Snwhitehorn char tname[MAXDNAME+1]; 285256792Snwhitehorn int n, ttype, tclass; 286256792Snwhitehorn 287119563Salc n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 288190681Snwhitehorn if (n < 0) 289190681Snwhitehorn return (-1); 290190681Snwhitehorn cp += n; 291190681Snwhitehorn if (cp + 2 * INT16SZ > eom1) 292190681Snwhitehorn return (-1); 293256792Snwhitehorn ttype = ns_get16(cp); cp += INT16SZ; 294256792Snwhitehorn tclass = ns_get16(cp); cp += INT16SZ; 295256792Snwhitehorn if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 296256792Snwhitehorn return (0); 297256792Snwhitehorn } 298256792Snwhitehorn return (1); 299256792Snwhitehorn} 300256792Snwhitehorn 301256792Snwhitehornint 302256792Snwhitehornres_nsend(res_state statp, 303256792Snwhitehorn const u_char *buf, int buflen, u_char *ans, int anssiz) 304256792Snwhitehorn{ 305256792Snwhitehorn int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n; 306190681Snwhitehorn#ifdef USE_KQUEUE 307256792Snwhitehorn int kq; 308256792Snwhitehorn#endif 309256792Snwhitehorn char abuf[NI_MAXHOST]; 310190681Snwhitehorn 311256792Snwhitehorn /* No name servers or res_init() failure */ 312256792Snwhitehorn if (statp->nscount == 0 || EXT(statp).ext == NULL) { 313256792Snwhitehorn errno = ESRCH; 314256792Snwhitehorn return (-1); 315256792Snwhitehorn } 316190681Snwhitehorn if (anssiz < HFIXEDSZ) { 317256792Snwhitehorn errno = EINVAL; 318256792Snwhitehorn return (-1); 319256792Snwhitehorn } 320256792Snwhitehorn DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), 321256792Snwhitehorn (stdout, ";; res_send()\n"), buf, buflen); 322256792Snwhitehorn v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; 323190681Snwhitehorn gotsomewhere = 0; 324256792Snwhitehorn terrno = ETIMEDOUT; 325256792Snwhitehorn 326256792Snwhitehorn#ifdef USE_KQUEUE 327190681Snwhitehorn if ((kq = kqueue()) < 0) { 328256792Snwhitehorn Perror(statp, stderr, "kqueue", errno); 329256792Snwhitehorn return (-1); 330256792Snwhitehorn } 331256792Snwhitehorn#endif 332256792Snwhitehorn 333256792Snwhitehorn /* 334190681Snwhitehorn * If the ns_addr_list in the resolver context has changed, then 335256792Snwhitehorn * invalidate our cached copy and the associated timing data. 336256792Snwhitehorn */ 337119563Salc if (EXT(statp).nscount != 0) { 338119563Salc int needclose = 0; 339119563Salc struct sockaddr_storage peer; 340256792Snwhitehorn ISC_SOCKLEN_T peerlen; 341190681Snwhitehorn 342190681Snwhitehorn if (EXT(statp).nscount != statp->nscount) 343190681Snwhitehorn needclose++; 344190681Snwhitehorn else 345190681Snwhitehorn for (ns = 0; ns < statp->nscount; ns++) { 346119563Salc if (statp->nsaddr_list[ns].sin_family && 347119563Salc !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], 348127086Salc (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { 349119563Salc needclose++; 350190681Snwhitehorn break; 351190681Snwhitehorn } 352190681Snwhitehorn 353256792Snwhitehorn if (EXT(statp).nssocks[ns] == -1) 354256792Snwhitehorn continue; 355256792Snwhitehorn peerlen = sizeof(peer); 356256792Snwhitehorn if (_getsockname(EXT(statp).nssocks[ns], 357256792Snwhitehorn (struct sockaddr *)&peer, &peerlen) < 0) { 358190681Snwhitehorn needclose++; 359256792Snwhitehorn break; 360256792Snwhitehorn } 361256792Snwhitehorn if (!sock_eq((struct sockaddr *)&peer, 362256792Snwhitehorn get_nsaddr(statp, ns))) { 363119563Salc needclose++; 364119563Salc break; 365119563Salc } 36636865Sdfr } 367126474Sgrehan if (needclose) { 368126474Sgrehan res_nclose(statp); 369126474Sgrehan EXT(statp).nscount = 0; 370126474Sgrehan } 371209950Snwhitehorn } 37236865Sdfr 37336865Sdfr /* 37436865Sdfr * Maybe initialize our private copy of the ns_addr_list. 37536865Sdfr */ 37636865Sdfr if (EXT(statp).nscount == 0) { 37736865Sdfr for (ns = 0; ns < statp->nscount; ns++) { 37836865Sdfr EXT(statp).nstimes[ns] = RES_MAXTIME; 37936865Sdfr EXT(statp).nssocks[ns] = -1; 38036865Sdfr if (!statp->nsaddr_list[ns].sin_family) 38136865Sdfr continue; 38236865Sdfr EXT(statp).ext->nsaddrs[ns].sin = 383256792Snwhitehorn statp->nsaddr_list[ns]; 38436865Sdfr } 385256792Snwhitehorn EXT(statp).nscount = statp->nscount; 38636865Sdfr } 38736865Sdfr 38836865Sdfr /* 38936865Sdfr * Some resolvers want to even out the load on their nameservers. 390256792Snwhitehorn * Note that RES_BLAST overrides RES_ROTATE. 39136865Sdfr */ 39299659Sbenno if ((statp->options & RES_ROTATE) != 0U && 39399659Sbenno (statp->options & RES_BLAST) == 0U) { 394209975Snwhitehorn union res_sockaddr_union inu; 395209975Snwhitehorn struct sockaddr_in ina; 396209975Snwhitehorn int lastns = statp->nscount - 1; 39799659Sbenno int fd; 39899659Sbenno u_int16_t nstime; 39999659Sbenno 400119004Smarcel if (EXT(statp).ext != NULL) 401119004Smarcel inu = EXT(statp).ext->nsaddrs[0]; 402256792Snwhitehorn ina = statp->nsaddr_list[0]; 40399659Sbenno fd = EXT(statp).nssocks[0]; 40499659Sbenno nstime = EXT(statp).nstimes[0]; 40599659Sbenno for (ns = 0; ns < lastns; ns++) { 406119004Smarcel if (EXT(statp).ext != NULL) 407119004Smarcel EXT(statp).ext->nsaddrs[ns] = 408256792Snwhitehorn EXT(statp).ext->nsaddrs[ns + 1]; 409119004Smarcel statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; 410119004Smarcel EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; 411 EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; 412 } 413 if (EXT(statp).ext != NULL) 414 EXT(statp).ext->nsaddrs[lastns] = inu; 415 statp->nsaddr_list[lastns] = ina; 416 EXT(statp).nssocks[lastns] = fd; 417 EXT(statp).nstimes[lastns] = nstime; 418 } 419 420 /* 421 * Send request, RETRY times, or until successful. 422 */ 423 for (tries = 0; tries < statp->retry; tries++) { 424 for (ns = 0; ns < statp->nscount; ns++) { 425 struct sockaddr *nsap; 426 int nsaplen; 427 nsap = get_nsaddr(statp, ns); 428 nsaplen = get_salen(nsap); 429 statp->_flags &= ~RES_F_LASTMASK; 430 statp->_flags |= (ns << RES_F_LASTSHIFT); 431 same_ns: 432 if (statp->qhook) { 433 int done = 0, loops = 0; 434 435 do { 436 res_sendhookact act; 437 438 act = (*statp->qhook)(&nsap, &buf, &buflen, 439 ans, anssiz, &resplen); 440 switch (act) { 441 case res_goahead: 442 done = 1; 443 break; 444 case res_nextns: 445 res_nclose(statp); 446 goto next_ns; 447 case res_done: 448#ifdef USE_KQUEUE 449 _close(kq); 450#endif 451 return (resplen); 452 case res_modified: 453 /* give the hook another try */ 454 if (++loops < 42) /*doug adams*/ 455 break; 456 /*FALLTHROUGH*/ 457 case res_error: 458 /*FALLTHROUGH*/ 459 default: 460 goto fail; 461 } 462 } while (!done); 463 } 464 465 Dprint(((statp->options & RES_DEBUG) && 466 getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), 467 NULL, 0, niflags) == 0), 468 (stdout, ";; Querying server (# %d) address = %s\n", 469 ns + 1, abuf)); 470 471 472 if (v_circuit) { 473 /* Use VC; at most one attempt per server. */ 474 tries = statp->retry; 475 n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 476 ns); 477 if (n < 0) 478 goto fail; 479 if (n == 0) 480 goto next_ns; 481 resplen = n; 482 } else { 483 /* Use datagrams. */ 484 n = send_dg(statp, 485#ifdef USE_KQUEUE 486 kq, 487#endif 488 buf, buflen, ans, anssiz, &terrno, 489 ns, tries, &v_circuit, &gotsomewhere); 490 if (n < 0) 491 goto fail; 492 if (n == 0) 493 goto next_ns; 494 if (v_circuit) 495 goto same_ns; 496 resplen = n; 497 } 498 499 Dprint((statp->options & RES_DEBUG) || 500 ((statp->pfcode & RES_PRF_REPLY) && 501 (statp->pfcode & RES_PRF_HEAD1)), 502 (stdout, ";; got answer:\n")); 503 504 DprintQ((statp->options & RES_DEBUG) || 505 (statp->pfcode & RES_PRF_REPLY), 506 (stdout, "%s", ""), 507 ans, (resplen > anssiz) ? anssiz : resplen); 508 509 /* 510 * If we have temporarily opened a virtual circuit, 511 * or if we haven't been asked to keep a socket open, 512 * close the socket. 513 */ 514 if ((v_circuit && (statp->options & RES_USEVC) == 0U) || 515 (statp->options & RES_STAYOPEN) == 0U) { 516 res_nclose(statp); 517 } 518 if (statp->rhook) { 519 int done = 0, loops = 0; 520 521 do { 522 res_sendhookact act; 523 524 act = (*statp->rhook)(nsap, buf, buflen, 525 ans, anssiz, &resplen); 526 switch (act) { 527 case res_goahead: 528 case res_done: 529 done = 1; 530 break; 531 case res_nextns: 532 res_nclose(statp); 533 goto next_ns; 534 case res_modified: 535 /* give the hook another try */ 536 if (++loops < 42) /*doug adams*/ 537 break; 538 /*FALLTHROUGH*/ 539 case res_error: 540 /*FALLTHROUGH*/ 541 default: 542 goto fail; 543 } 544 } while (!done); 545 546 } 547#ifdef USE_KQUEUE 548 _close(kq); 549#endif 550 return (resplen); 551 next_ns: ; 552 } /*foreach ns*/ 553 } /*foreach retry*/ 554 res_nclose(statp); 555#ifdef USE_KQUEUE 556 _close(kq); 557#endif 558 if (!v_circuit) { 559 if (!gotsomewhere) 560 errno = ECONNREFUSED; /*%< no nameservers found */ 561 else 562 errno = ETIMEDOUT; /*%< no answer obtained */ 563 } else 564 errno = terrno; 565 return (-1); 566 fail: 567 res_nclose(statp); 568#ifdef USE_KQUEUE 569 _close(kq); 570#endif 571 return (-1); 572} 573 574/* Private */ 575 576static int 577get_salen(sa) 578 const struct sockaddr *sa; 579{ 580 581#ifdef HAVE_SA_LEN 582 /* There are people do not set sa_len. Be forgiving to them. */ 583 if (sa->sa_len) 584 return (sa->sa_len); 585#endif 586 587 if (sa->sa_family == AF_INET) 588 return (sizeof(struct sockaddr_in)); 589 else if (sa->sa_family == AF_INET6) 590 return (sizeof(struct sockaddr_in6)); 591 else 592 return (0); /*%< unknown, die on connect */ 593} 594 595/*% 596 * pick appropriate nsaddr_list for use. see res_init() for initialization. 597 */ 598static struct sockaddr * 599get_nsaddr(statp, n) 600 res_state statp; 601 size_t n; 602{ 603 604 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 605 /* 606 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 607 * than struct sockaddr, and 608 * - user code did not update statp->nsaddr_list[n]. 609 */ 610 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 611 } else { 612 /* 613 * - user code updated statp->nsaddr_list[n], or 614 * - statp->nsaddr_list[n] has the same content as 615 * EXT(statp).ext->nsaddrs[n]. 616 */ 617 return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 618 } 619} 620 621static int 622send_vc(res_state statp, 623 const u_char *buf, int buflen, u_char *ans, int anssiz, 624 int *terrno, int ns) 625{ 626 const HEADER *hp = (const HEADER *) buf; 627 HEADER *anhp = (HEADER *) ans; 628 struct sockaddr *nsap; 629 int nsaplen; 630 int truncating, connreset, resplen, n; 631 struct iovec iov[2]; 632 u_short len; 633 u_char *cp; 634 void *tmp; 635#ifdef SO_NOSIGPIPE 636 int on = 1; 637#endif 638 639 nsap = get_nsaddr(statp, ns); 640 nsaplen = get_salen(nsap); 641 642 connreset = 0; 643 same_ns: 644 truncating = 0; 645 646 /* Are we still talking to whom we want to talk to? */ 647 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 648 struct sockaddr_storage peer; 649 ISC_SOCKLEN_T size = sizeof peer; 650 651 if (_getpeername(statp->_vcsock, 652 (struct sockaddr *)&peer, &size) < 0 || 653 !sock_eq((struct sockaddr *)&peer, nsap)) { 654 res_nclose(statp); 655 statp->_flags &= ~RES_F_VC; 656 } 657 } 658 659 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 660 if (statp->_vcsock >= 0) 661 res_nclose(statp); 662 663 statp->_vcsock = _socket(nsap->sa_family, SOCK_STREAM, 0); 664#if !defined(USE_POLL) && !defined(USE_KQUEUE) 665 if (statp->_vcsock > highestFD) { 666 res_nclose(statp); 667 errno = ENOTSOCK; 668 } 669#endif 670 if (statp->_vcsock < 0) { 671 switch (errno) { 672 case EPROTONOSUPPORT: 673#ifdef EPFNOSUPPORT 674 case EPFNOSUPPORT: 675#endif 676 case EAFNOSUPPORT: 677 Perror(statp, stderr, "socket(vc)", errno); 678 return (0); 679 default: 680 *terrno = errno; 681 Perror(statp, stderr, "socket(vc)", errno); 682 return (-1); 683 } 684 } 685#ifdef SO_NOSIGPIPE 686 /* 687 * Disable generation of SIGPIPE when writing to a closed 688 * socket. Write should return -1 and set errno to EPIPE 689 * instead. 690 * 691 * Push on even if setsockopt(SO_NOSIGPIPE) fails. 692 */ 693 (void)_setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on, 694 sizeof(on)); 695#endif 696 errno = 0; 697 if (_connect(statp->_vcsock, nsap, nsaplen) < 0) { 698 *terrno = errno; 699 Aerror(statp, stderr, "connect/vc", errno, nsap, 700 nsaplen); 701 res_nclose(statp); 702 return (0); 703 } 704 statp->_flags |= RES_F_VC; 705 } 706 707 /* 708 * Send length & message 709 */ 710 ns_put16((u_short)buflen, (u_char*)&len); 711 iov[0] = evConsIovec(&len, INT16SZ); 712 DE_CONST(buf, tmp); 713 iov[1] = evConsIovec(tmp, buflen); 714 if (_writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 715 *terrno = errno; 716 Perror(statp, stderr, "write failed", errno); 717 res_nclose(statp); 718 return (0); 719 } 720 /* 721 * Receive length & response 722 */ 723 read_len: 724 cp = ans; 725 len = INT16SZ; 726 while ((n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) { 727 cp += n; 728 if ((len -= n) == 0) 729 break; 730 } 731 if (n <= 0) { 732 *terrno = errno; 733 Perror(statp, stderr, "read failed", errno); 734 res_nclose(statp); 735 /* 736 * A long running process might get its TCP 737 * connection reset if the remote server was 738 * restarted. Requery the server instead of 739 * trying a new one. When there is only one 740 * server, this means that a query might work 741 * instead of failing. We only allow one reset 742 * per query to prevent looping. 743 */ 744 if (*terrno == ECONNRESET && !connreset) { 745 connreset = 1; 746 res_nclose(statp); 747 goto same_ns; 748 } 749 res_nclose(statp); 750 return (0); 751 } 752 resplen = ns_get16(ans); 753 if (resplen > anssiz) { 754 Dprint(statp->options & RES_DEBUG, 755 (stdout, ";; response truncated\n") 756 ); 757 truncating = 1; 758 len = anssiz; 759 } else 760 len = resplen; 761 if (len < HFIXEDSZ) { 762 /* 763 * Undersized message. 764 */ 765 Dprint(statp->options & RES_DEBUG, 766 (stdout, ";; undersized: %d\n", len)); 767 *terrno = EMSGSIZE; 768 res_nclose(statp); 769 return (0); 770 } 771 cp = ans; 772 while (len != 0 && 773 (n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) { 774 cp += n; 775 len -= n; 776 } 777 if (n <= 0) { 778 *terrno = errno; 779 Perror(statp, stderr, "read(vc)", errno); 780 res_nclose(statp); 781 return (0); 782 } 783 if (truncating) { 784 /* 785 * Flush rest of answer so connection stays in synch. 786 */ 787 anhp->tc = 1; 788 len = resplen - anssiz; 789 while (len != 0) { 790 char junk[PACKETSZ]; 791 792 n = _read(statp->_vcsock, junk, 793 (len > sizeof junk) ? sizeof junk : len); 794 if (n > 0) 795 len -= n; 796 else 797 break; 798 } 799 } 800 /* 801 * If the calling applicating has bailed out of 802 * a previous call and failed to arrange to have 803 * the circuit closed or the server has got 804 * itself confused, then drop the packet and 805 * wait for the correct one. 806 */ 807 if (hp->id != anhp->id) { 808 DprintQ((statp->options & RES_DEBUG) || 809 (statp->pfcode & RES_PRF_REPLY), 810 (stdout, ";; old answer (unexpected):\n"), 811 ans, (resplen > anssiz) ? anssiz: resplen); 812 goto read_len; 813 } 814 815 /* 816 * All is well, or the error is fatal. Signal that the 817 * next nameserver ought not be tried. 818 */ 819 return (resplen); 820} 821 822static int 823send_dg(res_state statp, 824#ifdef USE_KQUEUE 825 int kq, 826#endif 827 const u_char *buf, int buflen, u_char *ans, 828 int anssiz, int *terrno, int ns, int tries, int *v_circuit, 829 int *gotsomewhere) 830{ 831 const HEADER *hp = (const HEADER *) buf; 832 HEADER *anhp = (HEADER *) ans; 833 const struct sockaddr *nsap; 834 int nsaplen; 835 struct timespec now, timeout, finish; 836 struct sockaddr_storage from; 837 ISC_SOCKLEN_T fromlen; 838 int resplen, seconds, n, s; 839#ifdef USE_KQUEUE 840 struct kevent kv; 841#else 842#ifdef USE_POLL 843 int polltimeout; 844 struct pollfd pollfd; 845#else 846 fd_set dsmask; 847#endif 848#endif 849 850 nsap = get_nsaddr(statp, ns); 851 nsaplen = get_salen(nsap); 852 if (EXT(statp).nssocks[ns] == -1) { 853 EXT(statp).nssocks[ns] = _socket(nsap->sa_family, 854 SOCK_DGRAM, 0); 855#if !defined(USE_POLL) && !defined(USE_KQUEUE) 856 if (EXT(statp).nssocks[ns] > highestFD) { 857 res_nclose(statp); 858 errno = ENOTSOCK; 859 } 860#endif 861 if (EXT(statp).nssocks[ns] < 0) { 862 switch (errno) { 863 case EPROTONOSUPPORT: 864#ifdef EPFNOSUPPORT 865 case EPFNOSUPPORT: 866#endif 867 case EAFNOSUPPORT: 868 Perror(statp, stderr, "socket(dg)", errno); 869 return (0); 870 default: 871 *terrno = errno; 872 Perror(statp, stderr, "socket(dg)", errno); 873 return (-1); 874 } 875 } 876#ifndef CANNOT_CONNECT_DGRAM 877 /* 878 * On a 4.3BSD+ machine (client and server, 879 * actually), sending to a nameserver datagram 880 * port with no nameserver will cause an 881 * ICMP port unreachable message to be returned. 882 * If our datagram socket is "connected" to the 883 * server, we get an ECONNREFUSED error on the next 884 * socket operation, and select returns if the 885 * error message is received. We can thus detect 886 * the absence of a nameserver without timing out. 887 * 888 * When the option "insecure1" is specified, we'd 889 * rather expect to see responses from an "unknown" 890 * address. In order to let the kernel accept such 891 * responses, do not connect the socket here. 892 * XXX: or do we need an explicit option to disable 893 * connecting? 894 */ 895 if (!(statp->options & RES_INSECURE1) && 896 _connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { 897 Aerror(statp, stderr, "connect(dg)", errno, nsap, 898 nsaplen); 899 res_nclose(statp); 900 return (0); 901 } 902#endif /* !CANNOT_CONNECT_DGRAM */ 903 Dprint(statp->options & RES_DEBUG, 904 (stdout, ";; new DG socket\n")) 905 } 906 s = EXT(statp).nssocks[ns]; 907#ifndef CANNOT_CONNECT_DGRAM 908 if (statp->options & RES_INSECURE1) { 909 if (_sendto(s, 910 (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) { 911 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 912 res_nclose(statp); 913 return (0); 914 } 915 } else if (send(s, (const char*)buf, buflen, 0) != buflen) { 916 Perror(statp, stderr, "send", errno); 917 res_nclose(statp); 918 return (0); 919 } 920#else /* !CANNOT_CONNECT_DGRAM */ 921 if (_sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 922 { 923 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 924 res_nclose(statp); 925 return (0); 926 } 927#endif /* !CANNOT_CONNECT_DGRAM */ 928 929 /* 930 * Wait for reply. 931 */ 932 seconds = (statp->retrans << tries); 933 if (ns > 0) 934 seconds /= statp->nscount; 935 if (seconds <= 0) 936 seconds = 1; 937 now = evNowTime(); 938 timeout = evConsTime(seconds, 0); 939 finish = evAddTime(now, timeout); 940 goto nonow; 941 wait: 942 now = evNowTime(); 943 nonow: 944#ifndef USE_POLL 945 if (evCmpTime(finish, now) > 0) 946 timeout = evSubTime(finish, now); 947 else 948 timeout = evConsTime(0, 0); 949#ifdef USE_KQUEUE 950 EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0); 951 n = _kevent(kq, &kv, 1, &kv, 1, &timeout); 952#else 953 FD_ZERO(&dsmask); 954 FD_SET(s, &dsmask); 955 n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); 956#endif 957#else 958 timeout = evSubTime(finish, now); 959 if (timeout.tv_sec < 0) 960 timeout = evConsTime(0, 0); 961 polltimeout = 1000*timeout.tv_sec + 962 timeout.tv_nsec/1000000; 963 pollfd.fd = s; 964 pollfd.events = POLLRDNORM; 965 n = poll(&pollfd, 1, polltimeout); 966#endif /* USE_POLL */ 967 968 if (n == 0) { 969 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 970 *gotsomewhere = 1; 971 return (0); 972 } 973 if (n < 0) { 974 if (errno == EINTR) 975 goto wait; 976#ifdef USE_KQUEUE 977 Perror(statp, stderr, "kevent", errno); 978#else 979#ifndef USE_POLL 980 Perror(statp, stderr, "select", errno); 981#else 982 Perror(statp, stderr, "poll", errno); 983#endif /* USE_POLL */ 984#endif 985 res_nclose(statp); 986 return (0); 987 } 988#ifdef USE_KQUEUE 989 if (kv.ident != s) 990 goto wait; 991#endif 992 errno = 0; 993 fromlen = sizeof(from); 994 resplen = _recvfrom(s, (char*)ans, anssiz,0, 995 (struct sockaddr *)&from, &fromlen); 996 if (resplen <= 0) { 997 Perror(statp, stderr, "recvfrom", errno); 998 res_nclose(statp); 999 return (0); 1000 } 1001 *gotsomewhere = 1; 1002 if (resplen < HFIXEDSZ) { 1003 /* 1004 * Undersized message. 1005 */ 1006 Dprint(statp->options & RES_DEBUG, 1007 (stdout, ";; undersized: %d\n", 1008 resplen)); 1009 *terrno = EMSGSIZE; 1010 res_nclose(statp); 1011 return (0); 1012 } 1013 if (hp->id != anhp->id) { 1014 /* 1015 * response from old query, ignore it. 1016 * XXX - potential security hazard could 1017 * be detected here. 1018 */ 1019 DprintQ((statp->options & RES_DEBUG) || 1020 (statp->pfcode & RES_PRF_REPLY), 1021 (stdout, ";; old answer:\n"), 1022 ans, (resplen > anssiz) ? anssiz : resplen); 1023 goto wait; 1024 } 1025 if (!(statp->options & RES_INSECURE1) && 1026 !res_ourserver_p(statp, (struct sockaddr *)&from)) { 1027 /* 1028 * response from wrong server? ignore it. 1029 * XXX - potential security hazard could 1030 * be detected here. 1031 */ 1032 DprintQ((statp->options & RES_DEBUG) || 1033 (statp->pfcode & RES_PRF_REPLY), 1034 (stdout, ";; not our server:\n"), 1035 ans, (resplen > anssiz) ? anssiz : resplen); 1036 goto wait; 1037 } 1038#ifdef RES_USE_EDNS0 1039 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { 1040 /* 1041 * Do not retry if the server do not understand EDNS0. 1042 * The case has to be captured here, as FORMERR packet do not 1043 * carry query section, hence res_queriesmatch() returns 0. 1044 */ 1045 DprintQ(statp->options & RES_DEBUG, 1046 (stdout, "server rejected query with EDNS0:\n"), 1047 ans, (resplen > anssiz) ? anssiz : resplen); 1048 /* record the error */ 1049 statp->_flags |= RES_F_EDNS0ERR; 1050 res_nclose(statp); 1051 return (0); 1052 } 1053#endif 1054 if (!(statp->options & RES_INSECURE2) && 1055 !res_queriesmatch(buf, buf + buflen, 1056 ans, ans + anssiz)) { 1057 /* 1058 * response contains wrong query? ignore it. 1059 * XXX - potential security hazard could 1060 * be detected here. 1061 */ 1062 DprintQ((statp->options & RES_DEBUG) || 1063 (statp->pfcode & RES_PRF_REPLY), 1064 (stdout, ";; wrong query name:\n"), 1065 ans, (resplen > anssiz) ? anssiz : resplen); 1066 goto wait; 1067 } 1068 if (anhp->rcode == SERVFAIL || 1069 anhp->rcode == NOTIMP || 1070 anhp->rcode == REFUSED) { 1071 DprintQ(statp->options & RES_DEBUG, 1072 (stdout, "server rejected query:\n"), 1073 ans, (resplen > anssiz) ? anssiz : resplen); 1074 res_nclose(statp); 1075 /* don't retry if called from dig */ 1076 if (!statp->pfcode) 1077 return (0); 1078 } 1079 if (!(statp->options & RES_IGNTC) && anhp->tc) { 1080 /* 1081 * To get the rest of answer, 1082 * use TCP with same server. 1083 */ 1084 Dprint(statp->options & RES_DEBUG, 1085 (stdout, ";; truncated answer\n")); 1086 *v_circuit = 1; 1087 res_nclose(statp); 1088 return (1); 1089 } 1090 /* 1091 * All is well, or the error is fatal. Signal that the 1092 * next nameserver ought not be tried. 1093 */ 1094 return (resplen); 1095} 1096 1097static void 1098Aerror(const res_state statp, FILE *file, const char *string, int error, 1099 const struct sockaddr *address, int alen) 1100{ 1101 int save = errno; 1102 char hbuf[NI_MAXHOST]; 1103 char sbuf[NI_MAXSERV]; 1104 1105 if ((statp->options & RES_DEBUG) != 0U) { 1106 if (getnameinfo(address, alen, hbuf, sizeof(hbuf), 1107 sbuf, sizeof(sbuf), niflags)) { 1108 strncpy(hbuf, "?", sizeof(hbuf) - 1); 1109 hbuf[sizeof(hbuf) - 1] = '\0'; 1110 strncpy(sbuf, "?", sizeof(sbuf) - 1); 1111 sbuf[sizeof(sbuf) - 1] = '\0'; 1112 } 1113 fprintf(file, "res_send: %s ([%s].%s): %s\n", 1114 string, hbuf, sbuf, strerror(error)); 1115 } 1116 errno = save; 1117} 1118 1119static void 1120Perror(const res_state statp, FILE *file, const char *string, int error) { 1121 int save = errno; 1122 1123 if ((statp->options & RES_DEBUG) != 0U) 1124 fprintf(file, "res_send: %s: %s\n", 1125 string, strerror(error)); 1126 errno = save; 1127} 1128 1129static int 1130sock_eq(struct sockaddr *a, struct sockaddr *b) { 1131 struct sockaddr_in *a4, *b4; 1132 struct sockaddr_in6 *a6, *b6; 1133 1134 if (a->sa_family != b->sa_family) 1135 return 0; 1136 switch (a->sa_family) { 1137 case AF_INET: 1138 a4 = (struct sockaddr_in *)a; 1139 b4 = (struct sockaddr_in *)b; 1140 return a4->sin_port == b4->sin_port && 1141 a4->sin_addr.s_addr == b4->sin_addr.s_addr; 1142 case AF_INET6: 1143 a6 = (struct sockaddr_in6 *)a; 1144 b6 = (struct sockaddr_in6 *)b; 1145 return a6->sin6_port == b6->sin6_port && 1146#ifdef HAVE_SIN6_SCOPE_ID 1147 a6->sin6_scope_id == b6->sin6_scope_id && 1148#endif 1149 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 1150 default: 1151 return 0; 1152 } 1153} 1154 1155#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) 1156/* XXX needs to move to the porting library. */ 1157static int 1158pselect(int nfds, void *rfds, void *wfds, void *efds, 1159 struct timespec *tsp, const sigset_t *sigmask) 1160{ 1161 struct timeval tv, *tvp; 1162 sigset_t sigs; 1163 int n; 1164 1165 if (tsp) { 1166 tvp = &tv; 1167 tv = evTimeVal(*tsp); 1168 } else 1169 tvp = NULL; 1170 if (sigmask) 1171 sigprocmask(SIG_SETMASK, sigmask, &sigs); 1172 n = select(nfds, rfds, wfds, efds, tvp); 1173 if (sigmask) 1174 sigprocmask(SIG_SETMASK, &sigs, NULL); 1175 if (tsp) 1176 *tsp = evTimeSpec(tv); 1177 return (n); 1178} 1179#endif 1180