Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */
3 /*
4 * Copyright 2008 Android Open Source Project (source port randomization)
5 * Copyright (c) 1985, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
37 /*
38 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
39 *
40 * Permission to use, copy, modify, and distribute this software for any
41 * purpose with or without fee is hereby granted, provided that the above
42 * copyright notice and this permission notice appear in all copies, and that
43 * the name of Digital Equipment Corporation not be used in advertising or
44 * publicity pertaining to distribution of the document or software without
45 * specific, written prior permission.
46 *
47 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
48 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
50 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
51 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
52 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
53 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54 * SOFTWARE.
55 */
57 /*
58 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
59 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
60 *
61 * Permission to use, copy, modify, and distribute this software for any
62 * purpose with or without fee is hereby granted, provided that the above
63 * copyright notice and this permission notice appear in all copies.
64 *
65 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
66 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
67 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
68 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
69 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
70 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
71 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
72 */
74 /*
75 * This version of this file is derived from Android 2.3 "Gingerbread",
76 * which contains uncredited changes by Android/Google developers. It has
77 * been modified in 2011 for use in the Android build of Mozilla Firefox by
78 * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
79 * and Steve Workman <sjhworkman@gmail.com>).
80 * These changes are offered under the same license as the original NetBSD
81 * file, whose copyright and license are unchanged above.
82 */
84 #define ANDROID_CHANGES 1
85 #define MOZILLA_NECKO_EXCLUDE_CODE 1
87 #include <sys/cdefs.h>
88 #if defined(LIBC_SCCS) && !defined(lint)
89 #ifdef notdef
90 static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
91 static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp";
92 #else
93 __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
94 #endif
95 #endif /* LIBC_SCCS and not lint */
97 /* Set to 0 to not use the small/simple/limited DNS cache
98 * Cache implemented higher up in Gecko */
99 #define USE_RESOLV_CACHE 0
101 /*
102 * Send query to name server and wait for reply.
103 */
105 #include <sys/types.h>
106 #include <sys/param.h>
107 #include <sys/time.h>
108 #include <sys/socket.h>
109 #include <sys/uio.h>
111 #include <netinet/in.h>
112 #include "arpa_nameser.h"
113 #include <arpa/inet.h>
115 #include <errno.h>
116 #include <netdb.h>
117 #ifdef ANDROID_CHANGES
118 #include "resolv_private.h"
119 #else
120 #include <resolv.h>
121 #endif
122 #include <signal.h>
123 #include <stdio.h>
124 #include <stdlib.h>
125 #include <string.h>
126 #include <unistd.h>
128 #include "eventlib.h"
130 #if USE_RESOLV_CACHE
131 # include <resolv_cache.h>
132 #endif
134 #ifndef DE_CONST
135 #define DE_CONST(c,v) v = ((c) ? \
136 strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
137 #endif
139 /* Options. Leave them on. */
140 #ifndef DEBUG
141 #define DEBUG
142 #endif
143 #include "res_debug.h"
144 #include "res_private.h"
146 #define EXT(res) ((res)->_u._ext)
148 static const int highestFD = FD_SETSIZE - 1;
150 /* Forward. */
152 static int get_salen __P((const struct sockaddr *));
153 static struct sockaddr * get_nsaddr __P((res_state, size_t));
154 static int send_vc(res_state, const u_char *, int,
155 u_char *, int, int *, int);
156 static int send_dg(res_state, const u_char *, int,
157 u_char *, int, int *, int,
158 int *, int *);
159 static void Aerror(const res_state, FILE *, const char *, int,
160 const struct sockaddr *, int);
161 static void Perror(const res_state, FILE *, const char *, int);
162 static int sock_eq(struct sockaddr *, struct sockaddr *);
163 #ifdef NEED_PSELECT
164 static int pselect(int, void *, void *, void *,
165 struct timespec *,
166 const sigset_t *);
167 #endif
168 void res_pquery(const res_state, const u_char *, int, FILE *);
171 /* BIONIC-BEGIN: implement source port randomization */
172 typedef union {
173 struct sockaddr sa;
174 struct sockaddr_in sin;
175 struct sockaddr_in6 sin6;
176 } _sockaddr_union;
178 static int
179 random_bind( int s, int family )
180 {
181 _sockaddr_union u;
182 int j;
183 socklen_t slen;
185 /* clear all, this also sets the IP4/6 address to 'any' */
186 memset( &u, 0, sizeof u );
188 switch (family) {
189 case AF_INET:
190 u.sin.sin_family = family;
191 slen = sizeof u.sin;
192 break;
193 case AF_INET6:
194 u.sin6.sin6_family = family;
195 slen = sizeof u.sin6;
196 break;
197 default:
198 errno = EPROTO;
199 return -1;
200 }
202 /* first try to bind to a random source port a few times */
203 for (j = 0; j < 10; j++) {
204 /* find a random port between 1025 .. 65534 */
205 int port = 1025 + (res_randomid() % (65535-1025));
206 if (family == AF_INET)
207 u.sin.sin_port = htons(port);
208 else
209 u.sin6.sin6_port = htons(port);
211 if ( !bind( s, &u.sa, slen ) )
212 return 0;
213 }
215 /* nothing after 10 tries, our network table is probably busy */
216 /* let the system decide which port is best */
217 if (family == AF_INET)
218 u.sin.sin_port = 0;
219 else
220 u.sin6.sin6_port = 0;
222 return bind( s, &u.sa, slen );
223 }
224 /* BIONIC-END */
226 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
228 /* Public. */
230 /* int
231 * res_isourserver(ina)
232 * looks up "ina" in _res.ns_addr_list[]
233 * returns:
234 * 0 : not found
235 * >0 : found
236 * author:
237 * paul vixie, 29may94
238 */
239 int
240 res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
241 const struct sockaddr_in *inp, *srv;
242 const struct sockaddr_in6 *in6p, *srv6;
243 int ns;
245 switch (sa->sa_family) {
246 case AF_INET:
247 inp = (const struct sockaddr_in *)(const void *)sa;
248 for (ns = 0; ns < statp->nscount; ns++) {
249 srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
250 if (srv->sin_family == inp->sin_family &&
251 srv->sin_port == inp->sin_port &&
252 (srv->sin_addr.s_addr == INADDR_ANY ||
253 srv->sin_addr.s_addr == inp->sin_addr.s_addr))
254 return (1);
255 }
256 break;
257 case AF_INET6:
258 if (EXT(statp).ext == NULL)
259 break;
260 in6p = (const struct sockaddr_in6 *)(const void *)sa;
261 for (ns = 0; ns < statp->nscount; ns++) {
262 srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
263 if (srv6->sin6_family == in6p->sin6_family &&
264 srv6->sin6_port == in6p->sin6_port &&
265 #ifdef HAVE_SIN6_SCOPE_ID
266 (srv6->sin6_scope_id == 0 ||
267 srv6->sin6_scope_id == in6p->sin6_scope_id) &&
268 #endif
269 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
270 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
271 return (1);
272 }
273 break;
274 default:
275 break;
276 }
277 return (0);
278 }
280 /* int
281 * res_nameinquery(name, type, class, buf, eom)
282 * look for (name,type,class) in the query section of packet (buf,eom)
283 * requires:
284 * buf + HFIXEDSZ <= eom
285 * returns:
286 * -1 : format error
287 * 0 : not found
288 * >0 : found
289 * author:
290 * paul vixie, 29may94
291 */
292 int
293 res_nameinquery(const char *name, int type, int class,
294 const u_char *buf, const u_char *eom)
295 {
296 const u_char *cp = buf + HFIXEDSZ;
297 int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
299 while (qdcount-- > 0) {
300 char tname[MAXDNAME+1];
301 int n, ttype, tclass;
303 n = dn_expand(buf, eom, cp, tname, sizeof tname);
304 if (n < 0)
305 return (-1);
306 cp += n;
307 if (cp + 2 * INT16SZ > eom)
308 return (-1);
309 ttype = ns_get16(cp); cp += INT16SZ;
310 tclass = ns_get16(cp); cp += INT16SZ;
311 if (ttype == type && tclass == class &&
312 ns_samename(tname, name) == 1)
313 return (1);
314 }
315 return (0);
316 }
318 /* int
319 * res_queriesmatch(buf1, eom1, buf2, eom2)
320 * is there a 1:1 mapping of (name,type,class)
321 * in (buf1,eom1) and (buf2,eom2)?
322 * returns:
323 * -1 : format error
324 * 0 : not a 1:1 mapping
325 * >0 : is a 1:1 mapping
326 * author:
327 * paul vixie, 29may94
328 */
329 int
330 res_queriesmatch(const u_char *buf1, const u_char *eom1,
331 const u_char *buf2, const u_char *eom2)
332 {
333 const u_char *cp = buf1 + HFIXEDSZ;
334 int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
336 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
337 return (-1);
339 /*
340 * Only header section present in replies to
341 * dynamic update packets.
342 */
343 if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
344 (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
345 return (1);
347 if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
348 return (0);
349 while (qdcount-- > 0) {
350 char tname[MAXDNAME+1];
351 int n, ttype, tclass;
353 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
354 if (n < 0)
355 return (-1);
356 cp += n;
357 if (cp + 2 * INT16SZ > eom1)
358 return (-1);
359 ttype = ns_get16(cp); cp += INT16SZ;
360 tclass = ns_get16(cp); cp += INT16SZ;
361 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
362 return (0);
363 }
364 return (1);
365 }
368 int
369 res_nsend(res_state statp,
370 const u_char *buf, int buflen, u_char *ans, int anssiz)
371 {
372 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
373 char abuf[NI_MAXHOST];
374 #if USE_RESOLV_CACHE
375 struct resolv_cache* cache;
376 ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;
377 #endif
379 if (statp->nscount == 0) {
380 errno = ESRCH;
381 return (-1);
382 }
383 if (anssiz < HFIXEDSZ) {
384 errno = EINVAL;
385 return (-1);
386 }
387 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
388 (stdout, ";; res_send()\n"), buf, buflen);
389 v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
390 gotsomewhere = 0;
391 terrno = ETIMEDOUT;
393 #if USE_RESOLV_CACHE
394 cache = __get_res_cache();
395 if (cache != NULL) {
396 int anslen = 0;
397 cache_status = _resolv_cache_lookup(
398 cache, buf, buflen,
399 ans, anssiz, &anslen);
401 if (cache_status == RESOLV_CACHE_FOUND) {
402 return anslen;
403 }
404 }
405 #endif
407 /*
408 * If the ns_addr_list in the resolver context has changed, then
409 * invalidate our cached copy and the associated timing data.
410 */
411 if (EXT(statp).nscount != 0) {
412 int needclose = 0;
413 struct sockaddr_storage peer;
414 socklen_t peerlen;
416 if (EXT(statp).nscount != statp->nscount)
417 needclose++;
418 else
419 for (ns = 0; ns < statp->nscount; ns++) {
420 if (statp->nsaddr_list[ns].sin_family &&
421 !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
422 (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
423 needclose++;
424 break;
425 }
427 if (EXT(statp).nssocks[ns] == -1)
428 continue;
429 peerlen = sizeof(peer);
430 if (getsockname(EXT(statp).nssocks[ns],
431 (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
432 needclose++;
433 break;
434 }
435 if (!sock_eq((struct sockaddr *)(void *)&peer,
436 get_nsaddr(statp, (size_t)ns))) {
437 needclose++;
438 break;
439 }
440 }
441 if (needclose) {
442 res_nclose(statp);
443 EXT(statp).nscount = 0;
444 }
445 }
447 /*
448 * Maybe initialize our private copy of the ns_addr_list.
449 */
450 if (EXT(statp).nscount == 0) {
451 for (ns = 0; ns < statp->nscount; ns++) {
452 EXT(statp).nstimes[ns] = RES_MAXTIME;
453 EXT(statp).nssocks[ns] = -1;
454 if (!statp->nsaddr_list[ns].sin_family)
455 continue;
456 EXT(statp).ext->nsaddrs[ns].sin =
457 statp->nsaddr_list[ns];
458 }
459 EXT(statp).nscount = statp->nscount;
460 }
462 /*
463 * Some resolvers want to even out the load on their nameservers.
464 * Note that RES_BLAST overrides RES_ROTATE.
465 */
466 if ((statp->options & RES_ROTATE) != 0U &&
467 (statp->options & RES_BLAST) == 0U) {
468 union res_sockaddr_union inu;
469 struct sockaddr_in ina;
470 int lastns = statp->nscount - 1;
471 int fd;
472 u_int16_t nstime;
474 if (EXT(statp).ext != NULL)
475 inu = EXT(statp).ext->nsaddrs[0];
476 ina = statp->nsaddr_list[0];
477 fd = EXT(statp).nssocks[0];
478 nstime = EXT(statp).nstimes[0];
479 for (ns = 0; ns < lastns; ns++) {
480 if (EXT(statp).ext != NULL)
481 EXT(statp).ext->nsaddrs[ns] =
482 EXT(statp).ext->nsaddrs[ns + 1];
483 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
484 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
485 EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
486 }
487 if (EXT(statp).ext != NULL)
488 EXT(statp).ext->nsaddrs[lastns] = inu;
489 statp->nsaddr_list[lastns] = ina;
490 EXT(statp).nssocks[lastns] = fd;
491 EXT(statp).nstimes[lastns] = nstime;
492 }
494 /*
495 * Send request, RETRY times, or until successful.
496 */
497 for (try = 0; try < statp->retry; try++) {
498 for (ns = 0; ns < statp->nscount; ns++) {
499 struct sockaddr *nsap;
500 int nsaplen;
501 nsap = get_nsaddr(statp, (size_t)ns);
502 nsaplen = get_salen(nsap);
503 statp->_flags &= ~RES_F_LASTMASK;
504 statp->_flags |= (ns << RES_F_LASTSHIFT);
505 same_ns:
506 if (statp->qhook) {
507 int done = 0, loops = 0;
509 do {
510 res_sendhookact act;
512 act = (*statp->qhook)(&nsap, &buf, &buflen,
513 ans, anssiz, &resplen);
514 switch (act) {
515 case res_goahead:
516 done = 1;
517 break;
518 case res_nextns:
519 res_nclose(statp);
520 goto next_ns;
521 case res_done:
522 return (resplen);
523 case res_modified:
524 /* give the hook another try */
525 if (++loops < 42) /*doug adams*/
526 break;
527 /*FALLTHROUGH*/
528 case res_error:
529 /*FALLTHROUGH*/
530 default:
531 goto fail;
532 }
533 } while (!done);
534 }
536 Dprint(((statp->options & RES_DEBUG) &&
537 getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
538 NULL, 0, niflags) == 0),
539 (stdout, ";; Querying server (# %d) address = %s\n",
540 ns + 1, abuf));
543 if (v_circuit) {
544 /* Use VC; at most one attempt per server. */
545 try = statp->retry;
546 n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
547 ns);
548 if (n < 0)
549 goto fail;
550 if (n == 0)
551 goto next_ns;
552 resplen = n;
553 } else {
554 /* Use datagrams. */
555 n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
556 ns, &v_circuit, &gotsomewhere);
557 if (n < 0)
558 goto fail;
559 if (n == 0)
560 goto next_ns;
561 if (v_circuit)
562 goto same_ns;
563 resplen = n;
564 }
566 Dprint((statp->options & RES_DEBUG) ||
567 ((statp->pfcode & RES_PRF_REPLY) &&
568 (statp->pfcode & RES_PRF_HEAD1)),
569 (stdout, ";; got answer:\n"));
571 DprintQ((statp->options & RES_DEBUG) ||
572 (statp->pfcode & RES_PRF_REPLY),
573 (stdout, "%s", ""),
574 ans, (resplen > anssiz) ? anssiz : resplen);
576 #if USE_RESOLV_CACHE
577 if (cache_status == RESOLV_CACHE_NOTFOUND) {
578 _resolv_cache_add(cache, buf, buflen,
579 ans, resplen);
580 }
581 #endif
582 /*
583 * If we have temporarily opened a virtual circuit,
584 * or if we haven't been asked to keep a socket open,
585 * close the socket.
586 */
587 if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
588 (statp->options & RES_STAYOPEN) == 0U) {
589 res_nclose(statp);
590 }
591 if (statp->rhook) {
592 int done = 0, loops = 0;
594 do {
595 res_sendhookact act;
597 act = (*statp->rhook)(nsap, buf, buflen,
598 ans, anssiz, &resplen);
599 switch (act) {
600 case res_goahead:
601 case res_done:
602 done = 1;
603 break;
604 case res_nextns:
605 res_nclose(statp);
606 goto next_ns;
607 case res_modified:
608 /* give the hook another try */
609 if (++loops < 42) /*doug adams*/
610 break;
611 /*FALLTHROUGH*/
612 case res_error:
613 /*FALLTHROUGH*/
614 default:
615 goto fail;
616 }
617 } while (!done);
619 }
620 return (resplen);
621 next_ns: ;
622 } /*foreach ns*/
623 } /*foreach retry*/
624 res_nclose(statp);
625 if (!v_circuit) {
626 if (!gotsomewhere)
627 errno = ECONNREFUSED; /* no nameservers found */
628 else
629 errno = ETIMEDOUT; /* no answer obtained */
630 } else
631 errno = terrno;
632 return (-1);
633 fail:
634 res_nclose(statp);
635 return (-1);
636 }
638 /* Private */
640 static int
641 get_salen(sa)
642 const struct sockaddr *sa;
643 {
645 #ifdef HAVE_SA_LEN
646 /* There are people do not set sa_len. Be forgiving to them. */
647 if (sa->sa_len)
648 return (sa->sa_len);
649 #endif
651 if (sa->sa_family == AF_INET)
652 return (sizeof(struct sockaddr_in));
653 else if (sa->sa_family == AF_INET6)
654 return (sizeof(struct sockaddr_in6));
655 else
656 return (0); /* unknown, die on connect */
657 }
659 /*
660 * pick appropriate nsaddr_list for use. see res_init() for initialization.
661 */
662 static struct sockaddr *
663 get_nsaddr(statp, n)
664 res_state statp;
665 size_t n;
666 {
668 if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
669 /*
670 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
671 * than struct sockaddr, and
672 * - user code did not update statp->nsaddr_list[n].
673 */
674 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
675 } else {
676 /*
677 * - user code updated statp->nsaddr_list[n], or
678 * - statp->nsaddr_list[n] has the same content as
679 * EXT(statp).ext->nsaddrs[n].
680 */
681 return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
682 }
683 }
685 static int
686 send_vc(res_state statp,
687 const u_char *buf, int buflen, u_char *ans, int anssiz,
688 int *terrno, int ns)
689 {
690 const HEADER *hp = (const HEADER *)(const void *)buf;
691 HEADER *anhp = (HEADER *)(void *)ans;
692 struct sockaddr *nsap;
693 int nsaplen;
694 int truncating, connreset, resplen, n;
695 struct iovec iov[2];
696 u_short len;
697 u_char *cp;
698 void *tmp;
700 nsap = get_nsaddr(statp, (size_t)ns);
701 nsaplen = get_salen(nsap);
703 connreset = 0;
704 same_ns:
705 truncating = 0;
707 /* Are we still talking to whom we want to talk to? */
708 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
709 struct sockaddr_storage peer;
710 socklen_t size = sizeof peer;
712 if (getpeername(statp->_vcsock,
713 (struct sockaddr *)(void *)&peer, &size) < 0 ||
714 !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
715 res_nclose(statp);
716 statp->_flags &= ~RES_F_VC;
717 }
718 }
720 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
721 if (statp->_vcsock >= 0)
722 res_nclose(statp);
724 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
725 if (statp->_vcsock > highestFD) {
726 res_nclose(statp);
727 errno = ENOTSOCK;
728 }
729 if (statp->_vcsock < 0) {
730 switch (errno) {
731 case EPROTONOSUPPORT:
732 #ifdef EPFNOSUPPORT
733 case EPFNOSUPPORT:
734 #endif
735 case EAFNOSUPPORT:
736 Perror(statp, stderr, "socket(vc)", errno);
737 return (0);
738 default:
739 *terrno = errno;
740 Perror(statp, stderr, "socket(vc)", errno);
741 return (-1);
742 }
743 }
744 errno = 0;
745 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
746 *terrno = errno;
747 Aerror(statp, stderr, "bind/vc", errno, nsap,
748 nsaplen);
749 res_nclose(statp);
750 return (0);
751 }
752 if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
753 *terrno = errno;
754 Aerror(statp, stderr, "connect/vc", errno, nsap,
755 nsaplen);
756 res_nclose(statp);
757 return (0);
758 }
759 statp->_flags |= RES_F_VC;
760 }
762 /*
763 * Send length & message
764 */
765 ns_put16((u_short)buflen, (u_char*)(void *)&len);
766 iov[0] = evConsIovec(&len, INT16SZ);
767 DE_CONST(buf, tmp);
768 iov[1] = evConsIovec(tmp, (size_t)buflen);
769 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
770 *terrno = errno;
771 Perror(statp, stderr, "write failed", errno);
772 res_nclose(statp);
773 return (0);
774 }
775 /*
776 * Receive length & response
777 */
778 read_len:
779 cp = ans;
780 len = INT16SZ;
781 while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
782 cp += n;
783 if ((len -= n) == 0)
784 break;
785 }
786 if (n <= 0) {
787 *terrno = errno;
788 Perror(statp, stderr, "read failed", errno);
789 res_nclose(statp);
790 /*
791 * A long running process might get its TCP
792 * connection reset if the remote server was
793 * restarted. Requery the server instead of
794 * trying a new one. When there is only one
795 * server, this means that a query might work
796 * instead of failing. We only allow one reset
797 * per query to prevent looping.
798 */
799 if (*terrno == ECONNRESET && !connreset) {
800 connreset = 1;
801 res_nclose(statp);
802 goto same_ns;
803 }
804 res_nclose(statp);
805 return (0);
806 }
807 resplen = ns_get16(ans);
808 if (resplen > anssiz) {
809 Dprint(statp->options & RES_DEBUG,
810 (stdout, ";; response truncated\n")
811 );
812 truncating = 1;
813 len = anssiz;
814 } else
815 len = resplen;
816 if (len < HFIXEDSZ) {
817 /*
818 * Undersized message.
819 */
820 Dprint(statp->options & RES_DEBUG,
821 (stdout, ";; undersized: %d\n", len));
822 *terrno = EMSGSIZE;
823 res_nclose(statp);
824 return (0);
825 }
826 cp = ans;
827 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
828 cp += n;
829 len -= n;
830 }
831 if (n <= 0) {
832 *terrno = errno;
833 Perror(statp, stderr, "read(vc)", errno);
834 res_nclose(statp);
835 return (0);
836 }
837 if (truncating) {
838 /*
839 * Flush rest of answer so connection stays in synch.
840 */
841 anhp->tc = 1;
842 len = resplen - anssiz;
843 while (len != 0) {
844 char junk[PACKETSZ];
846 n = read(statp->_vcsock, junk,
847 (len > sizeof junk) ? sizeof junk : len);
848 if (n > 0)
849 len -= n;
850 else
851 break;
852 }
853 }
854 /*
855 * If the calling applicating has bailed out of
856 * a previous call and failed to arrange to have
857 * the circuit closed or the server has got
858 * itself confused, then drop the packet and
859 * wait for the correct one.
860 */
861 if (hp->id != anhp->id) {
862 DprintQ((statp->options & RES_DEBUG) ||
863 (statp->pfcode & RES_PRF_REPLY),
864 (stdout, ";; old answer (unexpected):\n"),
865 ans, (resplen > anssiz) ? anssiz: resplen);
866 goto read_len;
867 }
869 /*
870 * All is well, or the error is fatal. Signal that the
871 * next nameserver ought not be tried.
872 */
873 return (resplen);
874 }
876 static int
877 send_dg(res_state statp,
878 const u_char *buf, int buflen, u_char *ans, int anssiz,
879 int *terrno, int ns, int *v_circuit, int *gotsomewhere)
880 {
881 const HEADER *hp = (const HEADER *)(const void *)buf;
882 HEADER *anhp = (HEADER *)(void *)ans;
883 const struct sockaddr *nsap;
884 int nsaplen;
885 struct timespec now, timeout, finish;
886 fd_set dsmask;
887 struct sockaddr_storage from;
888 socklen_t fromlen;
889 int resplen, seconds, n, s;
891 nsap = get_nsaddr(statp, (size_t)ns);
892 nsaplen = get_salen(nsap);
893 if (EXT(statp).nssocks[ns] == -1) {
894 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
895 if (EXT(statp).nssocks[ns] > highestFD) {
896 res_nclose(statp);
897 errno = ENOTSOCK;
898 }
899 if (EXT(statp).nssocks[ns] < 0) {
900 switch (errno) {
901 case EPROTONOSUPPORT:
902 #ifdef EPFNOSUPPORT
903 case EPFNOSUPPORT:
904 #endif
905 case EAFNOSUPPORT:
906 Perror(statp, stderr, "socket(dg)", errno);
907 return (0);
908 default:
909 *terrno = errno;
910 Perror(statp, stderr, "socket(dg)", errno);
911 return (-1);
912 }
913 }
914 #ifndef CANNOT_CONNECT_DGRAM
915 /*
916 * On a 4.3BSD+ machine (client and server,
917 * actually), sending to a nameserver datagram
918 * port with no nameserver will cause an
919 * ICMP port unreachable message to be returned.
920 * If our datagram socket is "connected" to the
921 * server, we get an ECONNREFUSED error on the next
922 * socket operation, and select returns if the
923 * error message is received. We can thus detect
924 * the absence of a nameserver without timing out.
925 */
926 if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
927 Aerror(statp, stderr, "bind(dg)", errno, nsap,
928 nsaplen);
929 res_nclose(statp);
930 return (0);
931 }
932 if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
933 Aerror(statp, stderr, "connect(dg)", errno, nsap,
934 nsaplen);
935 res_nclose(statp);
936 return (0);
937 }
938 #endif /* !CANNOT_CONNECT_DGRAM */
939 Dprint(statp->options & RES_DEBUG,
940 (stdout, ";; new DG socket\n"))
941 }
942 s = EXT(statp).nssocks[ns];
943 #ifndef CANNOT_CONNECT_DGRAM
944 if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
945 Perror(statp, stderr, "send", errno);
946 res_nclose(statp);
947 return (0);
948 }
949 #else /* !CANNOT_CONNECT_DGRAM */
950 if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
951 {
952 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
953 res_nclose(statp);
954 return (0);
955 }
956 #endif /* !CANNOT_CONNECT_DGRAM */
958 /*
959 * Wait for reply.
960 */
961 seconds = (statp->retrans << ns);
962 if (ns > 0)
963 seconds /= statp->nscount;
964 if (seconds <= 0)
965 seconds = 1;
966 now = evNowTime();
967 timeout = evConsTime((long)seconds, 0L);
968 finish = evAddTime(now, timeout);
969 goto nonow;
970 wait:
971 now = evNowTime();
972 nonow:
973 FD_ZERO(&dsmask);
974 FD_SET(s, &dsmask);
975 if (evCmpTime(finish, now) > 0)
976 timeout = evSubTime(finish, now);
977 else
978 timeout = evConsTime(0L, 0L);
979 n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
980 if (n == 0) {
981 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
982 *gotsomewhere = 1;
983 return (0);
984 }
985 if (n < 0) {
986 if (errno == EINTR)
987 goto wait;
988 Perror(statp, stderr, "select", errno);
989 res_nclose(statp);
990 return (0);
991 }
992 errno = 0;
993 fromlen = sizeof(from);
994 resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
995 (struct sockaddr *)(void *)&from, &fromlen);
996 if (resplen <= 0) {
997 Perror(statp, stderr, "recvfrom", errno);
998 res_nclose(statp);
999 return (0);
1000 }
1001 *gotsomewhere = 1;
1002 if (resplen < HFIXEDSZ) {
1003 /*
1004 * Undersized message.
1005 */
1006 Dprint(statp->options & RES_DEBUG,
1007 (stdout, ";; undersized: %d\n",
1008 resplen));
1009 *terrno = EMSGSIZE;
1010 res_nclose(statp);
1011 return (0);
1012 }
1013 if (hp->id != anhp->id) {
1014 /*
1015 * response from old query, ignore it.
1016 * XXX - potential security hazard could
1017 * be detected here.
1018 */
1019 DprintQ((statp->options & RES_DEBUG) ||
1020 (statp->pfcode & RES_PRF_REPLY),
1021 (stdout, ";; old answer:\n"),
1022 ans, (resplen > anssiz) ? anssiz : resplen);
1023 goto wait;
1024 }
1025 if (!(statp->options & RES_INSECURE1) &&
1026 !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
1027 /*
1028 * response from wrong server? ignore it.
1029 * XXX - potential security hazard could
1030 * be detected here.
1031 */
1032 DprintQ((statp->options & RES_DEBUG) ||
1033 (statp->pfcode & RES_PRF_REPLY),
1034 (stdout, ";; not our server:\n"),
1035 ans, (resplen > anssiz) ? anssiz : resplen);
1036 goto wait;
1037 }
1038 #ifdef RES_USE_EDNS0
1039 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1040 /*
1041 * Do not retry if the server do not understand EDNS0.
1042 * The case has to be captured here, as FORMERR packet do not
1043 * carry query section, hence res_queriesmatch() returns 0.
1044 */
1045 DprintQ(statp->options & RES_DEBUG,
1046 (stdout, "server rejected query with EDNS0:\n"),
1047 ans, (resplen > anssiz) ? anssiz : resplen);
1048 /* record the error */
1049 statp->_flags |= RES_F_EDNS0ERR;
1050 res_nclose(statp);
1051 return (0);
1052 }
1053 #endif
1054 if (!(statp->options & RES_INSECURE2) &&
1055 !res_queriesmatch(buf, buf + buflen,
1056 ans, ans + anssiz)) {
1057 /*
1058 * response contains wrong query? ignore it.
1059 * XXX - potential security hazard could
1060 * be detected here.
1061 */
1062 DprintQ((statp->options & RES_DEBUG) ||
1063 (statp->pfcode & RES_PRF_REPLY),
1064 (stdout, ";; wrong query name:\n"),
1065 ans, (resplen > anssiz) ? anssiz : resplen);
1066 goto wait;
1067 }
1068 if (anhp->rcode == SERVFAIL ||
1069 anhp->rcode == NOTIMP ||
1070 anhp->rcode == REFUSED) {
1071 DprintQ(statp->options & RES_DEBUG,
1072 (stdout, "server rejected query:\n"),
1073 ans, (resplen > anssiz) ? anssiz : resplen);
1074 res_nclose(statp);
1075 /* don't retry if called from dig */
1076 if (!statp->pfcode)
1077 return (0);
1078 }
1079 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1080 /*
1081 * To get the rest of answer,
1082 * use TCP with same server.
1083 */
1084 Dprint(statp->options & RES_DEBUG,
1085 (stdout, ";; truncated answer\n"));
1086 *v_circuit = 1;
1087 res_nclose(statp);
1088 return (1);
1089 }
1090 /*
1091 * All is well, or the error is fatal. Signal that the
1092 * next nameserver ought not be tried.
1093 */
1094 return (resplen);
1095 }
1097 static void
1098 Aerror(const res_state statp, FILE *file, const char *string, int error,
1099 const struct sockaddr *address, int alen)
1100 {
1101 int save = errno;
1102 char hbuf[NI_MAXHOST];
1103 char sbuf[NI_MAXSERV];
1105 alen = alen;
1107 if ((statp->options & RES_DEBUG) != 0U) {
1108 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1109 sbuf, sizeof(sbuf), niflags)) {
1110 strncpy(hbuf, "?", sizeof(hbuf) - 1);
1111 hbuf[sizeof(hbuf) - 1] = '\0';
1112 strncpy(sbuf, "?", sizeof(sbuf) - 1);
1113 sbuf[sizeof(sbuf) - 1] = '\0';
1114 }
1115 fprintf(file, "res_send: %s ([%s].%s): %s\n",
1116 string, hbuf, sbuf, strerror(error));
1117 }
1118 errno = save;
1119 }
1121 static void
1122 Perror(const res_state statp, FILE *file, const char *string, int error) {
1123 int save = errno;
1125 if ((statp->options & RES_DEBUG) != 0U)
1126 fprintf(file, "res_send: %s: %s\n",
1127 string, strerror(error));
1128 errno = save;
1129 }
1131 static int
1132 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1133 struct sockaddr_in *a4, *b4;
1134 struct sockaddr_in6 *a6, *b6;
1136 if (a->sa_family != b->sa_family)
1137 return 0;
1138 switch (a->sa_family) {
1139 case AF_INET:
1140 a4 = (struct sockaddr_in *)(void *)a;
1141 b4 = (struct sockaddr_in *)(void *)b;
1142 return a4->sin_port == b4->sin_port &&
1143 a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1144 case AF_INET6:
1145 a6 = (struct sockaddr_in6 *)(void *)a;
1146 b6 = (struct sockaddr_in6 *)(void *)b;
1147 return a6->sin6_port == b6->sin6_port &&
1148 #ifdef HAVE_SIN6_SCOPE_ID
1149 a6->sin6_scope_id == b6->sin6_scope_id &&
1150 #endif
1151 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1152 default:
1153 return 0;
1154 }
1155 }
1157 #ifdef NEED_PSELECT
1158 /* XXX needs to move to the porting library. */
1159 static int
1160 pselect(int nfds, void *rfds, void *wfds, void *efds,
1161 struct timespec *tsp, const sigset_t *sigmask)
1162 {
1163 struct timeval tv, *tvp;
1164 sigset_t sigs;
1165 int n;
1167 if (tsp) {
1168 tvp = &tv;
1169 tv = evTimeVal(*tsp);
1170 } else
1171 tvp = NULL;
1172 if (sigmask)
1173 sigprocmask(SIG_SETMASK, sigmask, &sigs);
1174 n = select(nfds, rfds, wfds, efds, tvp);
1175 if (sigmask)
1176 sigprocmask(SIG_SETMASK, &sigs, NULL);
1177 if (tsp)
1178 *tsp = evTimeSpec(tv);
1179 return (n);
1180 }
1181 #endif