1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/android/res_send.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1181 @@ 1.4 +/* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */ 1.5 + 1.6 +/* 1.7 + * Copyright 2008 Android Open Source Project (source port randomization) 1.8 + * Copyright (c) 1985, 1989, 1993 1.9 + * The Regents of the University of California. All rights reserved. 1.10 + * 1.11 + * Redistribution and use in source and binary forms, with or without 1.12 + * modification, are permitted provided that the following conditions 1.13 + * are met: 1.14 + * 1. Redistributions of source code must retain the above copyright 1.15 + * notice, this list of conditions and the following disclaimer. 1.16 + * 2. Redistributions in binary form must reproduce the above copyright 1.17 + * notice, this list of conditions and the following disclaimer in the 1.18 + * documentation and/or other materials provided with the distribution. 1.19 + * 3. All advertising materials mentioning features or use of this software 1.20 + * must display the following acknowledgement: 1.21 + * This product includes software developed by the University of 1.22 + * California, Berkeley and its contributors. 1.23 + * 4. Neither the name of the University nor the names of its contributors 1.24 + * may be used to endorse or promote products derived from this software 1.25 + * without specific prior written permission. 1.26 + * 1.27 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1.28 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.29 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.30 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1.31 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1.32 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1.33 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.34 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1.35 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1.36 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1.37 + * SUCH DAMAGE. 1.38 + */ 1.39 + 1.40 +/* 1.41 + * Portions Copyright (c) 1993 by Digital Equipment Corporation. 1.42 + * 1.43 + * Permission to use, copy, modify, and distribute this software for any 1.44 + * purpose with or without fee is hereby granted, provided that the above 1.45 + * copyright notice and this permission notice appear in all copies, and that 1.46 + * the name of Digital Equipment Corporation not be used in advertising or 1.47 + * publicity pertaining to distribution of the document or software without 1.48 + * specific, written prior permission. 1.49 + * 1.50 + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 1.51 + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 1.52 + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 1.53 + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 1.54 + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 1.55 + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 1.56 + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1.57 + * SOFTWARE. 1.58 + */ 1.59 + 1.60 +/* 1.61 + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 1.62 + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 1.63 + * 1.64 + * Permission to use, copy, modify, and distribute this software for any 1.65 + * purpose with or without fee is hereby granted, provided that the above 1.66 + * copyright notice and this permission notice appear in all copies. 1.67 + * 1.68 + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 1.69 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1.70 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 1.71 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.72 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1.73 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 1.74 + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1.75 + */ 1.76 + 1.77 +/* 1.78 + * This version of this file is derived from Android 2.3 "Gingerbread", 1.79 + * which contains uncredited changes by Android/Google developers. It has 1.80 + * been modified in 2011 for use in the Android build of Mozilla Firefox by 1.81 + * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>, 1.82 + * and Steve Workman <sjhworkman@gmail.com>). 1.83 + * These changes are offered under the same license as the original NetBSD 1.84 + * file, whose copyright and license are unchanged above. 1.85 + */ 1.86 + 1.87 +#define ANDROID_CHANGES 1 1.88 +#define MOZILLA_NECKO_EXCLUDE_CODE 1 1.89 + 1.90 +#include <sys/cdefs.h> 1.91 +#if defined(LIBC_SCCS) && !defined(lint) 1.92 +#ifdef notdef 1.93 +static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 1.94 +static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp"; 1.95 +#else 1.96 +__RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $"); 1.97 +#endif 1.98 +#endif /* LIBC_SCCS and not lint */ 1.99 + 1.100 +/* Set to 0 to not use the small/simple/limited DNS cache 1.101 + * Cache implemented higher up in Gecko */ 1.102 +#define USE_RESOLV_CACHE 0 1.103 + 1.104 +/* 1.105 + * Send query to name server and wait for reply. 1.106 + */ 1.107 + 1.108 +#include <sys/types.h> 1.109 +#include <sys/param.h> 1.110 +#include <sys/time.h> 1.111 +#include <sys/socket.h> 1.112 +#include <sys/uio.h> 1.113 + 1.114 +#include <netinet/in.h> 1.115 +#include "arpa_nameser.h" 1.116 +#include <arpa/inet.h> 1.117 + 1.118 +#include <errno.h> 1.119 +#include <netdb.h> 1.120 +#ifdef ANDROID_CHANGES 1.121 +#include "resolv_private.h" 1.122 +#else 1.123 +#include <resolv.h> 1.124 +#endif 1.125 +#include <signal.h> 1.126 +#include <stdio.h> 1.127 +#include <stdlib.h> 1.128 +#include <string.h> 1.129 +#include <unistd.h> 1.130 + 1.131 +#include "eventlib.h" 1.132 + 1.133 +#if USE_RESOLV_CACHE 1.134 +# include <resolv_cache.h> 1.135 +#endif 1.136 + 1.137 +#ifndef DE_CONST 1.138 +#define DE_CONST(c,v) v = ((c) ? \ 1.139 + strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL) 1.140 +#endif 1.141 + 1.142 +/* Options. Leave them on. */ 1.143 +#ifndef DEBUG 1.144 +#define DEBUG 1.145 +#endif 1.146 +#include "res_debug.h" 1.147 +#include "res_private.h" 1.148 + 1.149 +#define EXT(res) ((res)->_u._ext) 1.150 + 1.151 +static const int highestFD = FD_SETSIZE - 1; 1.152 + 1.153 +/* Forward. */ 1.154 + 1.155 +static int get_salen __P((const struct sockaddr *)); 1.156 +static struct sockaddr * get_nsaddr __P((res_state, size_t)); 1.157 +static int send_vc(res_state, const u_char *, int, 1.158 + u_char *, int, int *, int); 1.159 +static int send_dg(res_state, const u_char *, int, 1.160 + u_char *, int, int *, int, 1.161 + int *, int *); 1.162 +static void Aerror(const res_state, FILE *, const char *, int, 1.163 + const struct sockaddr *, int); 1.164 +static void Perror(const res_state, FILE *, const char *, int); 1.165 +static int sock_eq(struct sockaddr *, struct sockaddr *); 1.166 +#ifdef NEED_PSELECT 1.167 +static int pselect(int, void *, void *, void *, 1.168 + struct timespec *, 1.169 + const sigset_t *); 1.170 +#endif 1.171 +void res_pquery(const res_state, const u_char *, int, FILE *); 1.172 + 1.173 + 1.174 +/* BIONIC-BEGIN: implement source port randomization */ 1.175 +typedef union { 1.176 + struct sockaddr sa; 1.177 + struct sockaddr_in sin; 1.178 + struct sockaddr_in6 sin6; 1.179 +} _sockaddr_union; 1.180 + 1.181 +static int 1.182 +random_bind( int s, int family ) 1.183 +{ 1.184 + _sockaddr_union u; 1.185 + int j; 1.186 + socklen_t slen; 1.187 + 1.188 + /* clear all, this also sets the IP4/6 address to 'any' */ 1.189 + memset( &u, 0, sizeof u ); 1.190 + 1.191 + switch (family) { 1.192 + case AF_INET: 1.193 + u.sin.sin_family = family; 1.194 + slen = sizeof u.sin; 1.195 + break; 1.196 + case AF_INET6: 1.197 + u.sin6.sin6_family = family; 1.198 + slen = sizeof u.sin6; 1.199 + break; 1.200 + default: 1.201 + errno = EPROTO; 1.202 + return -1; 1.203 + } 1.204 + 1.205 + /* first try to bind to a random source port a few times */ 1.206 + for (j = 0; j < 10; j++) { 1.207 + /* find a random port between 1025 .. 65534 */ 1.208 + int port = 1025 + (res_randomid() % (65535-1025)); 1.209 + if (family == AF_INET) 1.210 + u.sin.sin_port = htons(port); 1.211 + else 1.212 + u.sin6.sin6_port = htons(port); 1.213 + 1.214 + if ( !bind( s, &u.sa, slen ) ) 1.215 + return 0; 1.216 + } 1.217 + 1.218 + /* nothing after 10 tries, our network table is probably busy */ 1.219 + /* let the system decide which port is best */ 1.220 + if (family == AF_INET) 1.221 + u.sin.sin_port = 0; 1.222 + else 1.223 + u.sin6.sin6_port = 0; 1.224 + 1.225 + return bind( s, &u.sa, slen ); 1.226 +} 1.227 +/* BIONIC-END */ 1.228 + 1.229 +static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 1.230 + 1.231 +/* Public. */ 1.232 + 1.233 +/* int 1.234 + * res_isourserver(ina) 1.235 + * looks up "ina" in _res.ns_addr_list[] 1.236 + * returns: 1.237 + * 0 : not found 1.238 + * >0 : found 1.239 + * author: 1.240 + * paul vixie, 29may94 1.241 + */ 1.242 +int 1.243 +res_ourserver_p(const res_state statp, const struct sockaddr *sa) { 1.244 + const struct sockaddr_in *inp, *srv; 1.245 + const struct sockaddr_in6 *in6p, *srv6; 1.246 + int ns; 1.247 + 1.248 + switch (sa->sa_family) { 1.249 + case AF_INET: 1.250 + inp = (const struct sockaddr_in *)(const void *)sa; 1.251 + for (ns = 0; ns < statp->nscount; ns++) { 1.252 + srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns); 1.253 + if (srv->sin_family == inp->sin_family && 1.254 + srv->sin_port == inp->sin_port && 1.255 + (srv->sin_addr.s_addr == INADDR_ANY || 1.256 + srv->sin_addr.s_addr == inp->sin_addr.s_addr)) 1.257 + return (1); 1.258 + } 1.259 + break; 1.260 + case AF_INET6: 1.261 + if (EXT(statp).ext == NULL) 1.262 + break; 1.263 + in6p = (const struct sockaddr_in6 *)(const void *)sa; 1.264 + for (ns = 0; ns < statp->nscount; ns++) { 1.265 + srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns); 1.266 + if (srv6->sin6_family == in6p->sin6_family && 1.267 + srv6->sin6_port == in6p->sin6_port && 1.268 +#ifdef HAVE_SIN6_SCOPE_ID 1.269 + (srv6->sin6_scope_id == 0 || 1.270 + srv6->sin6_scope_id == in6p->sin6_scope_id) && 1.271 +#endif 1.272 + (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || 1.273 + IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) 1.274 + return (1); 1.275 + } 1.276 + break; 1.277 + default: 1.278 + break; 1.279 + } 1.280 + return (0); 1.281 +} 1.282 + 1.283 +/* int 1.284 + * res_nameinquery(name, type, class, buf, eom) 1.285 + * look for (name,type,class) in the query section of packet (buf,eom) 1.286 + * requires: 1.287 + * buf + HFIXEDSZ <= eom 1.288 + * returns: 1.289 + * -1 : format error 1.290 + * 0 : not found 1.291 + * >0 : found 1.292 + * author: 1.293 + * paul vixie, 29may94 1.294 + */ 1.295 +int 1.296 +res_nameinquery(const char *name, int type, int class, 1.297 + const u_char *buf, const u_char *eom) 1.298 +{ 1.299 + const u_char *cp = buf + HFIXEDSZ; 1.300 + int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount); 1.301 + 1.302 + while (qdcount-- > 0) { 1.303 + char tname[MAXDNAME+1]; 1.304 + int n, ttype, tclass; 1.305 + 1.306 + n = dn_expand(buf, eom, cp, tname, sizeof tname); 1.307 + if (n < 0) 1.308 + return (-1); 1.309 + cp += n; 1.310 + if (cp + 2 * INT16SZ > eom) 1.311 + return (-1); 1.312 + ttype = ns_get16(cp); cp += INT16SZ; 1.313 + tclass = ns_get16(cp); cp += INT16SZ; 1.314 + if (ttype == type && tclass == class && 1.315 + ns_samename(tname, name) == 1) 1.316 + return (1); 1.317 + } 1.318 + return (0); 1.319 +} 1.320 + 1.321 +/* int 1.322 + * res_queriesmatch(buf1, eom1, buf2, eom2) 1.323 + * is there a 1:1 mapping of (name,type,class) 1.324 + * in (buf1,eom1) and (buf2,eom2)? 1.325 + * returns: 1.326 + * -1 : format error 1.327 + * 0 : not a 1:1 mapping 1.328 + * >0 : is a 1:1 mapping 1.329 + * author: 1.330 + * paul vixie, 29may94 1.331 + */ 1.332 +int 1.333 +res_queriesmatch(const u_char *buf1, const u_char *eom1, 1.334 + const u_char *buf2, const u_char *eom2) 1.335 +{ 1.336 + const u_char *cp = buf1 + HFIXEDSZ; 1.337 + int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount); 1.338 + 1.339 + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) 1.340 + return (-1); 1.341 + 1.342 + /* 1.343 + * Only header section present in replies to 1.344 + * dynamic update packets. 1.345 + */ 1.346 + if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) && 1.347 + (((const HEADER *)(const void *)buf2)->opcode == ns_o_update)) 1.348 + return (1); 1.349 + 1.350 + if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount)) 1.351 + return (0); 1.352 + while (qdcount-- > 0) { 1.353 + char tname[MAXDNAME+1]; 1.354 + int n, ttype, tclass; 1.355 + 1.356 + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); 1.357 + if (n < 0) 1.358 + return (-1); 1.359 + cp += n; 1.360 + if (cp + 2 * INT16SZ > eom1) 1.361 + return (-1); 1.362 + ttype = ns_get16(cp); cp += INT16SZ; 1.363 + tclass = ns_get16(cp); cp += INT16SZ; 1.364 + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) 1.365 + return (0); 1.366 + } 1.367 + return (1); 1.368 +} 1.369 + 1.370 + 1.371 +int 1.372 +res_nsend(res_state statp, 1.373 + const u_char *buf, int buflen, u_char *ans, int anssiz) 1.374 +{ 1.375 + int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; 1.376 + char abuf[NI_MAXHOST]; 1.377 +#if USE_RESOLV_CACHE 1.378 + struct resolv_cache* cache; 1.379 + ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED; 1.380 +#endif 1.381 + 1.382 + if (statp->nscount == 0) { 1.383 + errno = ESRCH; 1.384 + return (-1); 1.385 + } 1.386 + if (anssiz < HFIXEDSZ) { 1.387 + errno = EINVAL; 1.388 + return (-1); 1.389 + } 1.390 + DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), 1.391 + (stdout, ";; res_send()\n"), buf, buflen); 1.392 + v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; 1.393 + gotsomewhere = 0; 1.394 + terrno = ETIMEDOUT; 1.395 + 1.396 +#if USE_RESOLV_CACHE 1.397 + cache = __get_res_cache(); 1.398 + if (cache != NULL) { 1.399 + int anslen = 0; 1.400 + cache_status = _resolv_cache_lookup( 1.401 + cache, buf, buflen, 1.402 + ans, anssiz, &anslen); 1.403 + 1.404 + if (cache_status == RESOLV_CACHE_FOUND) { 1.405 + return anslen; 1.406 + } 1.407 + } 1.408 +#endif 1.409 + 1.410 + /* 1.411 + * If the ns_addr_list in the resolver context has changed, then 1.412 + * invalidate our cached copy and the associated timing data. 1.413 + */ 1.414 + if (EXT(statp).nscount != 0) { 1.415 + int needclose = 0; 1.416 + struct sockaddr_storage peer; 1.417 + socklen_t peerlen; 1.418 + 1.419 + if (EXT(statp).nscount != statp->nscount) 1.420 + needclose++; 1.421 + else 1.422 + for (ns = 0; ns < statp->nscount; ns++) { 1.423 + if (statp->nsaddr_list[ns].sin_family && 1.424 + !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns], 1.425 + (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) { 1.426 + needclose++; 1.427 + break; 1.428 + } 1.429 + 1.430 + if (EXT(statp).nssocks[ns] == -1) 1.431 + continue; 1.432 + peerlen = sizeof(peer); 1.433 + if (getsockname(EXT(statp).nssocks[ns], 1.434 + (struct sockaddr *)(void *)&peer, &peerlen) < 0) { 1.435 + needclose++; 1.436 + break; 1.437 + } 1.438 + if (!sock_eq((struct sockaddr *)(void *)&peer, 1.439 + get_nsaddr(statp, (size_t)ns))) { 1.440 + needclose++; 1.441 + break; 1.442 + } 1.443 + } 1.444 + if (needclose) { 1.445 + res_nclose(statp); 1.446 + EXT(statp).nscount = 0; 1.447 + } 1.448 + } 1.449 + 1.450 + /* 1.451 + * Maybe initialize our private copy of the ns_addr_list. 1.452 + */ 1.453 + if (EXT(statp).nscount == 0) { 1.454 + for (ns = 0; ns < statp->nscount; ns++) { 1.455 + EXT(statp).nstimes[ns] = RES_MAXTIME; 1.456 + EXT(statp).nssocks[ns] = -1; 1.457 + if (!statp->nsaddr_list[ns].sin_family) 1.458 + continue; 1.459 + EXT(statp).ext->nsaddrs[ns].sin = 1.460 + statp->nsaddr_list[ns]; 1.461 + } 1.462 + EXT(statp).nscount = statp->nscount; 1.463 + } 1.464 + 1.465 + /* 1.466 + * Some resolvers want to even out the load on their nameservers. 1.467 + * Note that RES_BLAST overrides RES_ROTATE. 1.468 + */ 1.469 + if ((statp->options & RES_ROTATE) != 0U && 1.470 + (statp->options & RES_BLAST) == 0U) { 1.471 + union res_sockaddr_union inu; 1.472 + struct sockaddr_in ina; 1.473 + int lastns = statp->nscount - 1; 1.474 + int fd; 1.475 + u_int16_t nstime; 1.476 + 1.477 + if (EXT(statp).ext != NULL) 1.478 + inu = EXT(statp).ext->nsaddrs[0]; 1.479 + ina = statp->nsaddr_list[0]; 1.480 + fd = EXT(statp).nssocks[0]; 1.481 + nstime = EXT(statp).nstimes[0]; 1.482 + for (ns = 0; ns < lastns; ns++) { 1.483 + if (EXT(statp).ext != NULL) 1.484 + EXT(statp).ext->nsaddrs[ns] = 1.485 + EXT(statp).ext->nsaddrs[ns + 1]; 1.486 + statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; 1.487 + EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; 1.488 + EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; 1.489 + } 1.490 + if (EXT(statp).ext != NULL) 1.491 + EXT(statp).ext->nsaddrs[lastns] = inu; 1.492 + statp->nsaddr_list[lastns] = ina; 1.493 + EXT(statp).nssocks[lastns] = fd; 1.494 + EXT(statp).nstimes[lastns] = nstime; 1.495 + } 1.496 + 1.497 + /* 1.498 + * Send request, RETRY times, or until successful. 1.499 + */ 1.500 + for (try = 0; try < statp->retry; try++) { 1.501 + for (ns = 0; ns < statp->nscount; ns++) { 1.502 + struct sockaddr *nsap; 1.503 + int nsaplen; 1.504 + nsap = get_nsaddr(statp, (size_t)ns); 1.505 + nsaplen = get_salen(nsap); 1.506 + statp->_flags &= ~RES_F_LASTMASK; 1.507 + statp->_flags |= (ns << RES_F_LASTSHIFT); 1.508 + same_ns: 1.509 + if (statp->qhook) { 1.510 + int done = 0, loops = 0; 1.511 + 1.512 + do { 1.513 + res_sendhookact act; 1.514 + 1.515 + act = (*statp->qhook)(&nsap, &buf, &buflen, 1.516 + ans, anssiz, &resplen); 1.517 + switch (act) { 1.518 + case res_goahead: 1.519 + done = 1; 1.520 + break; 1.521 + case res_nextns: 1.522 + res_nclose(statp); 1.523 + goto next_ns; 1.524 + case res_done: 1.525 + return (resplen); 1.526 + case res_modified: 1.527 + /* give the hook another try */ 1.528 + if (++loops < 42) /*doug adams*/ 1.529 + break; 1.530 + /*FALLTHROUGH*/ 1.531 + case res_error: 1.532 + /*FALLTHROUGH*/ 1.533 + default: 1.534 + goto fail; 1.535 + } 1.536 + } while (!done); 1.537 + } 1.538 + 1.539 + Dprint(((statp->options & RES_DEBUG) && 1.540 + getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), 1.541 + NULL, 0, niflags) == 0), 1.542 + (stdout, ";; Querying server (# %d) address = %s\n", 1.543 + ns + 1, abuf)); 1.544 + 1.545 + 1.546 + if (v_circuit) { 1.547 + /* Use VC; at most one attempt per server. */ 1.548 + try = statp->retry; 1.549 + n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, 1.550 + ns); 1.551 + if (n < 0) 1.552 + goto fail; 1.553 + if (n == 0) 1.554 + goto next_ns; 1.555 + resplen = n; 1.556 + } else { 1.557 + /* Use datagrams. */ 1.558 + n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, 1.559 + ns, &v_circuit, &gotsomewhere); 1.560 + if (n < 0) 1.561 + goto fail; 1.562 + if (n == 0) 1.563 + goto next_ns; 1.564 + if (v_circuit) 1.565 + goto same_ns; 1.566 + resplen = n; 1.567 + } 1.568 + 1.569 + Dprint((statp->options & RES_DEBUG) || 1.570 + ((statp->pfcode & RES_PRF_REPLY) && 1.571 + (statp->pfcode & RES_PRF_HEAD1)), 1.572 + (stdout, ";; got answer:\n")); 1.573 + 1.574 + DprintQ((statp->options & RES_DEBUG) || 1.575 + (statp->pfcode & RES_PRF_REPLY), 1.576 + (stdout, "%s", ""), 1.577 + ans, (resplen > anssiz) ? anssiz : resplen); 1.578 + 1.579 +#if USE_RESOLV_CACHE 1.580 + if (cache_status == RESOLV_CACHE_NOTFOUND) { 1.581 + _resolv_cache_add(cache, buf, buflen, 1.582 + ans, resplen); 1.583 + } 1.584 +#endif 1.585 + /* 1.586 + * If we have temporarily opened a virtual circuit, 1.587 + * or if we haven't been asked to keep a socket open, 1.588 + * close the socket. 1.589 + */ 1.590 + if ((v_circuit && (statp->options & RES_USEVC) == 0U) || 1.591 + (statp->options & RES_STAYOPEN) == 0U) { 1.592 + res_nclose(statp); 1.593 + } 1.594 + if (statp->rhook) { 1.595 + int done = 0, loops = 0; 1.596 + 1.597 + do { 1.598 + res_sendhookact act; 1.599 + 1.600 + act = (*statp->rhook)(nsap, buf, buflen, 1.601 + ans, anssiz, &resplen); 1.602 + switch (act) { 1.603 + case res_goahead: 1.604 + case res_done: 1.605 + done = 1; 1.606 + break; 1.607 + case res_nextns: 1.608 + res_nclose(statp); 1.609 + goto next_ns; 1.610 + case res_modified: 1.611 + /* give the hook another try */ 1.612 + if (++loops < 42) /*doug adams*/ 1.613 + break; 1.614 + /*FALLTHROUGH*/ 1.615 + case res_error: 1.616 + /*FALLTHROUGH*/ 1.617 + default: 1.618 + goto fail; 1.619 + } 1.620 + } while (!done); 1.621 + 1.622 + } 1.623 + return (resplen); 1.624 + next_ns: ; 1.625 + } /*foreach ns*/ 1.626 + } /*foreach retry*/ 1.627 + res_nclose(statp); 1.628 + if (!v_circuit) { 1.629 + if (!gotsomewhere) 1.630 + errno = ECONNREFUSED; /* no nameservers found */ 1.631 + else 1.632 + errno = ETIMEDOUT; /* no answer obtained */ 1.633 + } else 1.634 + errno = terrno; 1.635 + return (-1); 1.636 + fail: 1.637 + res_nclose(statp); 1.638 + return (-1); 1.639 +} 1.640 + 1.641 +/* Private */ 1.642 + 1.643 +static int 1.644 +get_salen(sa) 1.645 + const struct sockaddr *sa; 1.646 +{ 1.647 + 1.648 +#ifdef HAVE_SA_LEN 1.649 + /* There are people do not set sa_len. Be forgiving to them. */ 1.650 + if (sa->sa_len) 1.651 + return (sa->sa_len); 1.652 +#endif 1.653 + 1.654 + if (sa->sa_family == AF_INET) 1.655 + return (sizeof(struct sockaddr_in)); 1.656 + else if (sa->sa_family == AF_INET6) 1.657 + return (sizeof(struct sockaddr_in6)); 1.658 + else 1.659 + return (0); /* unknown, die on connect */ 1.660 +} 1.661 + 1.662 +/* 1.663 + * pick appropriate nsaddr_list for use. see res_init() for initialization. 1.664 + */ 1.665 +static struct sockaddr * 1.666 +get_nsaddr(statp, n) 1.667 + res_state statp; 1.668 + size_t n; 1.669 +{ 1.670 + 1.671 + if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { 1.672 + /* 1.673 + * - EXT(statp).ext->nsaddrs[n] holds an address that is larger 1.674 + * than struct sockaddr, and 1.675 + * - user code did not update statp->nsaddr_list[n]. 1.676 + */ 1.677 + return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; 1.678 + } else { 1.679 + /* 1.680 + * - user code updated statp->nsaddr_list[n], or 1.681 + * - statp->nsaddr_list[n] has the same content as 1.682 + * EXT(statp).ext->nsaddrs[n]. 1.683 + */ 1.684 + return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; 1.685 + } 1.686 +} 1.687 + 1.688 +static int 1.689 +send_vc(res_state statp, 1.690 + const u_char *buf, int buflen, u_char *ans, int anssiz, 1.691 + int *terrno, int ns) 1.692 +{ 1.693 + const HEADER *hp = (const HEADER *)(const void *)buf; 1.694 + HEADER *anhp = (HEADER *)(void *)ans; 1.695 + struct sockaddr *nsap; 1.696 + int nsaplen; 1.697 + int truncating, connreset, resplen, n; 1.698 + struct iovec iov[2]; 1.699 + u_short len; 1.700 + u_char *cp; 1.701 + void *tmp; 1.702 + 1.703 + nsap = get_nsaddr(statp, (size_t)ns); 1.704 + nsaplen = get_salen(nsap); 1.705 + 1.706 + connreset = 0; 1.707 + same_ns: 1.708 + truncating = 0; 1.709 + 1.710 + /* Are we still talking to whom we want to talk to? */ 1.711 + if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { 1.712 + struct sockaddr_storage peer; 1.713 + socklen_t size = sizeof peer; 1.714 + 1.715 + if (getpeername(statp->_vcsock, 1.716 + (struct sockaddr *)(void *)&peer, &size) < 0 || 1.717 + !sock_eq((struct sockaddr *)(void *)&peer, nsap)) { 1.718 + res_nclose(statp); 1.719 + statp->_flags &= ~RES_F_VC; 1.720 + } 1.721 + } 1.722 + 1.723 + if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { 1.724 + if (statp->_vcsock >= 0) 1.725 + res_nclose(statp); 1.726 + 1.727 + statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); 1.728 + if (statp->_vcsock > highestFD) { 1.729 + res_nclose(statp); 1.730 + errno = ENOTSOCK; 1.731 + } 1.732 + if (statp->_vcsock < 0) { 1.733 + switch (errno) { 1.734 + case EPROTONOSUPPORT: 1.735 +#ifdef EPFNOSUPPORT 1.736 + case EPFNOSUPPORT: 1.737 +#endif 1.738 + case EAFNOSUPPORT: 1.739 + Perror(statp, stderr, "socket(vc)", errno); 1.740 + return (0); 1.741 + default: 1.742 + *terrno = errno; 1.743 + Perror(statp, stderr, "socket(vc)", errno); 1.744 + return (-1); 1.745 + } 1.746 + } 1.747 + errno = 0; 1.748 + if (random_bind(statp->_vcsock,nsap->sa_family) < 0) { 1.749 + *terrno = errno; 1.750 + Aerror(statp, stderr, "bind/vc", errno, nsap, 1.751 + nsaplen); 1.752 + res_nclose(statp); 1.753 + return (0); 1.754 + } 1.755 + if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) { 1.756 + *terrno = errno; 1.757 + Aerror(statp, stderr, "connect/vc", errno, nsap, 1.758 + nsaplen); 1.759 + res_nclose(statp); 1.760 + return (0); 1.761 + } 1.762 + statp->_flags |= RES_F_VC; 1.763 + } 1.764 + 1.765 + /* 1.766 + * Send length & message 1.767 + */ 1.768 + ns_put16((u_short)buflen, (u_char*)(void *)&len); 1.769 + iov[0] = evConsIovec(&len, INT16SZ); 1.770 + DE_CONST(buf, tmp); 1.771 + iov[1] = evConsIovec(tmp, (size_t)buflen); 1.772 + if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { 1.773 + *terrno = errno; 1.774 + Perror(statp, stderr, "write failed", errno); 1.775 + res_nclose(statp); 1.776 + return (0); 1.777 + } 1.778 + /* 1.779 + * Receive length & response 1.780 + */ 1.781 + read_len: 1.782 + cp = ans; 1.783 + len = INT16SZ; 1.784 + while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) { 1.785 + cp += n; 1.786 + if ((len -= n) == 0) 1.787 + break; 1.788 + } 1.789 + if (n <= 0) { 1.790 + *terrno = errno; 1.791 + Perror(statp, stderr, "read failed", errno); 1.792 + res_nclose(statp); 1.793 + /* 1.794 + * A long running process might get its TCP 1.795 + * connection reset if the remote server was 1.796 + * restarted. Requery the server instead of 1.797 + * trying a new one. When there is only one 1.798 + * server, this means that a query might work 1.799 + * instead of failing. We only allow one reset 1.800 + * per query to prevent looping. 1.801 + */ 1.802 + if (*terrno == ECONNRESET && !connreset) { 1.803 + connreset = 1; 1.804 + res_nclose(statp); 1.805 + goto same_ns; 1.806 + } 1.807 + res_nclose(statp); 1.808 + return (0); 1.809 + } 1.810 + resplen = ns_get16(ans); 1.811 + if (resplen > anssiz) { 1.812 + Dprint(statp->options & RES_DEBUG, 1.813 + (stdout, ";; response truncated\n") 1.814 + ); 1.815 + truncating = 1; 1.816 + len = anssiz; 1.817 + } else 1.818 + len = resplen; 1.819 + if (len < HFIXEDSZ) { 1.820 + /* 1.821 + * Undersized message. 1.822 + */ 1.823 + Dprint(statp->options & RES_DEBUG, 1.824 + (stdout, ";; undersized: %d\n", len)); 1.825 + *terrno = EMSGSIZE; 1.826 + res_nclose(statp); 1.827 + return (0); 1.828 + } 1.829 + cp = ans; 1.830 + while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){ 1.831 + cp += n; 1.832 + len -= n; 1.833 + } 1.834 + if (n <= 0) { 1.835 + *terrno = errno; 1.836 + Perror(statp, stderr, "read(vc)", errno); 1.837 + res_nclose(statp); 1.838 + return (0); 1.839 + } 1.840 + if (truncating) { 1.841 + /* 1.842 + * Flush rest of answer so connection stays in synch. 1.843 + */ 1.844 + anhp->tc = 1; 1.845 + len = resplen - anssiz; 1.846 + while (len != 0) { 1.847 + char junk[PACKETSZ]; 1.848 + 1.849 + n = read(statp->_vcsock, junk, 1.850 + (len > sizeof junk) ? sizeof junk : len); 1.851 + if (n > 0) 1.852 + len -= n; 1.853 + else 1.854 + break; 1.855 + } 1.856 + } 1.857 + /* 1.858 + * If the calling applicating has bailed out of 1.859 + * a previous call and failed to arrange to have 1.860 + * the circuit closed or the server has got 1.861 + * itself confused, then drop the packet and 1.862 + * wait for the correct one. 1.863 + */ 1.864 + if (hp->id != anhp->id) { 1.865 + DprintQ((statp->options & RES_DEBUG) || 1.866 + (statp->pfcode & RES_PRF_REPLY), 1.867 + (stdout, ";; old answer (unexpected):\n"), 1.868 + ans, (resplen > anssiz) ? anssiz: resplen); 1.869 + goto read_len; 1.870 + } 1.871 + 1.872 + /* 1.873 + * All is well, or the error is fatal. Signal that the 1.874 + * next nameserver ought not be tried. 1.875 + */ 1.876 + return (resplen); 1.877 +} 1.878 + 1.879 +static int 1.880 +send_dg(res_state statp, 1.881 + const u_char *buf, int buflen, u_char *ans, int anssiz, 1.882 + int *terrno, int ns, int *v_circuit, int *gotsomewhere) 1.883 +{ 1.884 + const HEADER *hp = (const HEADER *)(const void *)buf; 1.885 + HEADER *anhp = (HEADER *)(void *)ans; 1.886 + const struct sockaddr *nsap; 1.887 + int nsaplen; 1.888 + struct timespec now, timeout, finish; 1.889 + fd_set dsmask; 1.890 + struct sockaddr_storage from; 1.891 + socklen_t fromlen; 1.892 + int resplen, seconds, n, s; 1.893 + 1.894 + nsap = get_nsaddr(statp, (size_t)ns); 1.895 + nsaplen = get_salen(nsap); 1.896 + if (EXT(statp).nssocks[ns] == -1) { 1.897 + EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); 1.898 + if (EXT(statp).nssocks[ns] > highestFD) { 1.899 + res_nclose(statp); 1.900 + errno = ENOTSOCK; 1.901 + } 1.902 + if (EXT(statp).nssocks[ns] < 0) { 1.903 + switch (errno) { 1.904 + case EPROTONOSUPPORT: 1.905 +#ifdef EPFNOSUPPORT 1.906 + case EPFNOSUPPORT: 1.907 +#endif 1.908 + case EAFNOSUPPORT: 1.909 + Perror(statp, stderr, "socket(dg)", errno); 1.910 + return (0); 1.911 + default: 1.912 + *terrno = errno; 1.913 + Perror(statp, stderr, "socket(dg)", errno); 1.914 + return (-1); 1.915 + } 1.916 + } 1.917 +#ifndef CANNOT_CONNECT_DGRAM 1.918 + /* 1.919 + * On a 4.3BSD+ machine (client and server, 1.920 + * actually), sending to a nameserver datagram 1.921 + * port with no nameserver will cause an 1.922 + * ICMP port unreachable message to be returned. 1.923 + * If our datagram socket is "connected" to the 1.924 + * server, we get an ECONNREFUSED error on the next 1.925 + * socket operation, and select returns if the 1.926 + * error message is received. We can thus detect 1.927 + * the absence of a nameserver without timing out. 1.928 + */ 1.929 + if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) { 1.930 + Aerror(statp, stderr, "bind(dg)", errno, nsap, 1.931 + nsaplen); 1.932 + res_nclose(statp); 1.933 + return (0); 1.934 + } 1.935 + if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) { 1.936 + Aerror(statp, stderr, "connect(dg)", errno, nsap, 1.937 + nsaplen); 1.938 + res_nclose(statp); 1.939 + return (0); 1.940 + } 1.941 +#endif /* !CANNOT_CONNECT_DGRAM */ 1.942 + Dprint(statp->options & RES_DEBUG, 1.943 + (stdout, ";; new DG socket\n")) 1.944 + } 1.945 + s = EXT(statp).nssocks[ns]; 1.946 +#ifndef CANNOT_CONNECT_DGRAM 1.947 + if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) { 1.948 + Perror(statp, stderr, "send", errno); 1.949 + res_nclose(statp); 1.950 + return (0); 1.951 + } 1.952 +#else /* !CANNOT_CONNECT_DGRAM */ 1.953 + if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) 1.954 + { 1.955 + Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); 1.956 + res_nclose(statp); 1.957 + return (0); 1.958 + } 1.959 +#endif /* !CANNOT_CONNECT_DGRAM */ 1.960 + 1.961 + /* 1.962 + * Wait for reply. 1.963 + */ 1.964 + seconds = (statp->retrans << ns); 1.965 + if (ns > 0) 1.966 + seconds /= statp->nscount; 1.967 + if (seconds <= 0) 1.968 + seconds = 1; 1.969 + now = evNowTime(); 1.970 + timeout = evConsTime((long)seconds, 0L); 1.971 + finish = evAddTime(now, timeout); 1.972 + goto nonow; 1.973 + wait: 1.974 + now = evNowTime(); 1.975 + nonow: 1.976 + FD_ZERO(&dsmask); 1.977 + FD_SET(s, &dsmask); 1.978 + if (evCmpTime(finish, now) > 0) 1.979 + timeout = evSubTime(finish, now); 1.980 + else 1.981 + timeout = evConsTime(0L, 0L); 1.982 + n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); 1.983 + if (n == 0) { 1.984 + Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); 1.985 + *gotsomewhere = 1; 1.986 + return (0); 1.987 + } 1.988 + if (n < 0) { 1.989 + if (errno == EINTR) 1.990 + goto wait; 1.991 + Perror(statp, stderr, "select", errno); 1.992 + res_nclose(statp); 1.993 + return (0); 1.994 + } 1.995 + errno = 0; 1.996 + fromlen = sizeof(from); 1.997 + resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0, 1.998 + (struct sockaddr *)(void *)&from, &fromlen); 1.999 + if (resplen <= 0) { 1.1000 + Perror(statp, stderr, "recvfrom", errno); 1.1001 + res_nclose(statp); 1.1002 + return (0); 1.1003 + } 1.1004 + *gotsomewhere = 1; 1.1005 + if (resplen < HFIXEDSZ) { 1.1006 + /* 1.1007 + * Undersized message. 1.1008 + */ 1.1009 + Dprint(statp->options & RES_DEBUG, 1.1010 + (stdout, ";; undersized: %d\n", 1.1011 + resplen)); 1.1012 + *terrno = EMSGSIZE; 1.1013 + res_nclose(statp); 1.1014 + return (0); 1.1015 + } 1.1016 + if (hp->id != anhp->id) { 1.1017 + /* 1.1018 + * response from old query, ignore it. 1.1019 + * XXX - potential security hazard could 1.1020 + * be detected here. 1.1021 + */ 1.1022 + DprintQ((statp->options & RES_DEBUG) || 1.1023 + (statp->pfcode & RES_PRF_REPLY), 1.1024 + (stdout, ";; old answer:\n"), 1.1025 + ans, (resplen > anssiz) ? anssiz : resplen); 1.1026 + goto wait; 1.1027 + } 1.1028 + if (!(statp->options & RES_INSECURE1) && 1.1029 + !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) { 1.1030 + /* 1.1031 + * response from wrong server? ignore it. 1.1032 + * XXX - potential security hazard could 1.1033 + * be detected here. 1.1034 + */ 1.1035 + DprintQ((statp->options & RES_DEBUG) || 1.1036 + (statp->pfcode & RES_PRF_REPLY), 1.1037 + (stdout, ";; not our server:\n"), 1.1038 + ans, (resplen > anssiz) ? anssiz : resplen); 1.1039 + goto wait; 1.1040 + } 1.1041 +#ifdef RES_USE_EDNS0 1.1042 + if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { 1.1043 + /* 1.1044 + * Do not retry if the server do not understand EDNS0. 1.1045 + * The case has to be captured here, as FORMERR packet do not 1.1046 + * carry query section, hence res_queriesmatch() returns 0. 1.1047 + */ 1.1048 + DprintQ(statp->options & RES_DEBUG, 1.1049 + (stdout, "server rejected query with EDNS0:\n"), 1.1050 + ans, (resplen > anssiz) ? anssiz : resplen); 1.1051 + /* record the error */ 1.1052 + statp->_flags |= RES_F_EDNS0ERR; 1.1053 + res_nclose(statp); 1.1054 + return (0); 1.1055 + } 1.1056 +#endif 1.1057 + if (!(statp->options & RES_INSECURE2) && 1.1058 + !res_queriesmatch(buf, buf + buflen, 1.1059 + ans, ans + anssiz)) { 1.1060 + /* 1.1061 + * response contains wrong query? ignore it. 1.1062 + * XXX - potential security hazard could 1.1063 + * be detected here. 1.1064 + */ 1.1065 + DprintQ((statp->options & RES_DEBUG) || 1.1066 + (statp->pfcode & RES_PRF_REPLY), 1.1067 + (stdout, ";; wrong query name:\n"), 1.1068 + ans, (resplen > anssiz) ? anssiz : resplen); 1.1069 + goto wait; 1.1070 + } 1.1071 + if (anhp->rcode == SERVFAIL || 1.1072 + anhp->rcode == NOTIMP || 1.1073 + anhp->rcode == REFUSED) { 1.1074 + DprintQ(statp->options & RES_DEBUG, 1.1075 + (stdout, "server rejected query:\n"), 1.1076 + ans, (resplen > anssiz) ? anssiz : resplen); 1.1077 + res_nclose(statp); 1.1078 + /* don't retry if called from dig */ 1.1079 + if (!statp->pfcode) 1.1080 + return (0); 1.1081 + } 1.1082 + if (!(statp->options & RES_IGNTC) && anhp->tc) { 1.1083 + /* 1.1084 + * To get the rest of answer, 1.1085 + * use TCP with same server. 1.1086 + */ 1.1087 + Dprint(statp->options & RES_DEBUG, 1.1088 + (stdout, ";; truncated answer\n")); 1.1089 + *v_circuit = 1; 1.1090 + res_nclose(statp); 1.1091 + return (1); 1.1092 + } 1.1093 + /* 1.1094 + * All is well, or the error is fatal. Signal that the 1.1095 + * next nameserver ought not be tried. 1.1096 + */ 1.1097 + return (resplen); 1.1098 +} 1.1099 + 1.1100 +static void 1.1101 +Aerror(const res_state statp, FILE *file, const char *string, int error, 1.1102 + const struct sockaddr *address, int alen) 1.1103 +{ 1.1104 + int save = errno; 1.1105 + char hbuf[NI_MAXHOST]; 1.1106 + char sbuf[NI_MAXSERV]; 1.1107 + 1.1108 + alen = alen; 1.1109 + 1.1110 + if ((statp->options & RES_DEBUG) != 0U) { 1.1111 + if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf), 1.1112 + sbuf, sizeof(sbuf), niflags)) { 1.1113 + strncpy(hbuf, "?", sizeof(hbuf) - 1); 1.1114 + hbuf[sizeof(hbuf) - 1] = '\0'; 1.1115 + strncpy(sbuf, "?", sizeof(sbuf) - 1); 1.1116 + sbuf[sizeof(sbuf) - 1] = '\0'; 1.1117 + } 1.1118 + fprintf(file, "res_send: %s ([%s].%s): %s\n", 1.1119 + string, hbuf, sbuf, strerror(error)); 1.1120 + } 1.1121 + errno = save; 1.1122 +} 1.1123 + 1.1124 +static void 1.1125 +Perror(const res_state statp, FILE *file, const char *string, int error) { 1.1126 + int save = errno; 1.1127 + 1.1128 + if ((statp->options & RES_DEBUG) != 0U) 1.1129 + fprintf(file, "res_send: %s: %s\n", 1.1130 + string, strerror(error)); 1.1131 + errno = save; 1.1132 +} 1.1133 + 1.1134 +static int 1.1135 +sock_eq(struct sockaddr *a, struct sockaddr *b) { 1.1136 + struct sockaddr_in *a4, *b4; 1.1137 + struct sockaddr_in6 *a6, *b6; 1.1138 + 1.1139 + if (a->sa_family != b->sa_family) 1.1140 + return 0; 1.1141 + switch (a->sa_family) { 1.1142 + case AF_INET: 1.1143 + a4 = (struct sockaddr_in *)(void *)a; 1.1144 + b4 = (struct sockaddr_in *)(void *)b; 1.1145 + return a4->sin_port == b4->sin_port && 1.1146 + a4->sin_addr.s_addr == b4->sin_addr.s_addr; 1.1147 + case AF_INET6: 1.1148 + a6 = (struct sockaddr_in6 *)(void *)a; 1.1149 + b6 = (struct sockaddr_in6 *)(void *)b; 1.1150 + return a6->sin6_port == b6->sin6_port && 1.1151 +#ifdef HAVE_SIN6_SCOPE_ID 1.1152 + a6->sin6_scope_id == b6->sin6_scope_id && 1.1153 +#endif 1.1154 + IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); 1.1155 + default: 1.1156 + return 0; 1.1157 + } 1.1158 +} 1.1159 + 1.1160 +#ifdef NEED_PSELECT 1.1161 +/* XXX needs to move to the porting library. */ 1.1162 +static int 1.1163 +pselect(int nfds, void *rfds, void *wfds, void *efds, 1.1164 + struct timespec *tsp, const sigset_t *sigmask) 1.1165 +{ 1.1166 + struct timeval tv, *tvp; 1.1167 + sigset_t sigs; 1.1168 + int n; 1.1169 + 1.1170 + if (tsp) { 1.1171 + tvp = &tv; 1.1172 + tv = evTimeVal(*tsp); 1.1173 + } else 1.1174 + tvp = NULL; 1.1175 + if (sigmask) 1.1176 + sigprocmask(SIG_SETMASK, sigmask, &sigs); 1.1177 + n = select(nfds, rfds, wfds, efds, tvp); 1.1178 + if (sigmask) 1.1179 + sigprocmask(SIG_SETMASK, &sigs, NULL); 1.1180 + if (tsp) 1.1181 + *tsp = evTimeSpec(tv); 1.1182 + return (n); 1.1183 +} 1.1184 +#endif