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 "private/libc_logging.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 return (resplen); 527 case res_modified: 528 /* give the hook another try */ 529 if (++loops < 42) /*doug adams*/ 530 break; 531 /*FALLTHROUGH*/ 532 case res_error: 533 /*FALLTHROUGH*/ 534 default: 535 goto fail; 536 } 537 } while (!done); 538 } 539 540 Dprint(((statp->options & RES_DEBUG) && 541 getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), 542 NULL, 0, niflags) == 0), 543 (stdout, ";; Querying server (# %d) address = %s\n", 544 ns + 1, abuf)); 545 546 547 if (v_circuit) { 548 /* Use VC; at most one attempt per server. */ 549 try = statp->retry; 550 551 n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 552 ns, &now, &rcode, &delay); 553 554 /* 555 * Only record stats the first time we try a query. This ensures that 556 * queries that deterministically fail (e.g., a name that always returns 557 * SERVFAIL or times out) do not unduly affect the stats. 558 */ 559 if (try == 0) { 560 struct __res_sample sample; 561 _res_stats_set_sample(&sample, now, rcode, delay); 562 _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, 563 ns, &sample, params.max_samples); 564 } 565 566 if (DBG) { 567 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 568 "used send_vc %d\n", n); 569 } 570 571 if (n < 0) 572 goto fail; 573 if (n == 0) 574 goto next_ns; 575 resplen = n; 576 } else { 577 /* Use datagrams. */ 578 if (DBG) { 579 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n"); 580 } 581 582 n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, 583 ns, &v_circuit, &gotsomewhere, &now, &rcode, &delay); 584 585 /* Only record stats the first time we try a query. See above. */ 586 if (try == 0) { 587 struct __res_sample sample; 588 _res_stats_set_sample(&sample, now, rcode, delay); 589 _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, 590 ns, &sample, params.max_samples); 591 } 592 593 if (DBG) { 594 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n); 595 } 596 597 if (n < 0) 598 goto fail; 599 if (n == 0) 600 goto next_ns; 601 if (DBG) { 602 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n", 603 time(NULL)); 604 } 605 if (v_circuit) 606 goto same_ns; 607 resplen = n; 608 } 609 610 Dprint((statp->options & RES_DEBUG) || 611 ((statp->pfcode & RES_PRF_REPLY) && 612 (statp->pfcode & RES_PRF_HEAD1)), 613 (stdout, ";; got answer:\n")); 614 615 DprintQ((statp->options & RES_DEBUG) || 616 (statp->pfcode & RES_PRF_REPLY), 617 (stdout, "%s", ""), 618 ans, (resplen > anssiz) ? anssiz : resplen); 619 620 if (cache_status == RESOLV_CACHE_NOTFOUND) { 621 _resolv_cache_add(statp->netid, buf, buflen, 622 ans, resplen); 623 } 624 /* 625 * If we have temporarily opened a virtual circuit, 626 * or if we haven't been asked to keep a socket open, 627 * close the socket. 628 */ 629 if ((v_circuit && (statp->options & RES_USEVC) == 0U) || 630 (statp->options & RES_STAYOPEN) == 0U) { 631 res_nclose(statp); 632 } 633 if (statp->rhook) { 634 int done = 0, loops = 0; 635 636 do { 637 res_sendhookact act; 638 639 act = (*statp->rhook)(nsap, buf, buflen, 640 ans, anssiz, &resplen); 641 switch (act) { 642 case res_goahead: 643 case res_done: 644 done = 1; 645 break; 646 case res_nextns: 647 res_nclose(statp); 648 goto next_ns; 649 case res_modified: 650 /* give the hook another try */ 651 if (++loops < 42) /*doug adams*/ 652 break; 653 /*FALLTHROUGH*/ 654 case res_error: 655 /*FALLTHROUGH*/ 656 default: 657 goto fail; 658 } 659 } while (!done); 660 661 } 662 return (resplen); 663 next_ns: ; 664 } /*foreach ns*/ 665 } /*foreach retry*/ 666 res_nclose(statp); 667 if (!v_circuit) { 668 if (!gotsomewhere) 669 errno = ECONNREFUSED; /* no nameservers found */ 670 else 671 errno = ETIMEDOUT; /* no answer obtained */ 672 } else 673 errno = terrno; 674 675 _resolv_cache_query_failed(statp->netid, buf, buflen); 676 677 return (-1); 678 fail: 679 680 _resolv_cache_query_failed(statp->netid, buf, buflen); 681 res_nclose(statp); 682 return (-1); 683} 684 685/* Private */ 686 687static int 688get_salen(sa) 689 const struct sockaddr *sa; 690{ 691 692#ifdef HAVE_SA_LEN 693 /* There are people do not set sa_len. Be forgiving to them. */ 694 if (sa->sa_len) 695 return (sa->sa_len); 696#endif 697 698 if (sa->sa_family == AF_INET) 699 return (sizeof(struct sockaddr_in)); 700 else if (sa->sa_family == AF_INET6) 701 return (sizeof(struct sockaddr_in6)); 702 else 703 return (0); /* unknown, die on connect */ 704} 705 706/* 707 * pick appropriate nsaddr_list for use. see res_init() for initialization. 708 */ 709static struct sockaddr * 710get_nsaddr(statp, n) 711 res_state statp; 712 size_t n; 713{ 714 715 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 716 /* 717 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 718 * than struct sockaddr, and 719 * - user code did not update statp->nsaddr_list[n]. 720 */ 721 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 722 } else { 723 /* 724 * - user code updated statp->nsaddr_list[n], or 725 * - statp->nsaddr_list[n] has the same content as 726 * EXT(statp).ext->nsaddrs[n]. 727 */ 728 return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 729 } 730} 731 732static int get_timeout(const res_state statp, const int ns) 733{ 734 int timeout = (statp->retrans << ns); 735 if (ns > 0) { 736 timeout /= statp->nscount; 737 } 738 if (timeout <= 0) { 739 timeout = 1; 740 } 741 if (DBG) { 742 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d sec\n", timeout); 743 } 744 745 return timeout; 746} 747 748static int 749send_vc(res_state statp, 750 const u_char *buf, int buflen, u_char *ans, int anssiz, 751 int *terrno, int ns, time_t* at, int* rcode, int* delay) 752{ 753 *at = time(NULL); 754 *rcode = RCODE_INTERNAL_ERROR; 755 *delay = 0; 756 const HEADER *hp = (const HEADER *)(const void *)buf; 757 HEADER *anhp = (HEADER *)(void *)ans; 758 struct sockaddr *nsap; 759 int nsaplen; 760 int truncating, connreset, resplen, n; 761 struct iovec iov[2]; 762 u_short len; 763 u_char *cp; 764 void *tmp; 765 766 if (DBG) { 767 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n"); 768 } 769 770 nsap = get_nsaddr(statp, (size_t)ns); 771 nsaplen = get_salen(nsap); 772 773 connreset = 0; 774 same_ns: 775 truncating = 0; 776 777 struct timespec now = evNowTime(); 778 779 /* Are we still talking to whom we want to talk to? */ 780 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 781 struct sockaddr_storage peer; 782 socklen_t size = sizeof peer; 783 unsigned old_mark; 784 socklen_t mark_size = sizeof(old_mark); 785 if (getpeername(statp->_vcsock, 786 (struct sockaddr *)(void *)&peer, &size) < 0 || 787 !sock_eq((struct sockaddr *)(void *)&peer, nsap) || 788 getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 || 789 old_mark != statp->_mark) { 790 res_nclose(statp); 791 statp->_flags &= ~RES_F_VC; 792 } 793 } 794 795 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 796 if (statp->_vcsock >= 0) 797 res_nclose(statp); 798 799 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0); 800 if (statp->_vcsock > highestFD) { 801 res_nclose(statp); 802 errno = ENOTSOCK; 803 } 804 if (statp->_vcsock < 0) { 805 switch (errno) { 806 case EPROTONOSUPPORT: 807#ifdef EPFNOSUPPORT 808 case EPFNOSUPPORT: 809#endif 810 case EAFNOSUPPORT: 811 Perror(statp, stderr, "socket(vc)", errno); 812 return (0); 813 default: 814 *terrno = errno; 815 Perror(statp, stderr, "socket(vc)", errno); 816 return (-1); 817 } 818 } 819 if (statp->_mark != MARK_UNSET) { 820 if (setsockopt(statp->_vcsock, SOL_SOCKET, 821 SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) { 822 *terrno = errno; 823 Perror(statp, stderr, "setsockopt", errno); 824 return -1; 825 } 826 } 827 errno = 0; 828 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) { 829 *terrno = errno; 830 Aerror(statp, stderr, "bind/vc", errno, nsap, 831 nsaplen); 832 res_nclose(statp); 833 return (0); 834 } 835 if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen, 836 get_timeout(statp, ns)) < 0) { 837 *terrno = errno; 838 Aerror(statp, stderr, "connect/vc", errno, nsap, 839 nsaplen); 840 res_nclose(statp); 841 /* 842 * The way connect_with_timeout() is implemented prevents us from reliably 843 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since 844 * currently both cases are handled in the same way, there is no need to 845 * change this (yet). If we ever need to reliably distinguish between these 846 * cases, both connect_with_timeout() and retrying_select() need to be 847 * modified, though. 848 */ 849 *rcode = RCODE_TIMEOUT; 850 return (0); 851 } 852 statp->_flags |= RES_F_VC; 853 } 854 855 /* 856 * Send length & message 857 */ 858 ns_put16((u_short)buflen, (u_char*)(void *)&len); 859 iov[0] = evConsIovec(&len, INT16SZ); 860 DE_CONST(buf, tmp); 861 iov[1] = evConsIovec(tmp, (size_t)buflen); 862 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 863 *terrno = errno; 864 Perror(statp, stderr, "write failed", errno); 865 res_nclose(statp); 866 return (0); 867 } 868 /* 869 * Receive length & response 870 */ 871 read_len: 872 cp = ans; 873 len = INT16SZ; 874 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) { 875 cp += n; 876 if ((len -= n) == 0) 877 break; 878 } 879 if (n <= 0) { 880 *terrno = errno; 881 Perror(statp, stderr, "read failed", errno); 882 res_nclose(statp); 883 /* 884 * A long running process might get its TCP 885 * connection reset if the remote server was 886 * restarted. Requery the server instead of 887 * trying a new one. When there is only one 888 * server, this means that a query might work 889 * instead of failing. We only allow one reset 890 * per query to prevent looping. 891 */ 892 if (*terrno == ECONNRESET && !connreset) { 893 connreset = 1; 894 res_nclose(statp); 895 goto same_ns; 896 } 897 res_nclose(statp); 898 return (0); 899 } 900 resplen = ns_get16(ans); 901 if (resplen > anssiz) { 902 Dprint(statp->options & RES_DEBUG, 903 (stdout, ";; response truncated\n") 904 ); 905 truncating = 1; 906 len = anssiz; 907 } else 908 len = resplen; 909 if (len < HFIXEDSZ) { 910 /* 911 * Undersized message. 912 */ 913 Dprint(statp->options & RES_DEBUG, 914 (stdout, ";; undersized: %d\n", len)); 915 *terrno = EMSGSIZE; 916 res_nclose(statp); 917 return (0); 918 } 919 cp = ans; 920 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){ 921 cp += n; 922 len -= n; 923 } 924 if (n <= 0) { 925 *terrno = errno; 926 Perror(statp, stderr, "read(vc)", errno); 927 res_nclose(statp); 928 return (0); 929 } 930 931 if (truncating) { 932 /* 933 * Flush rest of answer so connection stays in synch. 934 */ 935 anhp->tc = 1; 936 len = resplen - anssiz; 937 while (len != 0) { 938 char junk[PACKETSZ]; 939 940 n = read(statp->_vcsock, junk, 941 (len > sizeof junk) ? sizeof junk : len); 942 if (n > 0) 943 len -= n; 944 else 945 break; 946 } 947 } 948 /* 949 * If the calling applicating has bailed out of 950 * a previous call and failed to arrange to have 951 * the circuit closed or the server has got 952 * itself confused, then drop the packet and 953 * wait for the correct one. 954 */ 955 if (hp->id != anhp->id) { 956 DprintQ((statp->options & RES_DEBUG) || 957 (statp->pfcode & RES_PRF_REPLY), 958 (stdout, ";; old answer (unexpected):\n"), 959 ans, (resplen > anssiz) ? anssiz: resplen); 960 goto read_len; 961 } 962 963 /* 964 * All is well, or the error is fatal. Signal that the 965 * next nameserver ought not be tried. 966 */ 967 if (resplen > 0) { 968 struct timespec done = evNowTime(); 969 *delay = _res_stats_calculate_rtt(&done, &now); 970 *rcode = anhp->rcode; 971 } 972 return (resplen); 973} 974 975/* return -1 on error (errno set), 0 on success */ 976static int 977connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int sec) 978{ 979 int res, origflags; 980 fd_set rset, wset; 981 struct timespec now, timeout, finish; 982 983 origflags = fcntl(sock, F_GETFL, 0); 984 fcntl(sock, F_SETFL, origflags | O_NONBLOCK); 985 986 res = __connect(sock, nsap, salen); 987 if (res < 0 && errno != EINPROGRESS) { 988 res = -1; 989 goto done; 990 } 991 if (res != 0) { 992 now = evNowTime(); 993 timeout = evConsTime((long)sec, 0L); 994 finish = evAddTime(now, timeout); 995 if (DBG) { 996 __libc_format_log(ANDROID_LOG_DEBUG, "libc", " %d send_vc\n", sock); 997 } 998 999 res = retrying_select(sock, &rset, &wset, &finish); 1000 if (res <= 0) { 1001 res = -1; 1002 } 1003 } 1004done: 1005 fcntl(sock, F_SETFL, origflags); 1006 if (DBG) { 1007 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 1008 " %d connect_with_timeout returning %d\n", sock, res); 1009 } 1010 return res; 1011} 1012 1013static int 1014retrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct timespec *finish) 1015{ 1016 struct timespec now, timeout; 1017 int n, error; 1018 socklen_t len; 1019 1020 1021retry: 1022 if (DBG) { 1023 __libc_format_log(ANDROID_LOG_DEBUG, "libc", " %d retrying_select\n", sock); 1024 } 1025 1026 now = evNowTime(); 1027 if (readset) { 1028 FD_ZERO(readset); 1029 FD_SET(sock, readset); 1030 } 1031 if (writeset) { 1032 FD_ZERO(writeset); 1033 FD_SET(sock, writeset); 1034 } 1035 if (evCmpTime(*finish, now) > 0) 1036 timeout = evSubTime(*finish, now); 1037 else 1038 timeout = evConsTime(0L, 0L); 1039 1040 n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL); 1041 if (n == 0) { 1042 if (DBG) { 1043 __libc_format_log(ANDROID_LOG_DEBUG, " libc", 1044 " %d retrying_select timeout\n", sock); 1045 } 1046 errno = ETIMEDOUT; 1047 return 0; 1048 } 1049 if (n < 0) { 1050 if (errno == EINTR) 1051 goto retry; 1052 if (DBG) { 1053 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 1054 " %d retrying_select got error %d\n",sock, n); 1055 } 1056 return n; 1057 } 1058 if ((readset && FD_ISSET(sock, readset)) || (writeset && FD_ISSET(sock, writeset))) { 1059 len = sizeof(error); 1060 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) { 1061 errno = error; 1062 if (DBG) { 1063 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 1064 " %d retrying_select dot error2 %d\n", sock, errno); 1065 } 1066 1067 return -1; 1068 } 1069 } 1070 if (DBG) { 1071 __libc_format_log(ANDROID_LOG_DEBUG, "libc", 1072 " %d retrying_select returning %d\n",sock, n); 1073 } 1074 1075 return n; 1076} 1077 1078static int 1079send_dg(res_state statp, 1080 const u_char *buf, int buflen, u_char *ans, int anssiz, 1081 int *terrno, int ns, int *v_circuit, int *gotsomewhere, 1082 time_t *at, int *rcode, int* delay) 1083{ 1084 *at = time(NULL); 1085 *rcode = RCODE_INTERNAL_ERROR; 1086 *delay = 0; 1087 const HEADER *hp = (const HEADER *)(const void *)buf; 1088 HEADER *anhp = (HEADER *)(void *)ans; 1089 const struct sockaddr *nsap; 1090 int nsaplen; 1091 struct timespec now, timeout, finish, done; 1092 fd_set dsmask; 1093 struct sockaddr_storage from; 1094 socklen_t fromlen; 1095 int resplen, seconds, n, s; 1096 1097 nsap = get_nsaddr(statp, (size_t)ns); 1098 nsaplen = get_salen(nsap); 1099 if (EXT(statp).nssocks[ns] == -1) { 1100 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0); 1101 if (EXT(statp).nssocks[ns] > highestFD) { 1102 res_nclose(statp); 1103 errno = ENOTSOCK; 1104 } 1105 if (EXT(statp).nssocks[ns] < 0) { 1106 switch (errno) { 1107 case EPROTONOSUPPORT: 1108#ifdef EPFNOSUPPORT 1109 case EPFNOSUPPORT: 1110#endif 1111 case EAFNOSUPPORT: 1112 Perror(statp, stderr, "socket(dg)", errno); 1113 return (0); 1114 default: 1115 *terrno = errno; 1116 Perror(statp, stderr, "socket(dg)", errno); 1117 return (-1); 1118 } 1119 } 1120 1121 if (statp->_mark != MARK_UNSET) { 1122 if (setsockopt(EXT(statp).nssocks[ns], SOL_SOCKET, 1123 SO_MARK, &(statp->_mark), sizeof(statp->_mark)) < 0) { 1124 res_nclose(statp); 1125 return -1; 1126 } 1127 } 1128#ifndef CANNOT_CONNECT_DGRAM 1129 /* 1130 * On a 4.3BSD+ machine (client and server, 1131 * actually), sending to a nameserver datagram 1132 * port with no nameserver will cause an 1133 * ICMP port unreachable message to be returned. 1134 * If our datagram socket is "connected" to the 1135 * server, we get an ECONNREFUSED error on the next 1136 * socket operation, and select returns if the 1137 * error message is received. We can thus detect 1138 * the absence of a nameserver without timing out. 1139 */ 1140 if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) { 1141 Aerror(statp, stderr, "bind(dg)", errno, nsap, 1142 nsaplen); 1143 res_nclose(statp); 1144 return (0); 1145 } 1146 if (__connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) { 1147 Aerror(statp, stderr, "connect(dg)", errno, nsap, 1148 nsaplen); 1149 res_nclose(statp); 1150 return (0); 1151 } 1152#endif /* !CANNOT_CONNECT_DGRAM */ 1153 Dprint(statp->options & RES_DEBUG, 1154 (stdout, ";; new DG socket\n")) 1155 1156 } 1157 s = EXT(statp).nssocks[ns]; 1158#ifndef CANNOT_CONNECT_DGRAM 1159 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) { 1160 Perror(statp, stderr, "send", errno); 1161 res_nclose(statp); 1162 return (0); 1163 } 1164#else /* !CANNOT_CONNECT_DGRAM */ 1165 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 1166 { 1167 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 1168 res_nclose(statp); 1169 return (0); 1170 } 1171#endif /* !CANNOT_CONNECT_DGRAM */ 1172 1173 /* 1174 * Wait for reply. 1175 */ 1176 seconds = get_timeout(statp, ns); 1177 now = evNowTime(); 1178 timeout = evConsTime((long)seconds, 0L); 1179 finish = evAddTime(now, timeout); 1180retry: 1181 n = retrying_select(s, &dsmask, NULL, &finish); 1182 1183 if (n == 0) { 1184 *rcode = RCODE_TIMEOUT; 1185 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 1186 *gotsomewhere = 1; 1187 return (0); 1188 } 1189 if (n < 0) { 1190 Perror(statp, stderr, "select", errno); 1191 res_nclose(statp); 1192 return (0); 1193 } 1194 errno = 0; 1195 fromlen = sizeof(from); 1196 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0, 1197 (struct sockaddr *)(void *)&from, &fromlen); 1198 if (resplen <= 0) { 1199 Perror(statp, stderr, "recvfrom", errno); 1200 res_nclose(statp); 1201 return (0); 1202 } 1203 *gotsomewhere = 1; 1204 if (resplen < HFIXEDSZ) { 1205 /* 1206 * Undersized message. 1207 */ 1208 Dprint(statp->options & RES_DEBUG, 1209 (stdout, ";; undersized: %d\n", 1210 resplen)); 1211 *terrno = EMSGSIZE; 1212 res_nclose(statp); 1213 return (0); 1214 } 1215 if (hp->id != anhp->id) { 1216 /* 1217 * response from old query, ignore it. 1218 * XXX - potential security hazard could 1219 * be detected here. 1220 */ 1221 DprintQ((statp->options & RES_DEBUG) || 1222 (statp->pfcode & RES_PRF_REPLY), 1223 (stdout, ";; old answer:\n"), 1224 ans, (resplen > anssiz) ? anssiz : resplen); 1225 goto retry; 1226 } 1227 if (!(statp->options & RES_INSECURE1) && 1228 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) { 1229 /* 1230 * response from wrong server? ignore it. 1231 * XXX - potential security hazard could 1232 * be detected here. 1233 */ 1234 DprintQ((statp->options & RES_DEBUG) || 1235 (statp->pfcode & RES_PRF_REPLY), 1236 (stdout, ";; not our server:\n"), 1237 ans, (resplen > anssiz) ? anssiz : resplen); 1238 goto retry; 1239 } 1240#ifdef RES_USE_EDNS0 1241 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { 1242 /* 1243 * Do not retry if the server do not understand EDNS0. 1244 * The case has to be captured here, as FORMERR packet do not 1245 * carry query section, hence res_queriesmatch() returns 0. 1246 */ 1247 DprintQ(statp->options & RES_DEBUG, 1248 (stdout, "server rejected query with EDNS0:\n"), 1249 ans, (resplen > anssiz) ? anssiz : resplen); 1250 /* record the error */ 1251 statp->_flags |= RES_F_EDNS0ERR; 1252 res_nclose(statp); 1253 return (0); 1254 } 1255#endif 1256 if (!(statp->options & RES_INSECURE2) && 1257 !res_queriesmatch(buf, buf + buflen, 1258 ans, ans + anssiz)) { 1259 /* 1260 * response contains wrong query? ignore it. 1261 * XXX - potential security hazard could 1262 * be detected here. 1263 */ 1264 DprintQ((statp->options & RES_DEBUG) || 1265 (statp->pfcode & RES_PRF_REPLY), 1266 (stdout, ";; wrong query name:\n"), 1267 ans, (resplen > anssiz) ? anssiz : resplen); 1268 goto retry;; 1269 } 1270 done = evNowTime(); 1271 *delay = _res_stats_calculate_rtt(&done, &now); 1272 if (anhp->rcode == SERVFAIL || 1273 anhp->rcode == NOTIMP || 1274 anhp->rcode == REFUSED) { 1275 DprintQ(statp->options & RES_DEBUG, 1276 (stdout, "server rejected query:\n"), 1277 ans, (resplen > anssiz) ? anssiz : resplen); 1278 res_nclose(statp); 1279 /* don't retry if called from dig */ 1280 if (!statp->pfcode) { 1281 *rcode = anhp->rcode; 1282 return (0); 1283 } 1284 } 1285 if (!(statp->options & RES_IGNTC) && anhp->tc) { 1286 /* 1287 * To get the rest of answer, 1288 * use TCP with same server. 1289 */ 1290 Dprint(statp->options & RES_DEBUG, 1291 (stdout, ";; truncated answer\n")); 1292 *v_circuit = 1; 1293 res_nclose(statp); 1294 return (1); 1295 } 1296 /* 1297 * All is well, or the error is fatal. Signal that the 1298 * next nameserver ought not be tried. 1299 */ 1300 if (resplen > 0) { 1301 *rcode = anhp->rcode; 1302 } 1303 return (resplen); 1304} 1305 1306static void 1307Aerror(const res_state statp, FILE *file, const char *string, int error, 1308 const struct sockaddr *address, int alen) 1309{ 1310 int save = errno; 1311 char hbuf[NI_MAXHOST]; 1312 char sbuf[NI_MAXSERV]; 1313 1314 if ((statp->options & RES_DEBUG) != 0U) { 1315 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf), 1316 sbuf, sizeof(sbuf), niflags)) { 1317 strncpy(hbuf, "?", sizeof(hbuf) - 1); 1318 hbuf[sizeof(hbuf) - 1] = '\0'; 1319 strncpy(sbuf, "?", sizeof(sbuf) - 1); 1320 sbuf[sizeof(sbuf) - 1] = '\0'; 1321 } 1322 fprintf(file, "res_send: %s ([%s].%s): %s\n", 1323 string, hbuf, sbuf, strerror(error)); 1324 } 1325 errno = save; 1326} 1327 1328static void 1329Perror(const res_state statp, FILE *file, const char *string, int error) { 1330 int save = errno; 1331 1332 if ((statp->options & RES_DEBUG) != 0U) 1333 fprintf(file, "res_send: %s: %s\n", 1334 string, strerror(error)); 1335 errno = save; 1336} 1337 1338static int 1339sock_eq(struct sockaddr *a, struct sockaddr *b) { 1340 struct sockaddr_in *a4, *b4; 1341 struct sockaddr_in6 *a6, *b6; 1342 1343 if (a->sa_family != b->sa_family) 1344 return 0; 1345 switch (a->sa_family) { 1346 case AF_INET: 1347 a4 = (struct sockaddr_in *)(void *)a; 1348 b4 = (struct sockaddr_in *)(void *)b; 1349 return a4->sin_port == b4->sin_port && 1350 a4->sin_addr.s_addr == b4->sin_addr.s_addr; 1351 case AF_INET6: 1352 a6 = (struct sockaddr_in6 *)(void *)a; 1353 b6 = (struct sockaddr_in6 *)(void *)b; 1354 return a6->sin6_port == b6->sin6_port && 1355#ifdef HAVE_SIN6_SCOPE_ID 1356 a6->sin6_scope_id == b6->sin6_scope_id && 1357#endif 1358 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 1359 default: 1360 return 0; 1361 } 1362} 1363 1364#ifdef NEED_PSELECT 1365/* XXX needs to move to the porting library. */ 1366static int 1367pselect(int nfds, void *rfds, void *wfds, void *efds, 1368 struct timespec *tsp, const sigset_t *sigmask) 1369{ 1370 struct timeval tv, *tvp; 1371 sigset_t sigs; 1372 int n; 1373 1374 if (tsp) { 1375 tvp = &tv; 1376 tv = evTimeVal(*tsp); 1377 } else 1378 tvp = NULL; 1379 if (sigmask) 1380 sigprocmask(SIG_SETMASK, sigmask, &sigs); 1381 n = select(nfds, rfds, wfds, efds, tvp); 1382 if (sigmask) 1383 sigprocmask(SIG_SETMASK, &sigs, NULL); 1384 if (tsp) 1385 *tsp = evTimeSpec(tv); 1386 return (n); 1387} 1388#endif 1389