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(sa)683 get_salen(sa)
684 const struct sockaddr *sa;
685 {
686
687 #ifdef HAVE_SA_LEN
688 /* There are people do not set sa_len. Be forgiving to them. */
689 if (sa->sa_len)
690 return (sa->sa_len);
691 #endif
692
693 if (sa->sa_family == AF_INET)
694 return (sizeof(struct sockaddr_in));
695 else if (sa->sa_family == AF_INET6)
696 return (sizeof(struct sockaddr_in6));
697 else
698 return (0); /* unknown, die on connect */
699 }
700
701 /*
702 * pick appropriate nsaddr_list for use. see res_init() for initialization.
703 */
704 static struct sockaddr *
get_nsaddr(statp,n)705 get_nsaddr(statp, n)
706 res_state statp;
707 size_t n;
708 {
709
710 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
711 /*
712 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
713 * than struct sockaddr, and
714 * - user code did not update statp->nsaddr_list[n].
715 */
716 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
717 } else {
718 /*
719 * - user code updated statp->nsaddr_list[n], or
720 * - statp->nsaddr_list[n] has the same content as
721 * EXT(statp).ext->nsaddrs[n].
722 */
723 return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
724 }
725 }
726
get_timeout(const res_state statp,const struct __res_params * params,const int ns)727 static struct timespec get_timeout(const res_state statp, const struct __res_params* params, const int ns)
728 {
729 int msec;
730 if (params->base_timeout_msec != 0) {
731 // TODO: scale the timeout by retry attempt and maybe number of servers
732 msec = params->base_timeout_msec;
733 } else {
734 // Legacy algorithm which scales the timeout by nameserver number.
735 // For instance, with 4 nameservers: 5s, 2.5s, 5s, 10s
736 // This has no effect with 1 or 2 nameservers
737 msec = (statp->retrans * 1000) << ns;
738 if (ns > 0) {
739 msec /= statp->nscount;
740 }
741 if (msec < 1000) {
742 msec = 1000; // Use at least 100ms
743 }
744 }
745 if (DBG) {
746 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d msec\n", msec);
747 }
748
749 struct timespec result;
750 result.tv_sec = msec / 1000;
751 result.tv_nsec = (msec % 1000) * 1000000;
752 return result;
753 }
754
755 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)756 send_vc(res_state statp, struct __res_params* params,
757 const u_char *buf, int buflen, u_char *ans, int anssiz,
758 int *terrno, int ns, time_t* at, int* rcode, int* delay)
759 {
760 *at = time(NULL);
761 *rcode = RCODE_INTERNAL_ERROR;
762 *delay = 0;
763 const HEADER *hp = (const HEADER *)(const void *)buf;
764 HEADER *anhp = (HEADER *)(void *)ans;
765 struct sockaddr *nsap;
766 int nsaplen;
767 int truncating, connreset, resplen, n;
768 struct iovec iov[2];
769 u_short len;
770 u_char *cp;
771 void *tmp;
772
773 if (DBG) {
774 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
775 }
776
777 nsap = get_nsaddr(statp, (size_t)ns);
778 nsaplen = get_salen(nsap);
779
780 connreset = 0;
781 same_ns:
782 truncating = 0;
783
784 struct timespec now = evNowTime();
785
786 /* Are we still talking to whom we want to talk to? */
787 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
788 struct sockaddr_storage peer;
789 socklen_t size = sizeof peer;
790 unsigned old_mark;
791 socklen_t mark_size = sizeof(old_mark);
792 if (getpeername(statp->_vcsock,
793 (struct sockaddr *)(void *)&peer, &size) < 0 ||
794 !sock_eq((struct sockaddr *)(void *)&peer, nsap) ||
795 getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
796 old_mark != statp->_mark) {
797 res_nclose(statp);
798 statp->_flags &= ~RES_F_VC;
799 }
800 }
801
802 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
803 if (statp->_vcsock >= 0)
804 res_nclose(statp);
805
806 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
807 if (statp->_vcsock < 0) {
808 switch (errno) {
809 case EPROTONOSUPPORT:
810 #ifdef EPFNOSUPPORT
811 case EPFNOSUPPORT:
812 #endif
813 case EAFNOSUPPORT:
814 Perror(statp, stderr, "socket(vc)", errno);
815 return (0);
816 default:
817 *terrno = errno;
818 Perror(statp, stderr, "socket(vc)", errno);
819 return (-1);
820 }
821 }
822 fchown(statp->_vcsock, AID_DNS, -1);
823 if (statp->_mark != MARK_UNSET) {
824 if (setsockopt(statp->_vcsock, SOL_SOCKET,
825 SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
826 *terrno = errno;
827 Perror(statp, stderr, "setsockopt", errno);
828 return -1;
829 }
830 }
831 errno = 0;
832 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
833 *terrno = errno;
834 Aerror(statp, stderr, "bind/vc", errno, nsap,
835 nsaplen);
836 res_nclose(statp);
837 return (0);
838 }
839 if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen,
840 get_timeout(statp, params, ns)) < 0) {
841 *terrno = errno;
842 Aerror(statp, stderr, "connect/vc", errno, nsap,
843 nsaplen);
844 res_nclose(statp);
845 /*
846 * The way connect_with_timeout() is implemented prevents us from reliably
847 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
848 * currently both cases are handled in the same way, there is no need to
849 * change this (yet). If we ever need to reliably distinguish between these
850 * cases, both connect_with_timeout() and retrying_poll() need to be
851 * modified, though.
852 */
853 *rcode = RCODE_TIMEOUT;
854 return (0);
855 }
856 statp->_flags |= RES_F_VC;
857 }
858
859 /*
860 * Send length & message
861 */
862 ns_put16((u_short)buflen, (u_char*)(void *)&len);
863 iov[0] = evConsIovec(&len, INT16SZ);
864 DE_CONST(buf, tmp);
865 iov[1] = evConsIovec(tmp, (size_t)buflen);
866 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
867 *terrno = errno;
868 Perror(statp, stderr, "write failed", errno);
869 res_nclose(statp);
870 return (0);
871 }
872 /*
873 * Receive length & response
874 */
875 read_len:
876 cp = ans;
877 len = INT16SZ;
878 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
879 cp += n;
880 if ((len -= n) == 0)
881 break;
882 }
883 if (n <= 0) {
884 *terrno = errno;
885 Perror(statp, stderr, "read failed", errno);
886 res_nclose(statp);
887 /*
888 * A long running process might get its TCP
889 * connection reset if the remote server was
890 * restarted. Requery the server instead of
891 * trying a new one. When there is only one
892 * server, this means that a query might work
893 * instead of failing. We only allow one reset
894 * per query to prevent looping.
895 */
896 if (*terrno == ECONNRESET && !connreset) {
897 connreset = 1;
898 res_nclose(statp);
899 goto same_ns;
900 }
901 res_nclose(statp);
902 return (0);
903 }
904 resplen = ns_get16(ans);
905 if (resplen > anssiz) {
906 Dprint(statp->options & RES_DEBUG,
907 (stdout, ";; response truncated\n")
908 );
909 truncating = 1;
910 len = anssiz;
911 } else
912 len = resplen;
913 if (len < HFIXEDSZ) {
914 /*
915 * Undersized message.
916 */
917 Dprint(statp->options & RES_DEBUG,
918 (stdout, ";; undersized: %d\n", len));
919 *terrno = EMSGSIZE;
920 res_nclose(statp);
921 return (0);
922 }
923 cp = ans;
924 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
925 cp += n;
926 len -= n;
927 }
928 if (n <= 0) {
929 *terrno = errno;
930 Perror(statp, stderr, "read(vc)", errno);
931 res_nclose(statp);
932 return (0);
933 }
934
935 if (truncating) {
936 /*
937 * Flush rest of answer so connection stays in synch.
938 */
939 anhp->tc = 1;
940 len = resplen - anssiz;
941 while (len != 0) {
942 char junk[PACKETSZ];
943
944 n = read(statp->_vcsock, junk,
945 (len > sizeof junk) ? sizeof junk : len);
946 if (n > 0)
947 len -= n;
948 else
949 break;
950 }
951 }
952 /*
953 * If the calling applicating has bailed out of
954 * a previous call and failed to arrange to have
955 * the circuit closed or the server has got
956 * itself confused, then drop the packet and
957 * wait for the correct one.
958 */
959 if (hp->id != anhp->id) {
960 DprintQ((statp->options & RES_DEBUG) ||
961 (statp->pfcode & RES_PRF_REPLY),
962 (stdout, ";; old answer (unexpected):\n"),
963 ans, (resplen > anssiz) ? anssiz: resplen);
964 goto read_len;
965 }
966
967 /*
968 * All is well, or the error is fatal. Signal that the
969 * next nameserver ought not be tried.
970 */
971 if (resplen > 0) {
972 struct timespec done = evNowTime();
973 *delay = _res_stats_calculate_rtt(&done, &now);
974 *rcode = anhp->rcode;
975 }
976 return (resplen);
977 }
978
979 /* return -1 on error (errno set), 0 on success */
980 static int
connect_with_timeout(int sock,const struct sockaddr * nsap,socklen_t salen,const struct timespec timeout)981 connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen,
982 const struct timespec timeout)
983 {
984 int res, origflags;
985
986 origflags = fcntl(sock, F_GETFL, 0);
987 fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
988
989 res = __connect(sock, nsap, salen);
990 if (res < 0 && errno != EINPROGRESS) {
991 res = -1;
992 goto done;
993 }
994 if (res != 0) {
995 struct timespec now = evNowTime();
996 struct timespec finish = evAddTime(now, timeout);
997 if (DBG) {
998 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", " %d send_vc\n", sock);
999 }
1000
1001 res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
1002 if (res <= 0) {
1003 res = -1;
1004 }
1005 }
1006 done:
1007 fcntl(sock, F_SETFL, origflags);
1008 if (DBG) {
1009 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1010 " %d connect_with_const timeout returning %d\n", sock, res);
1011 }
1012 return res;
1013 }
1014
1015 static int
retrying_poll(const int sock,const short events,const struct timespec * finish)1016 retrying_poll(const int sock, const short events, const struct timespec* finish) {
1017 struct timespec now, timeout;
1018
1019 retry:
1020 if (DBG) {
1021 async_safe_format_log(ANDROID_LOG_DEBUG, "libc", " %d retrying_poll\n", sock);
1022 }
1023
1024 now = evNowTime();
1025 if (evCmpTime(*finish, now) > 0)
1026 timeout = evSubTime(*finish, now);
1027 else
1028 timeout = evConsTime(0L, 0L);
1029 struct pollfd fds = { .fd = sock, .events = events };
1030 int n = ppoll(&fds, 1, &timeout, /*sigmask=*/NULL);
1031 if (n == 0) {
1032 if (DBG) {
1033 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1034 " %d retrying_poll timeout\n", sock);
1035 }
1036 errno = ETIMEDOUT;
1037 return 0;
1038 }
1039 if (n < 0) {
1040 if (errno == EINTR)
1041 goto retry;
1042 if (DBG) {
1043 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1044 " %d retrying_poll got error %d\n",sock, n);
1045 }
1046 return n;
1047 }
1048 if (fds.revents & (POLLIN | POLLOUT | POLLERR)) {
1049 int error;
1050 socklen_t len = sizeof(error);
1051 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
1052 errno = error;
1053 if (DBG) {
1054 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1055 " %d retrying_poll dot error2 %d\n", sock, errno);
1056 }
1057
1058 return -1;
1059 }
1060 }
1061 if (DBG) {
1062 async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
1063 " %d retrying_poll returning %d\n",sock, n);
1064 }
1065
1066 return n;
1067 }
1068
1069 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)1070 send_dg(res_state statp, struct __res_params* params,
1071 const u_char *buf, int buflen, u_char *ans, int anssiz,
1072 int *terrno, int ns, int *v_circuit, int *gotsomewhere,
1073 time_t *at, int *rcode, int* delay)
1074 {
1075 *at = time(NULL);
1076 *rcode = RCODE_INTERNAL_ERROR;
1077 *delay = 0;
1078 const HEADER *hp = (const HEADER *)(const void *)buf;
1079 HEADER *anhp = (HEADER *)(void *)ans;
1080 const struct sockaddr *nsap;
1081 int nsaplen;
1082 struct timespec now, timeout, finish, done;
1083 struct sockaddr_storage from;
1084 socklen_t fromlen;
1085 int resplen, n, s;
1086
1087 nsap = get_nsaddr(statp, (size_t)ns);
1088 nsaplen = get_salen(nsap);
1089 if (EXT(statp).nssocks[ns] == -1) {
1090 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1091 if (EXT(statp).nssocks[ns] < 0) {
1092 switch (errno) {
1093 case EPROTONOSUPPORT:
1094 #ifdef EPFNOSUPPORT
1095 case EPFNOSUPPORT:
1096 #endif
1097 case EAFNOSUPPORT:
1098 Perror(statp, stderr, "socket(dg)", errno);
1099 return (0);
1100 default:
1101 *terrno = errno;
1102 Perror(statp, stderr, "socket(dg)", errno);
1103 return (-1);
1104 }
1105 }
1106
1107 fchown(EXT(statp).nssocks[ns], AID_DNS, -1);
1108 if (statp->_mark != MARK_UNSET) {
1109 if (setsockopt(EXT(statp).nssocks[ns], SOL_SOCKET,
1110 SO_MARK, &(statp->_mark), sizeof(statp->_mark)) < 0) {
1111 res_nclose(statp);
1112 return -1;
1113 }
1114 }
1115 #ifndef CANNOT_CONNECT_DGRAM
1116 /*
1117 * On a 4.3BSD+ machine (client and server,
1118 * actually), sending to a nameserver datagram
1119 * port with no nameserver will cause an
1120 * ICMP port unreachable message to be returned.
1121 * If our datagram socket is "connected" to the
1122 * server, we get an ECONNREFUSED error on the next
1123 * socket operation, and select returns if the
1124 * error message is received. We can thus detect
1125 * the absence of a nameserver without timing out.
1126 */
1127 if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
1128 Aerror(statp, stderr, "bind(dg)", errno, nsap,
1129 nsaplen);
1130 res_nclose(statp);
1131 return (0);
1132 }
1133 if (__connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
1134 Aerror(statp, stderr, "connect(dg)", errno, nsap,
1135 nsaplen);
1136 res_nclose(statp);
1137 return (0);
1138 }
1139 #endif /* !CANNOT_CONNECT_DGRAM */
1140 Dprint(statp->options & RES_DEBUG,
1141 (stdout, ";; new DG socket\n"))
1142
1143 }
1144 s = EXT(statp).nssocks[ns];
1145 #ifndef CANNOT_CONNECT_DGRAM
1146 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
1147 Perror(statp, stderr, "send", errno);
1148 res_nclose(statp);
1149 return (0);
1150 }
1151 #else /* !CANNOT_CONNECT_DGRAM */
1152 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
1153 {
1154 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
1155 res_nclose(statp);
1156 return (0);
1157 }
1158 #endif /* !CANNOT_CONNECT_DGRAM */
1159
1160 /*
1161 * Wait for reply.
1162 */
1163 timeout = get_timeout(statp, params, ns);
1164 now = evNowTime();
1165 finish = evAddTime(now, timeout);
1166 retry:
1167 n = retrying_poll(s, POLLIN, &finish);
1168
1169 if (n == 0) {
1170 *rcode = RCODE_TIMEOUT;
1171 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1172 *gotsomewhere = 1;
1173 return (0);
1174 }
1175 if (n < 0) {
1176 Perror(statp, stderr, "poll", errno);
1177 res_nclose(statp);
1178 return (0);
1179 }
1180 errno = 0;
1181 fromlen = sizeof(from);
1182 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
1183 (struct sockaddr *)(void *)&from, &fromlen);
1184 if (resplen <= 0) {
1185 Perror(statp, stderr, "recvfrom", errno);
1186 res_nclose(statp);
1187 return (0);
1188 }
1189 *gotsomewhere = 1;
1190 if (resplen < HFIXEDSZ) {
1191 /*
1192 * Undersized message.
1193 */
1194 Dprint(statp->options & RES_DEBUG,
1195 (stdout, ";; undersized: %d\n",
1196 resplen));
1197 *terrno = EMSGSIZE;
1198 res_nclose(statp);
1199 return (0);
1200 }
1201 if (hp->id != anhp->id) {
1202 /*
1203 * response from old query, ignore it.
1204 * XXX - potential security hazard could
1205 * be detected here.
1206 */
1207 DprintQ((statp->options & RES_DEBUG) ||
1208 (statp->pfcode & RES_PRF_REPLY),
1209 (stdout, ";; old answer:\n"),
1210 ans, (resplen > anssiz) ? anssiz : resplen);
1211 goto retry;
1212 }
1213 if (!(statp->options & RES_INSECURE1) &&
1214 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
1215 /*
1216 * response from wrong server? ignore it.
1217 * XXX - potential security hazard could
1218 * be detected here.
1219 */
1220 DprintQ((statp->options & RES_DEBUG) ||
1221 (statp->pfcode & RES_PRF_REPLY),
1222 (stdout, ";; not our server:\n"),
1223 ans, (resplen > anssiz) ? anssiz : resplen);
1224 goto retry;
1225 }
1226 #ifdef RES_USE_EDNS0
1227 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1228 /*
1229 * Do not retry if the server do not understand EDNS0.
1230 * The case has to be captured here, as FORMERR packet do not
1231 * carry query section, hence res_queriesmatch() returns 0.
1232 */
1233 DprintQ(statp->options & RES_DEBUG,
1234 (stdout, "server rejected query with EDNS0:\n"),
1235 ans, (resplen > anssiz) ? anssiz : resplen);
1236 /* record the error */
1237 statp->_flags |= RES_F_EDNS0ERR;
1238 res_nclose(statp);
1239 return (0);
1240 }
1241 #endif
1242 if (!(statp->options & RES_INSECURE2) &&
1243 !res_queriesmatch(buf, buf + buflen,
1244 ans, ans + anssiz)) {
1245 /*
1246 * response contains wrong query? ignore it.
1247 * XXX - potential security hazard could
1248 * be detected here.
1249 */
1250 DprintQ((statp->options & RES_DEBUG) ||
1251 (statp->pfcode & RES_PRF_REPLY),
1252 (stdout, ";; wrong query name:\n"),
1253 ans, (resplen > anssiz) ? anssiz : resplen);
1254 goto retry;;
1255 }
1256 done = evNowTime();
1257 *delay = _res_stats_calculate_rtt(&done, &now);
1258 if (anhp->rcode == SERVFAIL ||
1259 anhp->rcode == NOTIMP ||
1260 anhp->rcode == REFUSED) {
1261 DprintQ(statp->options & RES_DEBUG,
1262 (stdout, "server rejected query:\n"),
1263 ans, (resplen > anssiz) ? anssiz : resplen);
1264 res_nclose(statp);
1265 /* don't retry if called from dig */
1266 if (!statp->pfcode) {
1267 *rcode = anhp->rcode;
1268 return (0);
1269 }
1270 }
1271 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1272 /*
1273 * To get the rest of answer,
1274 * use TCP with same server.
1275 */
1276 Dprint(statp->options & RES_DEBUG,
1277 (stdout, ";; truncated answer\n"));
1278 *v_circuit = 1;
1279 res_nclose(statp);
1280 return (1);
1281 }
1282 /*
1283 * All is well, or the error is fatal. Signal that the
1284 * next nameserver ought not be tried.
1285 */
1286 if (resplen > 0) {
1287 *rcode = anhp->rcode;
1288 }
1289 return (resplen);
1290 }
1291
1292 static void
Aerror(const res_state statp,FILE * file,const char * string,int error,const struct sockaddr * address,int alen)1293 Aerror(const res_state statp, FILE *file, const char *string, int error,
1294 const struct sockaddr *address, int alen)
1295 {
1296 int save = errno;
1297 char hbuf[NI_MAXHOST];
1298 char sbuf[NI_MAXSERV];
1299
1300 if ((statp->options & RES_DEBUG) != 0U) {
1301 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1302 sbuf, sizeof(sbuf), niflags)) {
1303 strncpy(hbuf, "?", sizeof(hbuf) - 1);
1304 hbuf[sizeof(hbuf) - 1] = '\0';
1305 strncpy(sbuf, "?", sizeof(sbuf) - 1);
1306 sbuf[sizeof(sbuf) - 1] = '\0';
1307 }
1308 fprintf(file, "res_send: %s ([%s].%s): %s\n",
1309 string, hbuf, sbuf, strerror(error));
1310 }
1311 errno = save;
1312 }
1313
1314 static void
Perror(const res_state statp,FILE * file,const char * string,int error)1315 Perror(const res_state statp, FILE *file, const char *string, int error) {
1316 int save = errno;
1317
1318 if ((statp->options & RES_DEBUG) != 0U)
1319 fprintf(file, "res_send: %s: %s\n",
1320 string, strerror(error));
1321 errno = save;
1322 }
1323
1324 static int
sock_eq(struct sockaddr * a,struct sockaddr * b)1325 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1326 struct sockaddr_in *a4, *b4;
1327 struct sockaddr_in6 *a6, *b6;
1328
1329 if (a->sa_family != b->sa_family)
1330 return 0;
1331 switch (a->sa_family) {
1332 case AF_INET:
1333 a4 = (struct sockaddr_in *)(void *)a;
1334 b4 = (struct sockaddr_in *)(void *)b;
1335 return a4->sin_port == b4->sin_port &&
1336 a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1337 case AF_INET6:
1338 a6 = (struct sockaddr_in6 *)(void *)a;
1339 b6 = (struct sockaddr_in6 *)(void *)b;
1340 return a6->sin6_port == b6->sin6_port &&
1341 #ifdef HAVE_SIN6_SCOPE_ID
1342 a6->sin6_scope_id == b6->sin6_scope_id &&
1343 #endif
1344 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1345 default:
1346 return 0;
1347 }
1348 }
1349