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