other-licenses/android/res_send.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

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);
  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);
  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;
  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;
  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);
  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;
  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);
  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);
  1090 	/*
  1091 	 * All is well, or the error is fatal.  Signal that the
  1092 	 * next nameserver ought not be tried.
  1093 	 */
  1094 	return (resplen);
  1097 static void
  1098 Aerror(const res_state statp, FILE *file, const char *string, int error,
  1099        const struct sockaddr *address, int alen)
  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';
  1115 		fprintf(file, "res_send: %s ([%s].%s): %s\n",
  1116 			string, hbuf, sbuf, strerror(error));
  1118 	errno = save;
  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;
  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;
  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)
  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);
  1181 #endif

mercurial