other-licenses/android/res_init.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/other-licenses/android/res_init.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,915 @@
     1.4 +/*	$NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $	*/
     1.5 +
     1.6 +/*
     1.7 + * Copyright (c) 1985, 1989, 1993
     1.8 + *    The Regents of the University of California.  All rights reserved.
     1.9 + *
    1.10 + * Redistribution and use in source and binary forms, with or without
    1.11 + * modification, are permitted provided that the following conditions
    1.12 + * are met:
    1.13 + * 1. Redistributions of source code must retain the above copyright
    1.14 + *    notice, this list of conditions and the following disclaimer.
    1.15 + * 2. Redistributions in binary form must reproduce the above copyright
    1.16 + *    notice, this list of conditions and the following disclaimer in the
    1.17 + *    documentation and/or other materials provided with the distribution.
    1.18 + * 3. All advertising materials mentioning features or use of this software
    1.19 + *    must display the following acknowledgement:
    1.20 + * 	This product includes software developed by the University of
    1.21 + * 	California, Berkeley and its contributors.
    1.22 + * 4. Neither the name of the University nor the names of its contributors
    1.23 + *    may be used to endorse or promote products derived from this software
    1.24 + *    without specific prior written permission.
    1.25 + *
    1.26 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    1.27 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.28 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.29 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    1.30 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1.31 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    1.32 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.33 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    1.34 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    1.35 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.36 + * SUCH DAMAGE.
    1.37 + */
    1.38 +
    1.39 +/*
    1.40 + * Portions Copyright (c) 1993 by Digital Equipment Corporation.
    1.41 + *
    1.42 + * Permission to use, copy, modify, and distribute this software for any
    1.43 + * purpose with or without fee is hereby granted, provided that the above
    1.44 + * copyright notice and this permission notice appear in all copies, and that
    1.45 + * the name of Digital Equipment Corporation not be used in advertising or
    1.46 + * publicity pertaining to distribution of the document or software without
    1.47 + * specific, written prior permission.
    1.48 + *
    1.49 + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
    1.50 + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
    1.51 + * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
    1.52 + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
    1.53 + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
    1.54 + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
    1.55 + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
    1.56 + * SOFTWARE.
    1.57 + */
    1.58 +
    1.59 +/*
    1.60 + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
    1.61 + * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
    1.62 + *
    1.63 + * Permission to use, copy, modify, and distribute this software for any
    1.64 + * purpose with or without fee is hereby granted, provided that the above
    1.65 + * copyright notice and this permission notice appear in all copies.
    1.66 + *
    1.67 + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
    1.68 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    1.69 + * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
    1.70 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    1.71 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    1.72 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
    1.73 + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    1.74 + */
    1.75 +
    1.76 +/*
    1.77 + * This version of this file is derived from Android 2.3 "Gingerbread",
    1.78 + * which contains uncredited changes by Android/Google developers.  It has
    1.79 + * been modified in 2011 for use in the Android build of Mozilla Firefox by
    1.80 + * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
    1.81 + * and Steve Workman <sjhworkman@gmail.com>).
    1.82 + * These changes are offered under the same license as the original NetBSD
    1.83 + * file, whose copyright and license are unchanged above.
    1.84 + */
    1.85 +
    1.86 +#define ANDROID_CHANGES 1
    1.87 +#define MOZILLE_NECKO_EXCLUDE_CODE 1
    1.88 +
    1.89 +#include <sys/cdefs.h>
    1.90 +#if defined(LIBC_SCCS) && !defined(lint)
    1.91 +#ifdef notdef
    1.92 +static const char sccsid[] = "@(#)res_init.c	8.1 (Berkeley) 6/7/93";
    1.93 +static const char rcsid[] = "Id: res_init.c,v 1.9.2.5.4.2 2004/03/16 12:34:18 marka Exp";
    1.94 +#else
    1.95 +__RCSID("$NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $");
    1.96 +#endif
    1.97 +#endif /* LIBC_SCCS and not lint */
    1.98 +
    1.99 +
   1.100 +
   1.101 +#include <sys/types.h>
   1.102 +#include <sys/param.h>
   1.103 +#include <sys/socket.h>
   1.104 +#include <sys/time.h>
   1.105 +
   1.106 +#include <netinet/in.h>
   1.107 +#include <arpa/inet.h>
   1.108 +#include "arpa_nameser.h"
   1.109 +
   1.110 +#include <ctype.h>
   1.111 +#include <stdio.h>
   1.112 +#include <stdlib.h>
   1.113 +#include <string.h>
   1.114 +#include <unistd.h>
   1.115 +#include <netdb.h>
   1.116 +
   1.117 +#ifdef ANDROID_CHANGES
   1.118 +#include <sys/system_properties.h>
   1.119 +#endif /* ANDROID_CHANGES */
   1.120 +
   1.121 +#ifndef MIN
   1.122 +#define	MIN(x,y)	((x)<(y)?(x):(y))
   1.123 +#endif
   1.124 +
   1.125 +/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
   1.126 +#ifdef ANDROID_CHANGES
   1.127 +#include "resolv_private.h"
   1.128 +#define MAX_DNS_PROPERTIES 8
   1.129 +#define DNS_PROP_NAME_PREFIX "net.dns"
   1.130 +#define DNS_CHANGE_PROP_NAME "net.dnschange"
   1.131 +#define DNS_SEARCH_PROP_NAME "net.dns.search"
   1.132 +const prop_info *dns_change_prop;
   1.133 +int dns_last_change_counter;
   1.134 +static int _get_dns_change_count();
   1.135 +#else
   1.136 +#include <resolv.h>
   1.137 +#endif
   1.138 +
   1.139 +#include "res_private.h"
   1.140 +
   1.141 +/* Options.  Should all be left alone. */
   1.142 +#ifndef DEBUG
   1.143 +#define DEBUG
   1.144 +#endif
   1.145 +
   1.146 +static void res_setoptions __P((res_state, const char *, const char *));
   1.147 +
   1.148 +static const char sort_mask[] = "/&";
   1.149 +#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
   1.150 +static u_int32_t net_mask __P((struct in_addr));
   1.151 +
   1.152 +#if !defined(isascii)	/* XXX - could be a function */
   1.153 +# define isascii(c) (!(c & 0200))
   1.154 +#endif
   1.155 +
   1.156 +/*
   1.157 + * Resolver state default settings.
   1.158 + */
   1.159 +
   1.160 +/*
   1.161 + * Set up default settings.  If the configuration file exist, the values
   1.162 + * there will have precedence.  Otherwise, the server address is set to
   1.163 + * INADDR_ANY and the default domain name comes from the gethostname().
   1.164 + *
   1.165 + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
   1.166 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address
   1.167 + * since it was noted that INADDR_ANY actually meant ``the first interface
   1.168 + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
   1.169 + * it had to be "up" in order for you to reach your own name server.  It
   1.170 + * was later decided that since the recommended practice is to always
   1.171 + * install local static routes through 127.0.0.1 for all your network
   1.172 + * interfaces, that we could solve this problem without a code change.
   1.173 + *
   1.174 + * The configuration file should always be used, since it is the only way
   1.175 + * to specify a default domain.  If you are running a server on your local
   1.176 + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
   1.177 + * in the configuration file.
   1.178 + *
   1.179 + * Return 0 if completes successfully, -1 on error
   1.180 + */
   1.181 +int
   1.182 +res_ninit(res_state statp) {
   1.183 +	extern int __res_vinit(res_state, int);
   1.184 +
   1.185 +	return (__res_vinit(statp, 0));
   1.186 +}
   1.187 +
   1.188 +#ifdef ANDROID_CHANGES
   1.189 +int load_domain_search_list(res_state statp) {
   1.190 +	char propvalue[PROP_VALUE_MAX];
   1.191 +	register char *cp, **pp;
   1.192 +
   1.193 +	if(__system_property_get(DNS_SEARCH_PROP_NAME, propvalue) >= 1) {
   1.194 +		strlcpy(statp->defdname, propvalue, sizeof(statp->defdname));
   1.195 +		if ((cp = strchr(statp->defdname, '\n')) != NULL)
   1.196 +			*cp = '\0';
   1.197 +		cp = statp->defdname;
   1.198 +		pp = statp->dnsrch;
   1.199 +		while ( pp < statp->dnsrch + MAXDNSRCH ) {
   1.200 +			while (*cp == ' ' || *cp == '\t') /* skip leading white space */
   1.201 +				cp++;
   1.202 +			if (*cp == '\0')  /* stop if nothing more */
   1.203 +				break;
   1.204 +			*pp++ = cp;  /* record this search domain */
   1.205 +			while (*cp) { /* zero-terminate it */
   1.206 +				if (*cp == ' ' || *cp == '\t') {
   1.207 +					*cp++ = '\0';
   1.208 +					break;
   1.209 +				}
   1.210 +				cp++;
   1.211 +			}
   1.212 +		}
   1.213 +		*pp = NULL; /* statp->dnsrch has MAXDNSRCH+1 items */
   1.214 +		if (pp > statp->dnsrch)
   1.215 +			return 1;
   1.216 +	}
   1.217 +	statp->defdname[0] = '\0';  /* no default domain name on Android */
   1.218 +	statp->dnsrch[0] = NULL;
   1.219 +	return 0;
   1.220 +}
   1.221 +#endif
   1.222 +
   1.223 +/* This function has to be reachable by res_data.c but not publicly. */
   1.224 +int
   1.225 +__res_vinit(res_state statp, int preinit) {
   1.226 +	register FILE *fp;
   1.227 +	register char *cp, **pp;
   1.228 +	register int n;
   1.229 +	char buf[BUFSIZ];
   1.230 +	int nserv = 0;    /* number of nameserver records read from file */
   1.231 +	int haveenv = 0;
   1.232 +	int havesearch = 0;
   1.233 +	int nsort = 0;
   1.234 +	char *net;
   1.235 +	int dots;
   1.236 +	union res_sockaddr_union u[2];
   1.237 +#ifdef ANDROID_CHANGES
   1.238 +        pid_t mypid = getpid();
   1.239 +        int use_proc_props = 0;
   1.240 +        int found_prop;
   1.241 +	char dnsProperty[PROP_VALUE_MAX];
   1.242 +#endif
   1.243 +
   1.244 +	if (!preinit) {
   1.245 +		statp->retrans = RES_TIMEOUT;
   1.246 +		statp->retry = RES_DFLRETRY;
   1.247 +		statp->options = RES_DEFAULT;
   1.248 +		statp->id = res_randomid();
   1.249 +	}
   1.250 +
   1.251 +  if ((statp->options & RES_INIT) != 0U)
   1.252 +       res_ndestroy(statp);
   1.253 +
   1.254 +	memset(u, 0, sizeof(u));
   1.255 +#ifdef USELOOPBACK
   1.256 +	u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
   1.257 +#else
   1.258 +	u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
   1.259 +#endif
   1.260 +	u[nserv].sin.sin_family = AF_INET;
   1.261 +	u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
   1.262 +#ifdef HAVE_SA_LEN
   1.263 +	u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
   1.264 +#endif
   1.265 +	nserv++;
   1.266 +#ifdef HAS_INET6_STRUCTS
   1.267 +#ifdef USELOOPBACK
   1.268 +	u[nserv].sin6.sin6_addr = in6addr_loopback;
   1.269 +#else
   1.270 +	u[nserv].sin6.sin6_addr = in6addr_any;
   1.271 +#endif
   1.272 +	u[nserv].sin6.sin6_family = AF_INET6;
   1.273 +	u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
   1.274 +#ifdef HAVE_SA_LEN
   1.275 +	u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
   1.276 +#endif
   1.277 +	nserv++;
   1.278 +#endif
   1.279 +	statp->nscount = 0;
   1.280 +	statp->ndots = 1;
   1.281 +	statp->pfcode = 0;
   1.282 +	statp->_vcsock = -1;
   1.283 +	statp->_flags = 0;
   1.284 +	statp->qhook = NULL;
   1.285 +	statp->rhook = NULL;
   1.286 +	statp->_u._ext.nscount = 0;
   1.287 +	statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
   1.288 +	if (statp->_u._ext.ext != NULL) {
   1.289 +	        memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
   1.290 +		statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
   1.291 +		strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
   1.292 +		strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
   1.293 +	}
   1.294 +	statp->nsort = 0;
   1.295 +	res_setservers(statp, u, nserv);
   1.296 +
   1.297 +#if 0 /* IGNORE THE ENVIRONMENT */
   1.298 +	/* Allow user to override the local domain definition */
   1.299 +	if ((cp = getenv("LOCALDOMAIN")) != NULL) {
   1.300 +		(void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
   1.301 +		statp->defdname[sizeof(statp->defdname) - 1] = '\0';
   1.302 +		haveenv++;
   1.303 +
   1.304 +		/*
   1.305 +		 * Set search list to be blank-separated strings
   1.306 +		 * from rest of env value.  Permits users of LOCALDOMAIN
   1.307 +		 * to still have a search list, and anyone to set the
   1.308 +		 * one that they want to use as an individual (even more
   1.309 +		 * important now that the rfc1535 stuff restricts searches)
   1.310 +		 */
   1.311 +		cp = statp->defdname;
   1.312 +		pp = statp->dnsrch;
   1.313 +		*pp++ = cp;
   1.314 +		for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
   1.315 +			if (*cp == '\n')	/* silly backwards compat */
   1.316 +				break;
   1.317 +			else if (*cp == ' ' || *cp == '\t') {
   1.318 +				*cp = 0;
   1.319 +				n = 1;
   1.320 +			} else if (n) {
   1.321 +				*pp++ = cp;
   1.322 +				n = 0;
   1.323 +				havesearch = 1;
   1.324 +			}
   1.325 +		}
   1.326 +		/* null terminate last domain if there are excess */
   1.327 +		while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
   1.328 +			cp++;
   1.329 +		*cp = '\0';
   1.330 +		*pp++ = 0;
   1.331 +	}
   1.332 +	if (nserv > 0)
   1.333 +		statp->nscount = nserv;
   1.334 +#endif
   1.335 +#ifdef ANDROID_CHANGES /* READ FROM SYSTEM PROPERTIES */
   1.336 +	dns_last_change_counter = _get_dns_change_count();
   1.337 +
   1.338 +	nserv = 0;
   1.339 +	for(n = 1; n <= MAX_DNS_PROPERTIES && nserv < MAXNS; n++) {
   1.340 +		char propname[PROP_NAME_MAX];
   1.341 +		char propvalue[PROP_VALUE_MAX];
   1.342 +
   1.343 +		struct addrinfo hints, *ai;
   1.344 +		char sbuf[NI_MAXSERV];
   1.345 +		const size_t minsiz = sizeof(statp->_u._ext.ext->nsaddrs[0]);
   1.346 +
   1.347 +		/*
   1.348 +		 * Check first for process-specific properties, and if those don't
   1.349 +		 * exist, try the generic properties.
   1.350 +		 */
   1.351 +		found_prop = 0;
   1.352 +		if (n == 1 || use_proc_props) {
   1.353 +			snprintf(propname, sizeof(propname), "%s%d.%d", DNS_PROP_NAME_PREFIX, n, mypid);
   1.354 +			if(__system_property_get(propname, propvalue) < 1) {
   1.355 +				if (use_proc_props) {
   1.356 +					break;
   1.357 +				}
   1.358 +			} else {
   1.359 +				found_prop = 1;
   1.360 +				use_proc_props = 1;
   1.361 +			}
   1.362 +		}
   1.363 +		if (!found_prop) {
   1.364 +			snprintf(propname, sizeof(propname), "%s%d", DNS_PROP_NAME_PREFIX, n);
   1.365 +			if(__system_property_get(propname, propvalue) < 1) {
   1.366 +				break;
   1.367 +			}
   1.368 +		}
   1.369 +
   1.370 +		cp = propvalue;
   1.371 +
   1.372 +		while (*cp == ' ' || *cp == '\t')
   1.373 +			cp++;
   1.374 +		cp[strcspn(cp, ";# \t\n")] = '\0';
   1.375 +		if ((*cp != '\0') && (*cp != '\n')) {
   1.376 +			memset(&hints, 0, sizeof(hints));
   1.377 +			hints.ai_family = PF_UNSPEC;
   1.378 +			hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
   1.379 +			hints.ai_flags = AI_NUMERICHOST;
   1.380 +			sprintf(sbuf, "%u", NAMESERVER_PORT);
   1.381 +			if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
   1.382 +			    (size_t)ai->ai_addrlen <= minsiz) {
   1.383 +				if (statp->_u._ext.ext != NULL) {
   1.384 +					memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
   1.385 +					       ai->ai_addr, ai->ai_addrlen);
   1.386 +				}
   1.387 +				if ((size_t)ai->ai_addrlen <=
   1.388 +				    sizeof(statp->nsaddr_list[nserv])) {
   1.389 +					memcpy(&statp->nsaddr_list[nserv],
   1.390 +					       ai->ai_addr, ai->ai_addrlen);
   1.391 +				} else {
   1.392 +					statp->nsaddr_list[nserv].sin_family = 0;
   1.393 +				}
   1.394 +				freeaddrinfo(ai);
   1.395 +				nserv++;
   1.396 +			}
   1.397 +		}
   1.398 +	}
   1.399 +
   1.400 +	/* Add the domain search list */
   1.401 +	havesearch = load_domain_search_list(statp);
   1.402 +#else /* !ANDROID_CHANGES - IGNORE resolv.conf in Android */
   1.403 +#define	MATCH(line, name) \
   1.404 +	(!strncmp(line, name, sizeof(name) - 1) && \
   1.405 +	(line[sizeof(name) - 1] == ' ' || \
   1.406 +	 line[sizeof(name) - 1] == '\t'))
   1.407 +
   1.408 +	nserv = 0;
   1.409 +	if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
   1.410 +	    /* read the config file */
   1.411 +	    while (fgets(buf, sizeof(buf), fp) != NULL) {
   1.412 +		/* skip comments */
   1.413 +		if (*buf == ';' || *buf == '#')
   1.414 +			continue;
   1.415 +		/* read default domain name */
   1.416 +		if (MATCH(buf, "domain")) {
   1.417 +		    if (haveenv)	/* skip if have from environ */
   1.418 +			    continue;
   1.419 +		    cp = buf + sizeof("domain") - 1;
   1.420 +		    while (*cp == ' ' || *cp == '\t')
   1.421 +			    cp++;
   1.422 +		    if ((*cp == '\0') || (*cp == '\n'))
   1.423 +			    continue;
   1.424 +		    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
   1.425 +		    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
   1.426 +		    if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
   1.427 +			    *cp = '\0';
   1.428 +		    havesearch = 0;
   1.429 +		    continue;
   1.430 +		}
   1.431 +		/* set search list */
   1.432 +		if (MATCH(buf, "search")) {
   1.433 +		    if (haveenv)	/* skip if have from environ */
   1.434 +			    continue;
   1.435 +		    cp = buf + sizeof("search") - 1;
   1.436 +		    while (*cp == ' ' || *cp == '\t')
   1.437 +			    cp++;
   1.438 +		    if ((*cp == '\0') || (*cp == '\n'))
   1.439 +			    continue;
   1.440 +		    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
   1.441 +		    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
   1.442 +		    if ((cp = strchr(statp->defdname, '\n')) != NULL)
   1.443 +			    *cp = '\0';
   1.444 +		    /*
   1.445 +		     * Set search list to be blank-separated strings
   1.446 +		     * on rest of line.
   1.447 +		     */
   1.448 +		    cp = statp->defdname;
   1.449 +		    pp = statp->dnsrch;
   1.450 +		    *pp++ = cp;
   1.451 +		    for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
   1.452 +			    if (*cp == ' ' || *cp == '\t') {
   1.453 +				    *cp = 0;
   1.454 +				    n = 1;
   1.455 +			    } else if (n) {
   1.456 +				    *pp++ = cp;
   1.457 +				    n = 0;
   1.458 +			    }
   1.459 +		    }
   1.460 +		    /* null terminate last domain if there are excess */
   1.461 +		    while (*cp != '\0' && *cp != ' ' && *cp != '\t')
   1.462 +			    cp++;
   1.463 +		    *cp = '\0';
   1.464 +		    *pp++ = 0;
   1.465 +		    havesearch = 1;
   1.466 +		    continue;
   1.467 +		}
   1.468 +		/* read nameservers to query */
   1.469 +		if (MATCH(buf, "nameserver") && nserv < MAXNS) {
   1.470 +		    struct addrinfo hints, *ai;
   1.471 +		    char sbuf[NI_MAXSERV];
   1.472 +		    const size_t minsiz =
   1.473 +		        sizeof(statp->_u._ext.ext->nsaddrs[0]);
   1.474 +
   1.475 +		    cp = buf + sizeof("nameserver") - 1;
   1.476 +		    while (*cp == ' ' || *cp == '\t')
   1.477 +			cp++;
   1.478 +		    cp[strcspn(cp, ";# \t\n")] = '\0';
   1.479 +		    if ((*cp != '\0') && (*cp != '\n')) {
   1.480 +			memset(&hints, 0, sizeof(hints));
   1.481 +			hints.ai_family = PF_UNSPEC;
   1.482 +			hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
   1.483 +			hints.ai_flags = AI_NUMERICHOST;
   1.484 +			sprintf(sbuf, "%u", NAMESERVER_PORT);
   1.485 +			if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
   1.486 +			    ai->ai_addrlen <= minsiz) {
   1.487 +			    if (statp->_u._ext.ext != NULL) {
   1.488 +				memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
   1.489 +				    ai->ai_addr, ai->ai_addrlen);
   1.490 +			    }
   1.491 +			    if (ai->ai_addrlen <=
   1.492 +			        sizeof(statp->nsaddr_list[nserv])) {
   1.493 +				memcpy(&statp->nsaddr_list[nserv],
   1.494 +				    ai->ai_addr, ai->ai_addrlen);
   1.495 +			    } else
   1.496 +				statp->nsaddr_list[nserv].sin_family = 0;
   1.497 +			    freeaddrinfo(ai);
   1.498 +			    nserv++;
   1.499 +			}
   1.500 +		    }
   1.501 +		    continue;
   1.502 +		}
   1.503 +		if (MATCH(buf, "sortlist")) {
   1.504 +		    struct in_addr a;
   1.505 +
   1.506 +		    cp = buf + sizeof("sortlist") - 1;
   1.507 +		    while (nsort < MAXRESOLVSORT) {
   1.508 +			while (*cp == ' ' || *cp == '\t')
   1.509 +			    cp++;
   1.510 +			if (*cp == '\0' || *cp == '\n' || *cp == ';')
   1.511 +			    break;
   1.512 +			net = cp;
   1.513 +			while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
   1.514 +			       isascii(*cp) && !isspace((unsigned char)*cp))
   1.515 +				cp++;
   1.516 +			n = *cp;
   1.517 +			*cp = 0;
   1.518 +			if (inet_aton(net, &a)) {
   1.519 +			    statp->sort_list[nsort].addr = a;
   1.520 +			    if (ISSORTMASK(n)) {
   1.521 +				*cp++ = n;
   1.522 +				net = cp;
   1.523 +				while (*cp && *cp != ';' &&
   1.524 +					isascii(*cp) &&
   1.525 +					!isspace((unsigned char)*cp))
   1.526 +				    cp++;
   1.527 +				n = *cp;
   1.528 +				*cp = 0;
   1.529 +				if (inet_aton(net, &a)) {
   1.530 +				    statp->sort_list[nsort].mask = a.s_addr;
   1.531 +				} else {
   1.532 +				    statp->sort_list[nsort].mask =
   1.533 +					net_mask(statp->sort_list[nsort].addr);
   1.534 +				}
   1.535 +			    } else {
   1.536 +				statp->sort_list[nsort].mask =
   1.537 +				    net_mask(statp->sort_list[nsort].addr);
   1.538 +			    }
   1.539 +			    nsort++;
   1.540 +			}
   1.541 +			*cp = n;
   1.542 +		    }
   1.543 +		    continue;
   1.544 +		}
   1.545 +		if (MATCH(buf, "options")) {
   1.546 +		    res_setoptions(statp, buf + sizeof("options") - 1, "conf");
   1.547 +		    continue;
   1.548 +		}
   1.549 +	    }
   1.550 +	    if (nserv > 0)
   1.551 +		statp->nscount = nserv;
   1.552 +	    statp->nsort = nsort;
   1.553 +	    (void) fclose(fp);
   1.554 +	}
   1.555 +#endif /* !ANDROID_CHANGES */
   1.556 +/*
   1.557 + * Last chance to get a nameserver.  This should not normally
   1.558 + * be necessary
   1.559 + */
   1.560 +#ifdef NO_RESOLV_CONF
   1.561 +	if(nserv == 0)
   1.562 +		nserv = get_nameservers(statp);
   1.563 +#endif
   1.564 +
   1.565 +	if (statp->defdname[0] == 0 &&
   1.566 +	    gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
   1.567 +	    (cp = strchr(buf, '.')) != NULL)
   1.568 +		strcpy(statp->defdname, cp + 1);
   1.569 +
   1.570 +	/* find components of local domain that might be searched */
   1.571 +	if (havesearch == 0) {
   1.572 +		pp = statp->dnsrch;
   1.573 +		*pp++ = statp->defdname;
   1.574 +		*pp = NULL;
   1.575 +
   1.576 +		dots = 0;
   1.577 +		for (cp = statp->defdname; *cp; cp++)
   1.578 +			dots += (*cp == '.');
   1.579 +
   1.580 +		cp = statp->defdname;
   1.581 +		while (pp < statp->dnsrch + MAXDFLSRCH) {
   1.582 +			if (dots < LOCALDOMAINPARTS)
   1.583 +				break;
   1.584 +			cp = strchr(cp, '.') + 1;    /* we know there is one */
   1.585 +			*pp++ = cp;
   1.586 +			dots--;
   1.587 +		}
   1.588 +		*pp = NULL;
   1.589 +#ifdef DEBUG
   1.590 +		if (statp->options & RES_DEBUG) {
   1.591 +			printf(";; res_init()... default dnsrch list:\n");
   1.592 +			for (pp = statp->dnsrch; *pp; pp++)
   1.593 +				printf(";;\t%s\n", *pp);
   1.594 +			printf(";;\t..END..\n");
   1.595 +		}
   1.596 +#endif
   1.597 +	}
   1.598 +
   1.599 +	if ((cp = getenv("RES_OPTIONS")) != NULL)
   1.600 +		res_setoptions(statp, cp, "env");
   1.601 +	if (nserv > 0) {
   1.602 +		statp->nscount = nserv;
   1.603 +		statp->options |= RES_INIT;
   1.604 +	}
   1.605 +	return (0);
   1.606 +}
   1.607 +
   1.608 +static void
   1.609 +res_setoptions(res_state statp, const char *options, const char *source)
   1.610 +{
   1.611 +	const char *cp = options;
   1.612 +	int i;
   1.613 +	struct __res_state_ext *ext = statp->_u._ext.ext;
   1.614 +
   1.615 +#ifdef DEBUG
   1.616 +	if (statp->options & RES_DEBUG)
   1.617 +		printf(";; res_setoptions(\"%s\", \"%s\")...\n",
   1.618 +		       options, source);
   1.619 +#endif
   1.620 +	while (*cp) {
   1.621 +		/* skip leading and inner runs of spaces */
   1.622 +		while (*cp == ' ' || *cp == '\t')
   1.623 +			cp++;
   1.624 +		/* search for and process individual options */
   1.625 +		if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
   1.626 +			i = atoi(cp + sizeof("ndots:") - 1);
   1.627 +			if (i <= RES_MAXNDOTS)
   1.628 +				statp->ndots = i;
   1.629 +			else
   1.630 +				statp->ndots = RES_MAXNDOTS;
   1.631 +#ifdef DEBUG
   1.632 +			if (statp->options & RES_DEBUG)
   1.633 +				printf(";;\tndots=%d\n", statp->ndots);
   1.634 +#endif
   1.635 +		} else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
   1.636 +			i = atoi(cp + sizeof("timeout:") - 1);
   1.637 +			if (i <= RES_MAXRETRANS)
   1.638 +				statp->retrans = i;
   1.639 +			else
   1.640 +				statp->retrans = RES_MAXRETRANS;
   1.641 +#ifdef DEBUG
   1.642 +			if (statp->options & RES_DEBUG)
   1.643 +				printf(";;\ttimeout=%d\n", statp->retrans);
   1.644 +#endif
   1.645 +		} else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
   1.646 +			i = atoi(cp + sizeof("attempts:") - 1);
   1.647 +			if (i <= RES_MAXRETRY)
   1.648 +				statp->retry = i;
   1.649 +			else
   1.650 +				statp->retry = RES_MAXRETRY;
   1.651 +#ifdef DEBUG
   1.652 +			if (statp->options & RES_DEBUG)
   1.653 +				printf(";;\tattempts=%d\n", statp->retry);
   1.654 +#endif
   1.655 +		} else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
   1.656 +#ifdef DEBUG
   1.657 +			if (!(statp->options & RES_DEBUG)) {
   1.658 +				printf(";; res_setoptions(\"%s\", \"%s\")..\n",
   1.659 +				       options, source);
   1.660 +				statp->options |= RES_DEBUG;
   1.661 +			}
   1.662 +			printf(";;\tdebug\n");
   1.663 +#endif
   1.664 +		} else if (!strncmp(cp, "no_tld_query",
   1.665 +				    sizeof("no_tld_query") - 1) ||
   1.666 +			   !strncmp(cp, "no-tld-query",
   1.667 +				    sizeof("no-tld-query") - 1)) {
   1.668 +			statp->options |= RES_NOTLDQUERY;
   1.669 +		} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
   1.670 +			statp->options |= RES_USE_INET6;
   1.671 +		} else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
   1.672 +			statp->options |= RES_ROTATE;
   1.673 +		} else if (!strncmp(cp, "no-check-names",
   1.674 +				    sizeof("no-check-names") - 1)) {
   1.675 +			statp->options |= RES_NOCHECKNAME;
   1.676 +		}
   1.677 +#ifdef RES_USE_EDNS0
   1.678 +		else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
   1.679 +			statp->options |= RES_USE_EDNS0;
   1.680 +		}
   1.681 +#endif
   1.682 +		else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
   1.683 +			statp->options |= RES_USE_DNAME;
   1.684 +		}
   1.685 +		else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
   1.686 +			if (ext == NULL)
   1.687 +				goto skip;
   1.688 +			cp += sizeof("nibble:") - 1;
   1.689 +			i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
   1.690 +			strncpy(ext->nsuffix, cp, (size_t)i);
   1.691 +			ext->nsuffix[i] = '\0';
   1.692 +		}
   1.693 +		else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
   1.694 +			if (ext == NULL)
   1.695 +				goto skip;
   1.696 +			cp += sizeof("nibble2:") - 1;
   1.697 +			i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
   1.698 +			strncpy(ext->nsuffix2, cp, (size_t)i);
   1.699 +			ext->nsuffix2[i] = '\0';
   1.700 +		}
   1.701 +		else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
   1.702 +			cp += sizeof("v6revmode:") - 1;
   1.703 +			/* "nibble" and "bitstring" used to be valid */
   1.704 +			if (!strncmp(cp, "single", sizeof("single") - 1)) {
   1.705 +				statp->options |= RES_NO_NIBBLE2;
   1.706 +			} else if (!strncmp(cp, "both", sizeof("both") - 1)) {
   1.707 +				statp->options &=
   1.708 +					 ~RES_NO_NIBBLE2;
   1.709 +			}
   1.710 +		}
   1.711 +		else {
   1.712 +			/* XXX - print a warning here? */
   1.713 +		}
   1.714 +   skip:
   1.715 +		/* skip to next run of spaces */
   1.716 +		while (*cp && *cp != ' ' && *cp != '\t')
   1.717 +			cp++;
   1.718 +	}
   1.719 +}
   1.720 +
   1.721 +/* XXX - should really support CIDR which means explicit masks always. */
   1.722 +static u_int32_t
   1.723 +net_mask(in)		/* XXX - should really use system's version of this */
   1.724 +	struct in_addr in;
   1.725 +{
   1.726 +	register u_int32_t i = ntohl(in.s_addr);
   1.727 +
   1.728 +	if (IN_CLASSA(i))
   1.729 +		return (htonl(IN_CLASSA_NET));
   1.730 +	else if (IN_CLASSB(i))
   1.731 +		return (htonl(IN_CLASSB_NET));
   1.732 +	return (htonl(IN_CLASSC_NET));
   1.733 +}
   1.734 +
   1.735 +u_int
   1.736 +res_randomid(void) {
   1.737 +	struct timeval now;
   1.738 +
   1.739 +	gettimeofday(&now, NULL);
   1.740 +	return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
   1.741 +}
   1.742 +
   1.743 +/*
   1.744 + * This routine is for closing the socket if a virtual circuit is used and
   1.745 + * the program wants to close it.  This provides support for endhostent()
   1.746 + * which expects to close the socket.
   1.747 + *
   1.748 + * This routine is not expected to be user visible.
   1.749 + */
   1.750 +void
   1.751 +res_nclose(res_state statp) {
   1.752 +	int ns;
   1.753 +
   1.754 +	if (statp->_vcsock >= 0) {
   1.755 +		(void) close(statp->_vcsock);
   1.756 +		statp->_vcsock = -1;
   1.757 +		statp->_flags &= ~(RES_F_VC | RES_F_CONN);
   1.758 +	}
   1.759 +	for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
   1.760 +		if (statp->_u._ext.nssocks[ns] != -1) {
   1.761 +			(void) close(statp->_u._ext.nssocks[ns]);
   1.762 +			statp->_u._ext.nssocks[ns] = -1;
   1.763 +		}
   1.764 +	}
   1.765 +}
   1.766 +
   1.767 +void
   1.768 +res_ndestroy(res_state statp) {
   1.769 +	res_nclose(statp);
   1.770 +	if (statp->_u._ext.ext != NULL)
   1.771 +		free(statp->_u._ext.ext);
   1.772 +	statp->options &= ~RES_INIT;
   1.773 +	statp->_u._ext.ext = NULL;
   1.774 +}
   1.775 +
   1.776 +const char *
   1.777 +res_get_nibblesuffix(res_state statp) {
   1.778 +	if (statp->_u._ext.ext)
   1.779 +		return (statp->_u._ext.ext->nsuffix);
   1.780 +	return ("ip6.arpa");
   1.781 +}
   1.782 +
   1.783 +const char *
   1.784 +res_get_nibblesuffix2(res_state statp) {
   1.785 +	if (statp->_u._ext.ext)
   1.786 +		return (statp->_u._ext.ext->nsuffix2);
   1.787 +	return ("ip6.int");
   1.788 +}
   1.789 +
   1.790 +void
   1.791 +res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
   1.792 +	int i, nserv;
   1.793 +	size_t size;
   1.794 +
   1.795 +	/* close open servers */
   1.796 +	res_nclose(statp);
   1.797 +
   1.798 +	/* cause rtt times to be forgotten */
   1.799 +	statp->_u._ext.nscount = 0;
   1.800 +
   1.801 +	nserv = 0;
   1.802 +	for (i = 0; i < cnt && nserv < MAXNS; i++) {
   1.803 +		switch (set->sin.sin_family) {
   1.804 +		case AF_INET:
   1.805 +			size = sizeof(set->sin);
   1.806 +			if (statp->_u._ext.ext)
   1.807 +				memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
   1.808 +					&set->sin, size);
   1.809 +			if (size <= sizeof(statp->nsaddr_list[nserv]))
   1.810 +				memcpy(&statp->nsaddr_list[nserv],
   1.811 +					&set->sin, size);
   1.812 +#ifdef notdef
   1.813 +			else
   1.814 +				statp->nsaddr_list[nserv].sin_family = 0;
   1.815 +#endif
   1.816 +			nserv++;
   1.817 +			break;
   1.818 +
   1.819 +#ifdef HAS_INET6_STRUCTS
   1.820 +		case AF_INET6:
   1.821 +			size = sizeof(set->sin6);
   1.822 +			if (statp->_u._ext.ext)
   1.823 +				memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
   1.824 +					&set->sin6, size);
   1.825 +			if (size <= sizeof(statp->nsaddr_list[nserv]))
   1.826 +				memcpy(&statp->nsaddr_list[nserv],
   1.827 +					&set->sin6, size);
   1.828 +			else
   1.829 +				statp->nsaddr_list[nserv].sin_family = 0;
   1.830 +			nserv++;
   1.831 +			break;
   1.832 +#endif
   1.833 +
   1.834 +		default:
   1.835 +			break;
   1.836 +		}
   1.837 +		set++;
   1.838 +	}
   1.839 +	statp->nscount = nserv;
   1.840 +
   1.841 +}
   1.842 +
   1.843 +int
   1.844 +res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
   1.845 +	int i;
   1.846 +	size_t size;
   1.847 +	u_int16_t family;
   1.848 +
   1.849 +	for (i = 0; i < statp->nscount && i < cnt; i++) {
   1.850 +		if (statp->_u._ext.ext)
   1.851 +			family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
   1.852 +		else
   1.853 +			family = statp->nsaddr_list[i].sin_family;
   1.854 +
   1.855 +		switch (family) {
   1.856 +		case AF_INET:
   1.857 +			size = sizeof(set->sin);
   1.858 +			if (statp->_u._ext.ext)
   1.859 +				memcpy(&set->sin,
   1.860 +				       &statp->_u._ext.ext->nsaddrs[i],
   1.861 +				       size);
   1.862 +			else
   1.863 +				memcpy(&set->sin, &statp->nsaddr_list[i],
   1.864 +				       size);
   1.865 +			break;
   1.866 +
   1.867 +#ifdef HAS_INET6_STRUCTS
   1.868 +		case AF_INET6:
   1.869 +			size = sizeof(set->sin6);
   1.870 +			if (statp->_u._ext.ext)
   1.871 +				memcpy(&set->sin6,
   1.872 +				       &statp->_u._ext.ext->nsaddrs[i],
   1.873 +				       size);
   1.874 +			else
   1.875 +				memcpy(&set->sin6, &statp->nsaddr_list[i],
   1.876 +				       size);
   1.877 +			break;
   1.878 +#endif
   1.879 +
   1.880 +		default:
   1.881 +			set->sin.sin_family = 0;
   1.882 +			break;
   1.883 +		}
   1.884 +		set++;
   1.885 +	}
   1.886 +	return (statp->nscount);
   1.887 +}
   1.888 +
   1.889 +#ifdef ANDROID_CHANGES
   1.890 +static int _get_dns_change_count()
   1.891 +{
   1.892 +	if (dns_change_prop == NULL) {
   1.893 +		dns_change_prop = __system_property_find(DNS_CHANGE_PROP_NAME);
   1.894 +	}
   1.895 +	if (dns_change_prop != NULL) {
   1.896 +		char propvalue[PROP_VALUE_MAX];
   1.897 +		if (__system_property_read(dns_change_prop, NULL, propvalue) >= 1) {
   1.898 +			return atoi(propvalue);
   1.899 +		}
   1.900 +	}
   1.901 +	return -1;
   1.902 +}
   1.903 +
   1.904 +int res_get_dns_changed()
   1.905 +{
   1.906 +	int change_count;
   1.907 +
   1.908 +	change_count = _get_dns_change_count();
   1.909 +	if (change_count != dns_last_change_counter) {
   1.910 +		if (change_count != -1) {
   1.911 +			dns_last_change_counter = change_count;
   1.912 +		}
   1.913 +		return 1;
   1.914 +	} else {
   1.915 +		return 0;
   1.916 +	}
   1.917 +}
   1.918 +#endif /* ANDROID_CHANGES */

mercurial