blob: a95997d59ac2831a112b01e0d9a9ce410f7ebf91 [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */
2
3/*
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08004 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36/*
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 */
55
56/*
57 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
58 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
59 *
60 * Permission to use, copy, modify, and distribute this software for any
61 * purpose with or without fee is hereby granted, provided that the above
62 * copyright notice and this permission notice appear in all copies.
63 *
64 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
65 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
66 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
67 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
68 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
69 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
70 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
71 */
72
73#include <sys/cdefs.h>
74#if defined(LIBC_SCCS) && !defined(lint)
75#ifdef notdef
76static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
77static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp";
78#else
79__RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
80#endif
81#endif /* LIBC_SCCS and not lint */
82
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080083/*
84 * Send query to name server and wait for reply.
85 */
86
87#include <sys/types.h>
88#include <sys/param.h>
89#include <sys/time.h>
90#include <sys/socket.h>
91#include <sys/uio.h>
92
93#include <netinet/in.h>
Calin Juravle569fb982014-03-04 15:01:29 +000094#include <arpa/nameser.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080095#include <arpa/inet.h>
96
97#include <errno.h>
Robert Greenwaltecd0e952012-01-11 10:04:48 -080098#include <fcntl.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080099#include <netdb.h>
Bernie Innocentib6647242018-06-18 14:14:43 +0900100#include <poll.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800101#ifdef ANDROID_CHANGES
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500102#include "resolv_netid.h"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800103#include "resolv_private.h"
Lorenzo Colitti5f027202018-05-01 16:19:01 +0900104#include "private/android_filesystem_config.h"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800105#else
106#include <resolv.h>
107#endif
108#include <signal.h>
109#include <stdio.h>
110#include <stdlib.h>
111#include <string.h>
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800112#include <time.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800113#include <unistd.h>
114
115#include <isc/eventlib.h>
116
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900117#include <resolv_cache.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800118
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700119#include <async_safe/log.h>
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800120
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800121#ifndef DE_CONST
122#define DE_CONST(c,v) v = ((c) ? \
123 strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
124#endif
125
126/* Options. Leave them on. */
127#ifndef DEBUG
128#define DEBUG
129#endif
130#include "res_debug.h"
131#include "res_private.h"
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900132#include "resolv_stats.h"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800133
134#define EXT(res) ((res)->_u._ext)
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800135#define DBG 0
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800136
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800137/* Forward. */
138
139static int get_salen __P((const struct sockaddr *));
140static struct sockaddr * get_nsaddr __P((res_state, size_t));
Bernie Innocenti58d13622018-07-29 18:21:23 +0900141static int send_vc(res_state, struct __res_params *params, const u_char *, int,
142 u_char *, int, int *, int, time_t *, int *, int *);
143static int send_dg(res_state, struct __res_params *params, const u_char *, int,
144 u_char *, int, int *, int, int *, int *, time_t *, int *, int *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800145static void Aerror(const res_state, FILE *, const char *, int,
146 const struct sockaddr *, int);
147static void Perror(const res_state, FILE *, const char *, int);
148static int sock_eq(struct sockaddr *, struct sockaddr *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800149void res_pquery(const res_state, const u_char *, int, FILE *);
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800150static int connect_with_timeout(int sock, const struct sockaddr *nsap,
Bernie Innocenti58d13622018-07-29 18:21:23 +0900151 socklen_t salen, const struct timespec timeout);
Bernie Innocentib6647242018-06-18 14:14:43 +0900152static int retrying_poll(const int sock, short events, const struct timespec* finish);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800153
154/* BIONIC-BEGIN: implement source port randomization */
155typedef union {
156 struct sockaddr sa;
157 struct sockaddr_in sin;
158 struct sockaddr_in6 sin6;
159} _sockaddr_union;
160
161static int
162random_bind( int s, int family )
163{
164 _sockaddr_union u;
165 int j;
166 socklen_t slen;
167
168 /* clear all, this also sets the IP4/6 address to 'any' */
169 memset( &u, 0, sizeof u );
170
171 switch (family) {
172 case AF_INET:
173 u.sin.sin_family = family;
174 slen = sizeof u.sin;
175 break;
176 case AF_INET6:
177 u.sin6.sin6_family = family;
178 slen = sizeof u.sin6;
179 break;
180 default:
181 errno = EPROTO;
182 return -1;
183 }
184
185 /* first try to bind to a random source port a few times */
186 for (j = 0; j < 10; j++) {
187 /* find a random port between 1025 .. 65534 */
188 int port = 1025 + (res_randomid() % (65535-1025));
189 if (family == AF_INET)
190 u.sin.sin_port = htons(port);
191 else
192 u.sin6.sin6_port = htons(port);
193
194 if ( !bind( s, &u.sa, slen ) )
195 return 0;
196 }
197
198 /* nothing after 10 tries, our network table is probably busy */
199 /* let the system decide which port is best */
200 if (family == AF_INET)
201 u.sin.sin_port = 0;
202 else
203 u.sin6.sin6_port = 0;
204
205 return bind( s, &u.sa, slen );
206}
207/* BIONIC-END */
208
209static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
210
211/* Public. */
212
213/* int
214 * res_isourserver(ina)
215 * looks up "ina" in _res.ns_addr_list[]
216 * returns:
217 * 0 : not found
218 * >0 : found
219 * author:
220 * paul vixie, 29may94
221 */
Jim Huang7cc56662010-10-15 02:02:57 +0800222__LIBC_HIDDEN__ int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800223res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
224 const struct sockaddr_in *inp, *srv;
225 const struct sockaddr_in6 *in6p, *srv6;
226 int ns;
227
228 switch (sa->sa_family) {
229 case AF_INET:
230 inp = (const struct sockaddr_in *)(const void *)sa;
231 for (ns = 0; ns < statp->nscount; ns++) {
232 srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
233 if (srv->sin_family == inp->sin_family &&
234 srv->sin_port == inp->sin_port &&
235 (srv->sin_addr.s_addr == INADDR_ANY ||
236 srv->sin_addr.s_addr == inp->sin_addr.s_addr))
237 return (1);
238 }
239 break;
240 case AF_INET6:
241 if (EXT(statp).ext == NULL)
242 break;
243 in6p = (const struct sockaddr_in6 *)(const void *)sa;
244 for (ns = 0; ns < statp->nscount; ns++) {
245 srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
246 if (srv6->sin6_family == in6p->sin6_family &&
247 srv6->sin6_port == in6p->sin6_port &&
248#ifdef HAVE_SIN6_SCOPE_ID
249 (srv6->sin6_scope_id == 0 ||
250 srv6->sin6_scope_id == in6p->sin6_scope_id) &&
251#endif
252 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
253 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
254 return (1);
255 }
256 break;
257 default:
258 break;
259 }
260 return (0);
261}
262
263/* int
264 * res_nameinquery(name, type, class, buf, eom)
265 * look for (name,type,class) in the query section of packet (buf,eom)
266 * requires:
267 * buf + HFIXEDSZ <= eom
268 * returns:
269 * -1 : format error
270 * 0 : not found
271 * >0 : found
272 * author:
273 * paul vixie, 29may94
274 */
275int
276res_nameinquery(const char *name, int type, int class,
277 const u_char *buf, const u_char *eom)
278{
279 const u_char *cp = buf + HFIXEDSZ;
280 int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
281
282 while (qdcount-- > 0) {
283 char tname[MAXDNAME+1];
284 int n, ttype, tclass;
285
286 n = dn_expand(buf, eom, cp, tname, sizeof tname);
287 if (n < 0)
288 return (-1);
289 cp += n;
290 if (cp + 2 * INT16SZ > eom)
291 return (-1);
292 ttype = ns_get16(cp); cp += INT16SZ;
293 tclass = ns_get16(cp); cp += INT16SZ;
294 if (ttype == type && tclass == class &&
295 ns_samename(tname, name) == 1)
296 return (1);
297 }
298 return (0);
299}
300
301/* int
302 * res_queriesmatch(buf1, eom1, buf2, eom2)
303 * is there a 1:1 mapping of (name,type,class)
304 * in (buf1,eom1) and (buf2,eom2)?
305 * returns:
306 * -1 : format error
307 * 0 : not a 1:1 mapping
308 * >0 : is a 1:1 mapping
309 * author:
310 * paul vixie, 29may94
311 */
312int
313res_queriesmatch(const u_char *buf1, const u_char *eom1,
314 const u_char *buf2, const u_char *eom2)
315{
316 const u_char *cp = buf1 + HFIXEDSZ;
317 int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
318
319 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
320 return (-1);
321
322 /*
323 * Only header section present in replies to
324 * dynamic update packets.
325 */
326 if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
327 (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
328 return (1);
329
330 if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
331 return (0);
332 while (qdcount-- > 0) {
333 char tname[MAXDNAME+1];
334 int n, ttype, tclass;
335
336 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
337 if (n < 0)
338 return (-1);
339 cp += n;
340 if (cp + 2 * INT16SZ > eom1)
341 return (-1);
342 ttype = ns_get16(cp); cp += INT16SZ;
343 tclass = ns_get16(cp); cp += INT16SZ;
344 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
345 return (0);
346 }
347 return (1);
348}
349
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800350int
351res_nsend(res_state statp,
352 const u_char *buf, int buflen, u_char *ans, int anssiz)
353{
354 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
355 char abuf[NI_MAXHOST];
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900356 ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;
Mattias Falkc63e5902011-08-23 14:34:14 +0200357
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800358 if (anssiz < HFIXEDSZ) {
359 errno = EINVAL;
360 return (-1);
361 }
362 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
363 (stdout, ";; res_send()\n"), buf, buflen);
364 v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
365 gotsomewhere = 0;
366 terrno = ETIMEDOUT;
367
Paul Jensen41d9a502014-04-08 15:43:41 -0400368 int anslen = 0;
369 cache_status = _resolv_cache_lookup(
370 statp->netid, buf, buflen,
371 ans, anssiz, &anslen);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800372
Paul Jensen41d9a502014-04-08 15:43:41 -0400373 if (cache_status == RESOLV_CACHE_FOUND) {
374 return anslen;
375 } else if (cache_status != RESOLV_CACHE_UNSUPPORTED) {
376 // had a cache miss for a known network, so populate the thread private
377 // data so the normal resolve path can do its thing
378 _resolv_populate_res_for_net(statp);
Mattias Falkc63e5902011-08-23 14:34:14 +0200379 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200380 if (statp->nscount == 0) {
Lorenzo Colittie5477f82014-11-28 20:03:23 +0900381 // We have no nameservers configured, so there's no point trying.
382 // Tell the cache the query failed, or any retries and anyone else asking the same
383 // question will block for PENDING_REQUEST_TIMEOUT seconds instead of failing fast.
384 _resolv_cache_query_failed(statp->netid, buf, buflen);
Mattias Falkc63e5902011-08-23 14:34:14 +0200385 errno = ESRCH;
386 return (-1);
387 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800388
389 /*
390 * If the ns_addr_list in the resolver context has changed, then
391 * invalidate our cached copy and the associated timing data.
392 */
393 if (EXT(statp).nscount != 0) {
394 int needclose = 0;
395 struct sockaddr_storage peer;
396 socklen_t peerlen;
397
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900398 if (EXT(statp).nscount != statp->nscount) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800399 needclose++;
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900400 } else {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800401 for (ns = 0; ns < statp->nscount; ns++) {
402 if (statp->nsaddr_list[ns].sin_family &&
403 !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
404 (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
405 needclose++;
406 break;
407 }
408
409 if (EXT(statp).nssocks[ns] == -1)
410 continue;
411 peerlen = sizeof(peer);
Jim Huang87043f92011-12-12 16:32:56 +0800412 if (getpeername(EXT(statp).nssocks[ns],
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800413 (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
414 needclose++;
415 break;
416 }
417 if (!sock_eq((struct sockaddr *)(void *)&peer,
418 get_nsaddr(statp, (size_t)ns))) {
419 needclose++;
420 break;
421 }
422 }
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900423 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800424 if (needclose) {
425 res_nclose(statp);
426 EXT(statp).nscount = 0;
427 }
428 }
429
430 /*
431 * Maybe initialize our private copy of the ns_addr_list.
432 */
433 if (EXT(statp).nscount == 0) {
434 for (ns = 0; ns < statp->nscount; ns++) {
435 EXT(statp).nstimes[ns] = RES_MAXTIME;
436 EXT(statp).nssocks[ns] = -1;
437 if (!statp->nsaddr_list[ns].sin_family)
438 continue;
439 EXT(statp).ext->nsaddrs[ns].sin =
440 statp->nsaddr_list[ns];
441 }
442 EXT(statp).nscount = statp->nscount;
443 }
444
445 /*
446 * Some resolvers want to even out the load on their nameservers.
447 * Note that RES_BLAST overrides RES_ROTATE.
448 */
449 if ((statp->options & RES_ROTATE) != 0U &&
450 (statp->options & RES_BLAST) == 0U) {
451 union res_sockaddr_union inu;
452 struct sockaddr_in ina;
453 int lastns = statp->nscount - 1;
454 int fd;
455 u_int16_t nstime;
456
457 if (EXT(statp).ext != NULL)
458 inu = EXT(statp).ext->nsaddrs[0];
459 ina = statp->nsaddr_list[0];
460 fd = EXT(statp).nssocks[0];
461 nstime = EXT(statp).nstimes[0];
462 for (ns = 0; ns < lastns; ns++) {
463 if (EXT(statp).ext != NULL)
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900464 EXT(statp).ext->nsaddrs[ns] =
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800465 EXT(statp).ext->nsaddrs[ns + 1];
466 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
467 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
468 EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
469 }
470 if (EXT(statp).ext != NULL)
471 EXT(statp).ext->nsaddrs[lastns] = inu;
472 statp->nsaddr_list[lastns] = ina;
473 EXT(statp).nssocks[lastns] = fd;
474 EXT(statp).nstimes[lastns] = nstime;
475 }
476
477 /*
478 * Send request, RETRY times, or until successful.
479 */
480 for (try = 0; try < statp->retry; try++) {
Pierre Imaifff35672016-04-18 11:42:14 +0900481 struct __res_stats stats[MAXNS];
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900482 struct __res_params params;
483 int revision_id = _resolv_cache_get_resolver_stats(statp->netid, &params, stats);
Pierre Imaifff35672016-04-18 11:42:14 +0900484 bool usable_servers[MAXNS];
Pierre Imai97c9d732016-04-18 12:00:12 +0900485 android_net_res_stats_get_usable_servers(&params, stats, statp->nscount,
486 usable_servers);
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900487
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800488 for (ns = 0; ns < statp->nscount; ns++) {
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900489 if (!usable_servers[ns]) continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800490 struct sockaddr *nsap;
491 int nsaplen;
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900492 time_t now = 0;
493 int rcode = RCODE_INTERNAL_ERROR;
494 int delay = 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800495 nsap = get_nsaddr(statp, (size_t)ns);
496 nsaplen = get_salen(nsap);
497 statp->_flags &= ~RES_F_LASTMASK;
498 statp->_flags |= (ns << RES_F_LASTSHIFT);
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900499
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800500 same_ns:
501 if (statp->qhook) {
502 int done = 0, loops = 0;
503
504 do {
505 res_sendhookact act;
506
507 act = (*statp->qhook)(&nsap, &buf, &buflen,
508 ans, anssiz, &resplen);
509 switch (act) {
510 case res_goahead:
511 done = 1;
512 break;
513 case res_nextns:
514 res_nclose(statp);
515 goto next_ns;
516 case res_done:
Ben Schwartzf0305dc2017-04-24 17:57:11 -0400517 if (cache_status == RESOLV_CACHE_NOTFOUND) {
518 _resolv_cache_add(statp->netid, buf, buflen,
519 ans, resplen);
520 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800521 return (resplen);
522 case res_modified:
523 /* give the hook another try */
524 if (++loops < 42) /*doug adams*/
525 break;
526 /*FALLTHROUGH*/
527 case res_error:
528 /*FALLTHROUGH*/
529 default:
530 goto fail;
531 }
532 } while (!done);
533 }
534
535 Dprint(((statp->options & RES_DEBUG) &&
536 getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800537 NULL, 0, niflags) == 0),
538 (stdout, ";; Querying server (# %d) address = %s\n",
539 ns + 1, abuf));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800540
541
542 if (v_circuit) {
543 /* Use VC; at most one attempt per server. */
544 try = statp->retry;
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800545
Bernie Innocenti58d13622018-07-29 18:21:23 +0900546 n = send_vc(statp, &params, buf, buflen, ans, anssiz, &terrno,
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900547 ns, &now, &rcode, &delay);
548
Pierre Imai8b8611a2016-04-27 17:30:30 +0900549 /*
550 * Only record stats the first time we try a query. This ensures that
551 * queries that deterministically fail (e.g., a name that always returns
552 * SERVFAIL or times out) do not unduly affect the stats.
553 */
554 if (try == 0) {
555 struct __res_sample sample;
556 _res_stats_set_sample(&sample, now, rcode, delay);
557 _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id,
558 ns, &sample, params.max_samples);
559 }
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800560
561 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700562 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800563 "used send_vc %d\n", n);
564 }
565
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800566 if (n < 0)
567 goto fail;
568 if (n == 0)
569 goto next_ns;
570 resplen = n;
571 } else {
572 /* Use datagrams. */
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800573 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700574 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n");
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800575 }
576
Bernie Innocenti58d13622018-07-29 18:21:23 +0900577 n = send_dg(statp, &params, buf, buflen, ans, anssiz, &terrno,
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900578 ns, &v_circuit, &gotsomewhere, &now, &rcode, &delay);
579
Pierre Imai8b8611a2016-04-27 17:30:30 +0900580 /* Only record stats the first time we try a query. See above. */
581 if (try == 0) {
582 struct __res_sample sample;
583 _res_stats_set_sample(&sample, now, rcode, delay);
584 _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id,
585 ns, &sample, params.max_samples);
586 }
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900587
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800588 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700589 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n);
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800590 }
591
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800592 if (n < 0)
593 goto fail;
594 if (n == 0)
595 goto next_ns;
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800596 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700597 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900598 time(NULL));
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800599 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800600 if (v_circuit)
601 goto same_ns;
602 resplen = n;
603 }
604
605 Dprint((statp->options & RES_DEBUG) ||
606 ((statp->pfcode & RES_PRF_REPLY) &&
607 (statp->pfcode & RES_PRF_HEAD1)),
608 (stdout, ";; got answer:\n"));
609
610 DprintQ((statp->options & RES_DEBUG) ||
611 (statp->pfcode & RES_PRF_REPLY),
612 (stdout, "%s", ""),
613 ans, (resplen > anssiz) ? anssiz : resplen);
614
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900615 if (cache_status == RESOLV_CACHE_NOTFOUND) {
616 _resolv_cache_add(statp->netid, buf, buflen,
617 ans, resplen);
618 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800619 /*
620 * If we have temporarily opened a virtual circuit,
621 * or if we haven't been asked to keep a socket open,
622 * close the socket.
623 */
624 if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
625 (statp->options & RES_STAYOPEN) == 0U) {
626 res_nclose(statp);
627 }
628 if (statp->rhook) {
629 int done = 0, loops = 0;
630
631 do {
632 res_sendhookact act;
633
634 act = (*statp->rhook)(nsap, buf, buflen,
635 ans, anssiz, &resplen);
636 switch (act) {
637 case res_goahead:
638 case res_done:
639 done = 1;
640 break;
641 case res_nextns:
642 res_nclose(statp);
643 goto next_ns;
644 case res_modified:
645 /* give the hook another try */
646 if (++loops < 42) /*doug adams*/
647 break;
648 /*FALLTHROUGH*/
649 case res_error:
650 /*FALLTHROUGH*/
651 default:
652 goto fail;
653 }
654 } while (!done);
655
656 }
657 return (resplen);
658 next_ns: ;
659 } /*foreach ns*/
660 } /*foreach retry*/
661 res_nclose(statp);
662 if (!v_circuit) {
663 if (!gotsomewhere)
664 errno = ECONNREFUSED; /* no nameservers found */
665 else
666 errno = ETIMEDOUT; /* no answer obtained */
667 } else
668 errno = terrno;
Henrik Engströmce5ba8b2012-06-20 08:47:52 +0200669
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900670 _resolv_cache_query_failed(statp->netid, buf, buflen);
Henrik Engströmce5ba8b2012-06-20 08:47:52 +0200671
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800672 return (-1);
673 fail:
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900674
Paul Jensen41d9a502014-04-08 15:43:41 -0400675 _resolv_cache_query_failed(statp->netid, buf, buflen);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800676 res_nclose(statp);
677 return (-1);
678}
679
680/* Private */
681
682static int
Yi Kong7eeb11d2022-06-22 16:31:39 +0800683get_salen(const struct sockaddr *sa)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800684{
685
686#ifdef HAVE_SA_LEN
687 /* There are people do not set sa_len. Be forgiving to them. */
688 if (sa->sa_len)
689 return (sa->sa_len);
690#endif
691
692 if (sa->sa_family == AF_INET)
693 return (sizeof(struct sockaddr_in));
694 else if (sa->sa_family == AF_INET6)
695 return (sizeof(struct sockaddr_in6));
696 else
697 return (0); /* unknown, die on connect */
698}
699
700/*
701 * pick appropriate nsaddr_list for use. see res_init() for initialization.
702 */
703static struct sockaddr *
Yi Kong7eeb11d2022-06-22 16:31:39 +0800704get_nsaddr(res_state statp, size_t n)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800705{
706
707 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
708 /*
709 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
710 * than struct sockaddr, and
711 * - user code did not update statp->nsaddr_list[n].
712 */
713 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
714 } else {
715 /*
716 * - user code updated statp->nsaddr_list[n], or
717 * - statp->nsaddr_list[n] has the same content as
718 * EXT(statp).ext->nsaddrs[n].
719 */
720 return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
721 }
722}
723
Bernie Innocenti58d13622018-07-29 18:21:23 +0900724static struct timespec get_timeout(const res_state statp, const struct __res_params* params, const int ns)
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800725{
Bernie Innocenti58d13622018-07-29 18:21:23 +0900726 int msec;
727 if (params->base_timeout_msec != 0) {
728 // TODO: scale the timeout by retry attempt and maybe number of servers
729 msec = params->base_timeout_msec;
730 } else {
731 // Legacy algorithm which scales the timeout by nameserver number.
732 // For instance, with 4 nameservers: 5s, 2.5s, 5s, 10s
733 // This has no effect with 1 or 2 nameservers
734 msec = (statp->retrans * 1000) << ns;
735 if (ns > 0) {
736 msec /= statp->nscount;
737 }
738 if (msec < 1000) {
739 msec = 1000; // Use at least 100ms
740 }
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800741 }
742 if (DBG) {
Bernie Innocenti58d13622018-07-29 18:21:23 +0900743 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d msec\n", msec);
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800744 }
745
Bernie Innocenti58d13622018-07-29 18:21:23 +0900746 struct timespec result;
747 result.tv_sec = msec / 1000;
748 result.tv_nsec = (msec % 1000) * 1000000;
749 return result;
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800750}
751
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800752static int
Bernie Innocenti58d13622018-07-29 18:21:23 +0900753send_vc(res_state statp, struct __res_params* params,
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800754 const u_char *buf, int buflen, u_char *ans, int anssiz,
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900755 int *terrno, int ns, time_t* at, int* rcode, int* delay)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800756{
Pierre Imai8b8611a2016-04-27 17:30:30 +0900757 *at = time(NULL);
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900758 *rcode = RCODE_INTERNAL_ERROR;
759 *delay = 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800760 const HEADER *hp = (const HEADER *)(const void *)buf;
761 HEADER *anhp = (HEADER *)(void *)ans;
762 struct sockaddr *nsap;
763 int nsaplen;
764 int truncating, connreset, resplen, n;
765 struct iovec iov[2];
766 u_short len;
767 u_char *cp;
768 void *tmp;
769
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800770 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700771 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800772 }
773
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800774 nsap = get_nsaddr(statp, (size_t)ns);
775 nsaplen = get_salen(nsap);
776
777 connreset = 0;
778 same_ns:
779 truncating = 0;
780
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900781 struct timespec now = evNowTime();
782
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800783 /* Are we still talking to whom we want to talk to? */
784 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
785 struct sockaddr_storage peer;
786 socklen_t size = sizeof peer;
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500787 unsigned old_mark;
Elliott Hughes37b1b5b2014-07-02 16:27:20 -0700788 socklen_t mark_size = sizeof(old_mark);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800789 if (getpeername(statp->_vcsock,
790 (struct sockaddr *)(void *)&peer, &size) < 0 ||
Chad Brubakerc39214e2013-06-20 10:36:56 -0700791 !sock_eq((struct sockaddr *)(void *)&peer, nsap) ||
792 getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
793 old_mark != statp->_mark) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800794 res_nclose(statp);
795 statp->_flags &= ~RES_F_VC;
796 }
797 }
798
799 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
800 if (statp->_vcsock >= 0)
801 res_nclose(statp);
802
Nick Kralevich1781ed72014-06-29 20:46:17 -0700803 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800804 if (statp->_vcsock < 0) {
805 switch (errno) {
806 case EPROTONOSUPPORT:
807#ifdef EPFNOSUPPORT
808 case EPFNOSUPPORT:
809#endif
810 case EAFNOSUPPORT:
811 Perror(statp, stderr, "socket(vc)", errno);
812 return (0);
813 default:
814 *terrno = errno;
815 Perror(statp, stderr, "socket(vc)", errno);
816 return (-1);
817 }
818 }
Lorenzo Colitti5f027202018-05-01 16:19:01 +0900819 fchown(statp->_vcsock, AID_DNS, -1);
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500820 if (statp->_mark != MARK_UNSET) {
Chad Brubakerc39214e2013-06-20 10:36:56 -0700821 if (setsockopt(statp->_vcsock, SOL_SOCKET,
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900822 SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
Chad Brubakerc39214e2013-06-20 10:36:56 -0700823 *terrno = errno;
824 Perror(statp, stderr, "setsockopt", errno);
825 return -1;
826 }
827 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800828 errno = 0;
829 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
830 *terrno = errno;
831 Aerror(statp, stderr, "bind/vc", errno, nsap,
832 nsaplen);
833 res_nclose(statp);
834 return (0);
835 }
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800836 if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen,
Bernie Innocenti58d13622018-07-29 18:21:23 +0900837 get_timeout(statp, params, ns)) < 0) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800838 *terrno = errno;
839 Aerror(statp, stderr, "connect/vc", errno, nsap,
840 nsaplen);
841 res_nclose(statp);
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900842 /*
843 * The way connect_with_timeout() is implemented prevents us from reliably
844 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
845 * currently both cases are handled in the same way, there is no need to
846 * change this (yet). If we ever need to reliably distinguish between these
Bernie Innocentib6647242018-06-18 14:14:43 +0900847 * cases, both connect_with_timeout() and retrying_poll() need to be
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900848 * modified, though.
849 */
850 *rcode = RCODE_TIMEOUT;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800851 return (0);
852 }
853 statp->_flags |= RES_F_VC;
854 }
855
856 /*
857 * Send length & message
858 */
859 ns_put16((u_short)buflen, (u_char*)(void *)&len);
860 iov[0] = evConsIovec(&len, INT16SZ);
861 DE_CONST(buf, tmp);
862 iov[1] = evConsIovec(tmp, (size_t)buflen);
863 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
864 *terrno = errno;
865 Perror(statp, stderr, "write failed", errno);
866 res_nclose(statp);
867 return (0);
868 }
869 /*
870 * Receive length & response
871 */
872 read_len:
873 cp = ans;
874 len = INT16SZ;
875 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
876 cp += n;
877 if ((len -= n) == 0)
878 break;
879 }
880 if (n <= 0) {
881 *terrno = errno;
882 Perror(statp, stderr, "read failed", errno);
883 res_nclose(statp);
884 /*
885 * A long running process might get its TCP
886 * connection reset if the remote server was
887 * restarted. Requery the server instead of
888 * trying a new one. When there is only one
889 * server, this means that a query might work
890 * instead of failing. We only allow one reset
891 * per query to prevent looping.
892 */
893 if (*terrno == ECONNRESET && !connreset) {
894 connreset = 1;
895 res_nclose(statp);
896 goto same_ns;
897 }
898 res_nclose(statp);
899 return (0);
900 }
901 resplen = ns_get16(ans);
902 if (resplen > anssiz) {
903 Dprint(statp->options & RES_DEBUG,
904 (stdout, ";; response truncated\n")
905 );
906 truncating = 1;
907 len = anssiz;
908 } else
909 len = resplen;
910 if (len < HFIXEDSZ) {
911 /*
912 * Undersized message.
913 */
914 Dprint(statp->options & RES_DEBUG,
915 (stdout, ";; undersized: %d\n", len));
916 *terrno = EMSGSIZE;
917 res_nclose(statp);
918 return (0);
919 }
920 cp = ans;
921 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
922 cp += n;
923 len -= n;
924 }
925 if (n <= 0) {
926 *terrno = errno;
927 Perror(statp, stderr, "read(vc)", errno);
928 res_nclose(statp);
929 return (0);
930 }
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900931
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800932 if (truncating) {
933 /*
934 * Flush rest of answer so connection stays in synch.
935 */
936 anhp->tc = 1;
937 len = resplen - anssiz;
938 while (len != 0) {
939 char junk[PACKETSZ];
940
941 n = read(statp->_vcsock, junk,
942 (len > sizeof junk) ? sizeof junk : len);
943 if (n > 0)
944 len -= n;
945 else
946 break;
947 }
Ken Chen43264bc2020-08-07 19:04:25 +0800948 // return size should never exceed container size
949 resplen = anssiz;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800950 }
951 /*
952 * If the calling applicating has bailed out of
953 * a previous call and failed to arrange to have
954 * the circuit closed or the server has got
955 * itself confused, then drop the packet and
956 * wait for the correct one.
957 */
958 if (hp->id != anhp->id) {
959 DprintQ((statp->options & RES_DEBUG) ||
960 (statp->pfcode & RES_PRF_REPLY),
961 (stdout, ";; old answer (unexpected):\n"),
Ken Chen43264bc2020-08-07 19:04:25 +0800962 ans, resplen);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800963 goto read_len;
964 }
965
966 /*
967 * All is well, or the error is fatal. Signal that the
968 * next nameserver ought not be tried.
969 */
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900970 if (resplen > 0) {
Pierre Imai8b8611a2016-04-27 17:30:30 +0900971 struct timespec done = evNowTime();
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900972 *delay = _res_stats_calculate_rtt(&done, &now);
973 *rcode = anhp->rcode;
974 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800975 return (resplen);
976}
977
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800978/* return -1 on error (errno set), 0 on success */
979static int
Bernie Innocenti58d13622018-07-29 18:21:23 +0900980connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen,
981 const struct timespec timeout)
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800982{
983 int res, origflags;
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800984
985 origflags = fcntl(sock, F_GETFL, 0);
986 fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
987
Paul Jensen31ad0372014-05-29 16:28:30 -0400988 res = __connect(sock, nsap, salen);
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800989 if (res < 0 && errno != EINPROGRESS) {
Pierre Imai6b3f0d62016-02-22 17:50:41 +0900990 res = -1;
991 goto done;
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800992 }
993 if (res != 0) {
Bernie Innocentib6647242018-06-18 14:14:43 +0900994 struct timespec now = evNowTime();
Bernie Innocentib6647242018-06-18 14:14:43 +0900995 struct timespec finish = evAddTime(now, timeout);
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800996 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -0700997 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", " %d send_vc\n", sock);
Robert Greenwaltecd0e952012-01-11 10:04:48 -0800998 }
999
Bernie Innocentib6647242018-06-18 14:14:43 +09001000 res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001001 if (res <= 0) {
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001002 res = -1;
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001003 }
1004 }
1005done:
1006 fcntl(sock, F_SETFL, origflags);
1007 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -07001008 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
Bernie Innocenti58d13622018-07-29 18:21:23 +09001009 " %d connect_with_const timeout returning %d\n", sock, res);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001010 }
1011 return res;
1012}
1013
1014static int
Bernie Innocentib6647242018-06-18 14:14:43 +09001015retrying_poll(const int sock, const short events, const struct timespec* finish) {
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001016 struct timespec now, timeout;
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001017
1018retry:
1019 if (DBG) {
Bernie Innocentib6647242018-06-18 14:14:43 +09001020 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", " %d retrying_poll\n", sock);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001021 }
1022
1023 now = evNowTime();
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001024 if (evCmpTime(*finish, now) > 0)
1025 timeout = evSubTime(*finish, now);
1026 else
1027 timeout = evConsTime(0L, 0L);
Bernie Innocentib6647242018-06-18 14:14:43 +09001028 struct pollfd fds = { .fd = sock, .events = events };
1029 int n = ppoll(&fds, 1, &timeout, /*sigmask=*/NULL);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001030 if (n == 0) {
1031 if (DBG) {
Bernie Innocenti58d13622018-07-29 18:21:23 +09001032 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
Bernie Innocentib6647242018-06-18 14:14:43 +09001033 " %d retrying_poll timeout\n", sock);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001034 }
1035 errno = ETIMEDOUT;
1036 return 0;
1037 }
1038 if (n < 0) {
1039 if (errno == EINTR)
1040 goto retry;
1041 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -07001042 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
Bernie Innocentib6647242018-06-18 14:14:43 +09001043 " %d retrying_poll got error %d\n",sock, n);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001044 }
1045 return n;
1046 }
Bernie Innocentib6647242018-06-18 14:14:43 +09001047 if (fds.revents & (POLLIN | POLLOUT | POLLERR)) {
1048 int error;
1049 socklen_t len = sizeof(error);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001050 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
1051 errno = error;
1052 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -07001053 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
Bernie Innocentib6647242018-06-18 14:14:43 +09001054 " %d retrying_poll dot error2 %d\n", sock, errno);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001055 }
1056
1057 return -1;
1058 }
1059 }
1060 if (DBG) {
Christopher Ferris7a3681e2017-04-24 17:48:32 -07001061 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
Bernie Innocentib6647242018-06-18 14:14:43 +09001062 " %d retrying_poll returning %d\n",sock, n);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001063 }
1064
1065 return n;
1066}
1067
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001068static int
Bernie Innocenti58d13622018-07-29 18:21:23 +09001069send_dg(res_state statp, struct __res_params* params,
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001070 const u_char *buf, int buflen, u_char *ans, int anssiz,
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001071 int *terrno, int ns, int *v_circuit, int *gotsomewhere,
1072 time_t *at, int *rcode, int* delay)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001073{
Pierre Imai8b8611a2016-04-27 17:30:30 +09001074 *at = time(NULL);
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001075 *rcode = RCODE_INTERNAL_ERROR;
1076 *delay = 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001077 const HEADER *hp = (const HEADER *)(const void *)buf;
1078 HEADER *anhp = (HEADER *)(void *)ans;
1079 const struct sockaddr *nsap;
1080 int nsaplen;
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001081 struct timespec now, timeout, finish, done;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001082 struct sockaddr_storage from;
1083 socklen_t fromlen;
Bernie Innocenti58d13622018-07-29 18:21:23 +09001084 int resplen, n, s;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001085
1086 nsap = get_nsaddr(statp, (size_t)ns);
1087 nsaplen = get_salen(nsap);
1088 if (EXT(statp).nssocks[ns] == -1) {
Nick Kralevich1781ed72014-06-29 20:46:17 -07001089 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001090 if (EXT(statp).nssocks[ns] < 0) {
1091 switch (errno) {
1092 case EPROTONOSUPPORT:
1093#ifdef EPFNOSUPPORT
1094 case EPFNOSUPPORT:
1095#endif
1096 case EAFNOSUPPORT:
1097 Perror(statp, stderr, "socket(dg)", errno);
1098 return (0);
1099 default:
1100 *terrno = errno;
1101 Perror(statp, stderr, "socket(dg)", errno);
1102 return (-1);
1103 }
1104 }
Chad Brubakerc39214e2013-06-20 10:36:56 -07001105
Lorenzo Colitti5f027202018-05-01 16:19:01 +09001106 fchown(EXT(statp).nssocks[ns], AID_DNS, -1);
Szymon Jakubczakea9bf672014-02-14 17:07:23 -05001107 if (statp->_mark != MARK_UNSET) {
Chad Brubakerc39214e2013-06-20 10:36:56 -07001108 if (setsockopt(EXT(statp).nssocks[ns], SOL_SOCKET,
1109 SO_MARK, &(statp->_mark), sizeof(statp->_mark)) < 0) {
1110 res_nclose(statp);
1111 return -1;
1112 }
1113 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001114#ifndef CANNOT_CONNECT_DGRAM
1115 /*
1116 * On a 4.3BSD+ machine (client and server,
1117 * actually), sending to a nameserver datagram
1118 * port with no nameserver will cause an
1119 * ICMP port unreachable message to be returned.
1120 * If our datagram socket is "connected" to the
1121 * server, we get an ECONNREFUSED error on the next
1122 * socket operation, and select returns if the
1123 * error message is received. We can thus detect
1124 * the absence of a nameserver without timing out.
1125 */
1126 if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
1127 Aerror(statp, stderr, "bind(dg)", errno, nsap,
1128 nsaplen);
1129 res_nclose(statp);
1130 return (0);
1131 }
Paul Jensen31ad0372014-05-29 16:28:30 -04001132 if (__connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001133 Aerror(statp, stderr, "connect(dg)", errno, nsap,
1134 nsaplen);
1135 res_nclose(statp);
1136 return (0);
1137 }
1138#endif /* !CANNOT_CONNECT_DGRAM */
1139 Dprint(statp->options & RES_DEBUG,
1140 (stdout, ";; new DG socket\n"))
Chad Brubakerc39214e2013-06-20 10:36:56 -07001141
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001142 }
1143 s = EXT(statp).nssocks[ns];
1144#ifndef CANNOT_CONNECT_DGRAM
1145 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
1146 Perror(statp, stderr, "send", errno);
1147 res_nclose(statp);
1148 return (0);
1149 }
1150#else /* !CANNOT_CONNECT_DGRAM */
1151 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
1152 {
1153 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
1154 res_nclose(statp);
1155 return (0);
1156 }
1157#endif /* !CANNOT_CONNECT_DGRAM */
1158
1159 /*
1160 * Wait for reply.
1161 */
Bernie Innocenti58d13622018-07-29 18:21:23 +09001162 timeout = get_timeout(statp, params, ns);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001163 now = evNowTime();
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001164 finish = evAddTime(now, timeout);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001165retry:
Bernie Innocentib6647242018-06-18 14:14:43 +09001166 n = retrying_poll(s, POLLIN, &finish);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001167
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001168 if (n == 0) {
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001169 *rcode = RCODE_TIMEOUT;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001170 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1171 *gotsomewhere = 1;
1172 return (0);
1173 }
1174 if (n < 0) {
Bernie Innocentib6647242018-06-18 14:14:43 +09001175 Perror(statp, stderr, "poll", errno);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001176 res_nclose(statp);
1177 return (0);
1178 }
1179 errno = 0;
1180 fromlen = sizeof(from);
1181 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
1182 (struct sockaddr *)(void *)&from, &fromlen);
1183 if (resplen <= 0) {
1184 Perror(statp, stderr, "recvfrom", errno);
1185 res_nclose(statp);
1186 return (0);
1187 }
1188 *gotsomewhere = 1;
1189 if (resplen < HFIXEDSZ) {
1190 /*
1191 * Undersized message.
1192 */
1193 Dprint(statp->options & RES_DEBUG,
1194 (stdout, ";; undersized: %d\n",
1195 resplen));
1196 *terrno = EMSGSIZE;
1197 res_nclose(statp);
1198 return (0);
1199 }
1200 if (hp->id != anhp->id) {
1201 /*
1202 * response from old query, ignore it.
1203 * XXX - potential security hazard could
1204 * be detected here.
1205 */
1206 DprintQ((statp->options & RES_DEBUG) ||
1207 (statp->pfcode & RES_PRF_REPLY),
1208 (stdout, ";; old answer:\n"),
1209 ans, (resplen > anssiz) ? anssiz : resplen);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001210 goto retry;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001211 }
1212 if (!(statp->options & RES_INSECURE1) &&
1213 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
1214 /*
1215 * response from wrong server? ignore it.
1216 * XXX - potential security hazard could
1217 * be detected here.
1218 */
1219 DprintQ((statp->options & RES_DEBUG) ||
1220 (statp->pfcode & RES_PRF_REPLY),
1221 (stdout, ";; not our server:\n"),
1222 ans, (resplen > anssiz) ? anssiz : resplen);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001223 goto retry;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001224 }
1225#ifdef RES_USE_EDNS0
1226 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1227 /*
1228 * Do not retry if the server do not understand EDNS0.
1229 * The case has to be captured here, as FORMERR packet do not
1230 * carry query section, hence res_queriesmatch() returns 0.
1231 */
1232 DprintQ(statp->options & RES_DEBUG,
1233 (stdout, "server rejected query with EDNS0:\n"),
1234 ans, (resplen > anssiz) ? anssiz : resplen);
1235 /* record the error */
1236 statp->_flags |= RES_F_EDNS0ERR;
1237 res_nclose(statp);
1238 return (0);
1239 }
1240#endif
1241 if (!(statp->options & RES_INSECURE2) &&
1242 !res_queriesmatch(buf, buf + buflen,
1243 ans, ans + anssiz)) {
1244 /*
1245 * response contains wrong query? ignore it.
1246 * XXX - potential security hazard could
1247 * be detected here.
1248 */
1249 DprintQ((statp->options & RES_DEBUG) ||
1250 (statp->pfcode & RES_PRF_REPLY),
1251 (stdout, ";; wrong query name:\n"),
1252 ans, (resplen > anssiz) ? anssiz : resplen);
Robert Greenwaltecd0e952012-01-11 10:04:48 -08001253 goto retry;;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001254 }
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001255 done = evNowTime();
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001256 *delay = _res_stats_calculate_rtt(&done, &now);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001257 if (anhp->rcode == SERVFAIL ||
1258 anhp->rcode == NOTIMP ||
1259 anhp->rcode == REFUSED) {
1260 DprintQ(statp->options & RES_DEBUG,
1261 (stdout, "server rejected query:\n"),
1262 ans, (resplen > anssiz) ? anssiz : resplen);
1263 res_nclose(statp);
1264 /* don't retry if called from dig */
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001265 if (!statp->pfcode) {
1266 *rcode = anhp->rcode;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001267 return (0);
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001268 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001269 }
1270 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1271 /*
1272 * To get the rest of answer,
1273 * use TCP with same server.
1274 */
1275 Dprint(statp->options & RES_DEBUG,
1276 (stdout, ";; truncated answer\n"));
1277 *v_circuit = 1;
1278 res_nclose(statp);
1279 return (1);
1280 }
1281 /*
1282 * All is well, or the error is fatal. Signal that the
1283 * next nameserver ought not be tried.
1284 */
Pierre Imai6b3f0d62016-02-22 17:50:41 +09001285 if (resplen > 0) {
1286 *rcode = anhp->rcode;
1287 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001288 return (resplen);
1289}
1290
1291static void
1292Aerror(const res_state statp, FILE *file, const char *string, int error,
1293 const struct sockaddr *address, int alen)
1294{
1295 int save = errno;
1296 char hbuf[NI_MAXHOST];
1297 char sbuf[NI_MAXSERV];
1298
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001299 if ((statp->options & RES_DEBUG) != 0U) {
1300 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1301 sbuf, sizeof(sbuf), niflags)) {
1302 strncpy(hbuf, "?", sizeof(hbuf) - 1);
1303 hbuf[sizeof(hbuf) - 1] = '\0';
1304 strncpy(sbuf, "?", sizeof(sbuf) - 1);
1305 sbuf[sizeof(sbuf) - 1] = '\0';
1306 }
1307 fprintf(file, "res_send: %s ([%s].%s): %s\n",
1308 string, hbuf, sbuf, strerror(error));
1309 }
1310 errno = save;
1311}
1312
1313static void
1314Perror(const res_state statp, FILE *file, const char *string, int error) {
1315 int save = errno;
1316
1317 if ((statp->options & RES_DEBUG) != 0U)
1318 fprintf(file, "res_send: %s: %s\n",
1319 string, strerror(error));
1320 errno = save;
1321}
1322
1323static int
1324sock_eq(struct sockaddr *a, struct sockaddr *b) {
1325 struct sockaddr_in *a4, *b4;
1326 struct sockaddr_in6 *a6, *b6;
1327
1328 if (a->sa_family != b->sa_family)
1329 return 0;
1330 switch (a->sa_family) {
1331 case AF_INET:
1332 a4 = (struct sockaddr_in *)(void *)a;
1333 b4 = (struct sockaddr_in *)(void *)b;
1334 return a4->sin_port == b4->sin_port &&
1335 a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1336 case AF_INET6:
1337 a6 = (struct sockaddr_in6 *)(void *)a;
1338 b6 = (struct sockaddr_in6 *)(void *)b;
1339 return a6->sin6_port == b6->sin6_port &&
1340#ifdef HAVE_SIN6_SCOPE_ID
1341 a6->sin6_scope_id == b6->sin6_scope_id &&
1342#endif
1343 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1344 default:
1345 return 0;
1346 }
1347}