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