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