1 /* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */
2
3 /*
4 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 /*
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 */
55
56 /*
57 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
58 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
59 *
60 * Permission to use, copy, modify, and distribute this software for any
61 * purpose with or without fee is hereby granted, provided that the above
62 * copyright notice and this permission notice appear in all copies.
63 *
64 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
65 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
66 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
67 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
68 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
69 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
70 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
71 */
72
73 #include <sys/cdefs.h>
74 #if defined(LIBC_SCCS) && !defined(lint)
75 #ifdef notdef
76 static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
77 static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp";
78 #else
79 __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
80 #endif
81 #endif /* LIBC_SCCS and not lint */
82
83 /*
84 * Send query to name server and wait for reply.
85 */
86
87 #include <sys/types.h>
88 #include <sys/param.h>
89 #include <sys/time.h>
90 #include <sys/socket.h>
91 #include <sys/uio.h>
92
93 #include <netinet/in.h>
94 #include <arpa/nameser.h>
95 #include <arpa/inet.h>
96
97 #include <errno.h>
98 #include <fcntl.h>
99 #include <netdb.h>
100 #include <poll.h>
101 #ifdef ANDROID_CHANGES
102 #include "resolv_netid.h"
103 #include "resolv_private.h"
104 #include "private/android_filesystem_config.h"
105 #else
106 #include <resolv.h>
107 #endif
108 #include <signal.h>
109 #include <stdio.h>
110 #include <stdlib.h>
111 #include <string.h>
112 #include <time.h>
113 #include <unistd.h>
114
115 #include <isc/eventlib.h>
116
117 #include <resolv_cache.h>
118
119 #include <async_safe/log.h>
120
121 #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"
132 #include "resolv_stats.h"
133
134 #define EXT(res) ((res)->_u._ext)
135 #define DBG 0
136
137 /* Forward. */
138
139 static int get_salen __P((const struct sockaddr *));
140 static struct sockaddr * get_nsaddr __P((res_state, size_t));
141 static int send_vc(res_state, struct __res_params *params, const u_char *, int,
142 u_char *, int, int *, int, time_t *, int *, int *);
143 static 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 *);
145 static void Aerror(const res_state, FILE *, const char *, int,
146 const struct sockaddr *, int);
147 static void Perror(const res_state, FILE *, const char *, int);
148 static int sock_eq(struct sockaddr *, struct sockaddr *);
149 void res_pquery(const res_state, const u_char *, int, FILE *);
150 static int connect_with_timeout(int sock, const struct sockaddr *nsap,
151 socklen_t salen, const struct timespec timeout);
152 static int retrying_poll(const int sock, short events, const struct timespec* finish);
153
154 /* BIONIC-BEGIN: implement source port randomization */
155 typedef union {
156 struct sockaddr sa;
157 struct sockaddr_in sin;
158 struct sockaddr_in6 sin6;
159 } _sockaddr_union;
160
161 static int
random_bind(int s,int family)162 random_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
209 static 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 */
222 __LIBC_HIDDEN__ int
res_ourserver_p(const res_state statp,const struct sockaddr * sa)223 res_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 */
275 int
res_nameinquery(const char * name,int type,int class,const u_char * buf,const u_char * eom)276 res_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 */
312 int
res_queriesmatch(const u_char * buf1,const u_char * eom1,const u_char * buf2,const u_char * eom2)313 res_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
350 int
res_nsend(res_state statp,const u_char * buf,int buflen,u_char * ans,int anssiz)351 res_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];
356 ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;
357
358 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
368 int anslen = 0;
369 cache_status = _resolv_cache_lookup(
370 statp->netid, buf, buflen,
371 ans, anssiz, &anslen);
372
373 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);
379 }
380 if (statp->nscount == 0) {
381 // 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);
385 errno = ESRCH;
386 return (-1);
387 }
388
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
398 if (EXT(statp).nscount != statp->nscount) {
399 needclose++;
400 } else {
401 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);
412 if (getpeername(EXT(statp).nssocks[ns],
413 (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 }
423 }
424 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)
464 EXT(statp).ext->nsaddrs[ns] =
465 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++) {
481 struct __res_stats stats[MAXNS];
482 struct __res_params params;
483 int revision_id = _resolv_cache_get_resolver_stats(statp->netid, ¶ms, stats);
484 bool usable_servers[MAXNS];
485 android_net_res_stats_get_usable_servers(¶ms, stats, statp->nscount,
486 usable_servers);
487
488 for (ns = 0; ns < statp->nscount; ns++) {
489 if (!usable_servers[ns]) continue;
490 struct sockaddr *nsap;
491 int nsaplen;
492 time_t now = 0;
493 int rcode = RCODE_INTERNAL_ERROR;
494 int delay = 0;
495 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);
499
500 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:
517 if (cache_status == RESOLV_CACHE_NOTFOUND) {
518 _resolv_cache_add(statp->netid, buf, buflen,
519 ans, resplen);
520 }
521 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),
537 NULL, 0, niflags) == 0),
538 (stdout, ";; Querying server (# %d) address = %s\n",
539 ns + 1, abuf));
540
541
542 if (v_circuit) {
543 /* Use VC; at most one attempt per server. */
544 try = statp->retry;
545
546 n = send_vc(statp, ¶ms, buf, buflen, ans, anssiz, &terrno,
547 ns, &now, &rcode, &delay);
548
549 /*
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 }
560
561 if (DBG) {
562 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
563 "used send_vc %d\n", n);
564 }
565
566 if (n < 0)
567 goto fail;
568 if (n == 0)
569 goto next_ns;
570 resplen = n;
571 } else {
572 /* Use datagrams. */
573 if (DBG) {
574 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n");
575 }
576
577 n = send_dg(statp, ¶ms, buf, buflen, ans, anssiz, &terrno,
578 ns, &v_circuit, &gotsomewhere, &now, &rcode, &delay);
579
580 /* 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 }
587
588 if (DBG) {
589 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n);
590 }
591
592 if (n < 0)
593 goto fail;
594 if (n == 0)
595 goto next_ns;
596 if (DBG) {
597 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
598 time(NULL));
599 }
600 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
615 if (cache_status == RESOLV_CACHE_NOTFOUND) {
616 _resolv_cache_add(statp->netid, buf, buflen,
617 ans, resplen);
618 }
619 /*
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;
669
670 _resolv_cache_query_failed(statp->netid, buf, buflen);
671
672 return (-1);
673 fail:
674
675 _resolv_cache_query_failed(statp->netid, buf, buflen);
676 res_nclose(statp);
677 return (-1);
678 }
679
680 /* Private */
681
682 static int
get_salen(const struct sockaddr * sa)683 get_salen(const struct sockaddr *sa)
684 {
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 */
703 static struct sockaddr *
get_nsaddr(res_state statp,size_t n)704 get_nsaddr(res_state statp, size_t n)
705 {
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
get_timeout(const res_state statp,const struct __res_params * params,const int ns)724 static struct timespec get_timeout(const res_state statp, const struct __res_params* params, const int ns)
725 {
726 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 }
741 }
742 if (DBG) {
743 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d msec\n", msec);
744 }
745
746 struct timespec result;
747 result.tv_sec = msec / 1000;
748 result.tv_nsec = (msec % 1000) * 1000000;
749 return result;
750 }
751
752 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 send_vc(res_state statp, struct __res_params* params,
754 const u_char *buf, int buflen, u_char *ans, int anssiz,
755 int *terrno, int ns, time_t* at, int* rcode, int* delay)
756 {
757 *at = time(NULL);
758 *rcode = RCODE_INTERNAL_ERROR;
759 *delay = 0;
760 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
770 if (DBG) {
771 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
772 }
773
774 nsap = get_nsaddr(statp, (size_t)ns);
775 nsaplen = get_salen(nsap);
776
777 connreset = 0;
778 same_ns:
779 truncating = 0;
780
781 struct timespec now = evNowTime();
782
783 /* 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;
787 unsigned old_mark;
788 socklen_t mark_size = sizeof(old_mark);
789 if (getpeername(statp->_vcsock,
790 (struct sockaddr *)(void *)&peer, &size) < 0 ||
791 !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) {
794 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
803 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
804 if (statp->_vcsock < 0) {
805 switch (errno) {
806 case EPROTONOSUPPORT:
807 #ifdef EPFNOSUPPORT
808 case EPFNOSUPPORT:
809 #endif
810 case EAFNOSUPPORT:
811 Perror(statp, stderr, "socket(vc)", errno);
812 return (0);
813 default:
814 *terrno = errno;
815 Perror(statp, stderr, "socket(vc)", errno);
816 return (-1);
817 }
818 }
819 fchown(statp->_vcsock, AID_DNS, -1);
820 if (statp->_mark != MARK_UNSET) {
821 if (setsockopt(statp->_vcsock, SOL_SOCKET,
822 SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
823 *terrno = errno;
824 Perror(statp, stderr, "setsockopt", errno);
825 return -1;
826 }
827 }
828 errno = 0;
829 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
830 *terrno = errno;
831 Aerror(statp, stderr, "bind/vc", errno, nsap,
832 nsaplen);
833 res_nclose(statp);
834 return (0);
835 }
836 if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen,
837 get_timeout(statp, params, ns)) < 0) {
838 *terrno = errno;
839 Aerror(statp, stderr, "connect/vc", errno, nsap,
840 nsaplen);
841 res_nclose(statp);
842 /*
843 * The way connect_with_timeout() is implemented prevents us from reliably
844 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
845 * currently both cases are handled in the same way, there is no need to
846 * change this (yet). If we ever need to reliably distinguish between these
847 * cases, both connect_with_timeout() and retrying_poll() need to be
848 * modified, though.
849 */
850 *rcode = RCODE_TIMEOUT;
851 return (0);
852 }
853 statp->_flags |= RES_F_VC;
854 }
855
856 /*
857 * Send length & message
858 */
859 ns_put16((u_short)buflen, (u_char*)(void *)&len);
860 iov[0] = evConsIovec(&len, INT16SZ);
861 DE_CONST(buf, tmp);
862 iov[1] = evConsIovec(tmp, (size_t)buflen);
863 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
864 *terrno = errno;
865 Perror(statp, stderr, "write failed", errno);
866 res_nclose(statp);
867 return (0);
868 }
869 /*
870 * Receive length & response
871 */
872 read_len:
873 cp = ans;
874 len = INT16SZ;
875 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
876 cp += n;
877 if ((len -= n) == 0)
878 break;
879 }
880 if (n <= 0) {
881 *terrno = errno;
882 Perror(statp, stderr, "read failed", errno);
883 res_nclose(statp);
884 /*
885 * A long running process might get its TCP
886 * connection reset if the remote server was
887 * restarted. Requery the server instead of
888 * trying a new one. When there is only one
889 * server, this means that a query might work
890 * instead of failing. We only allow one reset
891 * per query to prevent looping.
892 */
893 if (*terrno == ECONNRESET && !connreset) {
894 connreset = 1;
895 res_nclose(statp);
896 goto same_ns;
897 }
898 res_nclose(statp);
899 return (0);
900 }
901 resplen = ns_get16(ans);
902 if (resplen > anssiz) {
903 Dprint(statp->options & RES_DEBUG,
904 (stdout, ";; response truncated\n")
905 );
906 truncating = 1;
907 len = anssiz;
908 } else
909 len = resplen;
910 if (len < HFIXEDSZ) {
911 /*
912 * Undersized message.
913 */
914 Dprint(statp->options & RES_DEBUG,
915 (stdout, ";; undersized: %d\n", len));
916 *terrno = EMSGSIZE;
917 res_nclose(statp);
918 return (0);
919 }
920 cp = ans;
921 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
922 cp += n;
923 len -= n;
924 }
925 if (n <= 0) {
926 *terrno = errno;
927 Perror(statp, stderr, "read(vc)", errno);
928 res_nclose(statp);
929 return (0);
930 }
931
932 if (truncating) {
933 /*
934 * Flush rest of answer so connection stays in synch.
935 */
936 anhp->tc = 1;
937 len = resplen - anssiz;
938 while (len != 0) {
939 char junk[PACKETSZ];
940
941 n = read(statp->_vcsock, junk,
942 (len > sizeof junk) ? sizeof junk : len);
943 if (n > 0)
944 len -= n;
945 else
946 break;
947 }
948 // return size should never exceed container size
949 resplen = anssiz;
950 }
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"),
962 ans, resplen);
963 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 */
970 if (resplen > 0) {
971 struct timespec done = evNowTime();
972 *delay = _res_stats_calculate_rtt(&done, &now);
973 *rcode = anhp->rcode;
974 }
975 return (resplen);
976 }
977
978 /* return -1 on error (errno set), 0 on success */
979 static int
connect_with_timeout(int sock,const struct sockaddr * nsap,socklen_t salen,const struct timespec timeout)980 connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen,
981 const struct timespec timeout)
982 {
983 int res, origflags;
984
985 origflags = fcntl(sock, F_GETFL, 0);
986 fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
987
988 res = __connect(sock, nsap, salen);
989 if (res < 0 && errno != EINPROGRESS) {
990 res = -1;
991 goto done;
992 }
993 if (res != 0) {
994 struct timespec now = evNowTime();
995 struct timespec finish = evAddTime(now, timeout);
996 if (DBG) {
997 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", " %d send_vc\n", sock);
998 }
999
1000 res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
1001 if (res <= 0) {
1002 res = -1;
1003 }
1004 }
1005 done:
1006 fcntl(sock, F_SETFL, origflags);
1007 if (DBG) {
1008 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1009 " %d connect_with_const timeout returning %d\n", sock, res);
1010 }
1011 return res;
1012 }
1013
1014 static int
retrying_poll(const int sock,const short events,const struct timespec * finish)1015 retrying_poll(const int sock, const short events, const struct timespec* finish) {
1016 struct timespec now, timeout;
1017
1018 retry:
1019 if (DBG) {
1020 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", " %d retrying_poll\n", sock);
1021 }
1022
1023 now = evNowTime();
1024 if (evCmpTime(*finish, now) > 0)
1025 timeout = evSubTime(*finish, now);
1026 else
1027 timeout = evConsTime(0L, 0L);
1028 struct pollfd fds = { .fd = sock, .events = events };
1029 int n = ppoll(&fds, 1, &timeout, /*sigmask=*/NULL);
1030 if (n == 0) {
1031 if (DBG) {
1032 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1033 " %d retrying_poll timeout\n", sock);
1034 }
1035 errno = ETIMEDOUT;
1036 return 0;
1037 }
1038 if (n < 0) {
1039 if (errno == EINTR)
1040 goto retry;
1041 if (DBG) {
1042 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1043 " %d retrying_poll got error %d\n",sock, n);
1044 }
1045 return n;
1046 }
1047 if (fds.revents & (POLLIN | POLLOUT | POLLERR)) {
1048 int error;
1049 socklen_t len = sizeof(error);
1050 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
1051 errno = error;
1052 if (DBG) {
1053 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1054 " %d retrying_poll dot error2 %d\n", sock, errno);
1055 }
1056
1057 return -1;
1058 }
1059 }
1060 if (DBG) {
1061 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1062 " %d retrying_poll returning %d\n",sock, n);
1063 }
1064
1065 return n;
1066 }
1067
1068 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 send_dg(res_state statp, struct __res_params* params,
1070 const u_char *buf, int buflen, u_char *ans, int anssiz,
1071 int *terrno, int ns, int *v_circuit, int *gotsomewhere,
1072 time_t *at, int *rcode, int* delay)
1073 {
1074 *at = time(NULL);
1075 *rcode = RCODE_INTERNAL_ERROR;
1076 *delay = 0;
1077 const HEADER *hp = (const HEADER *)(const void *)buf;
1078 HEADER *anhp = (HEADER *)(void *)ans;
1079 const struct sockaddr *nsap;
1080 int nsaplen;
1081 struct timespec now, timeout, finish, done;
1082 struct sockaddr_storage from;
1083 socklen_t fromlen;
1084 int resplen, n, s;
1085
1086 nsap = get_nsaddr(statp, (size_t)ns);
1087 nsaplen = get_salen(nsap);
1088 if (EXT(statp).nssocks[ns] == -1) {
1089 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1090 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 }
1105
1106 fchown(EXT(statp).nssocks[ns], AID_DNS, -1);
1107 if (statp->_mark != MARK_UNSET) {
1108 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 }
1114 #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 }
1132 if (__connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
1133 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"))
1141
1142 }
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 */
1162 timeout = get_timeout(statp, params, ns);
1163 now = evNowTime();
1164 finish = evAddTime(now, timeout);
1165 retry:
1166 n = retrying_poll(s, POLLIN, &finish);
1167
1168 if (n == 0) {
1169 *rcode = RCODE_TIMEOUT;
1170 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1171 *gotsomewhere = 1;
1172 return (0);
1173 }
1174 if (n < 0) {
1175 Perror(statp, stderr, "poll", errno);
1176 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);
1210 goto retry;
1211 }
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);
1223 goto retry;
1224 }
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);
1253 goto retry;;
1254 }
1255 done = evNowTime();
1256 *delay = _res_stats_calculate_rtt(&done, &now);
1257 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 */
1265 if (!statp->pfcode) {
1266 *rcode = anhp->rcode;
1267 return (0);
1268 }
1269 }
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 */
1285 if (resplen > 0) {
1286 *rcode = anhp->rcode;
1287 }
1288 return (resplen);
1289 }
1290
1291 static void
Aerror(const res_state statp,FILE * file,const char * string,int error,const struct sockaddr * address,int alen)1292 Aerror(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
1299 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
1313 static void
Perror(const res_state statp,FILE * file,const char * string,int error)1314 Perror(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
1323 static int
sock_eq(struct sockaddr * a,struct sockaddr * b)1324 sock_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 }
1348