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.
michael@0 | 1 | /* $NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $ */ |
michael@0 | 2 | |
michael@0 | 3 | /* |
michael@0 | 4 | * Copyright (c) 1985, 1989, 1993 |
michael@0 | 5 | * The Regents of the University of California. All rights reserved. |
michael@0 | 6 | * |
michael@0 | 7 | * Redistribution and use in source and binary forms, with or without |
michael@0 | 8 | * modification, are permitted provided that the following conditions |
michael@0 | 9 | * are met: |
michael@0 | 10 | * 1. Redistributions of source code must retain the above copyright |
michael@0 | 11 | * notice, this list of conditions and the following disclaimer. |
michael@0 | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
michael@0 | 13 | * notice, this list of conditions and the following disclaimer in the |
michael@0 | 14 | * documentation and/or other materials provided with the distribution. |
michael@0 | 15 | * 3. All advertising materials mentioning features or use of this software |
michael@0 | 16 | * must display the following acknowledgement: |
michael@0 | 17 | * This product includes software developed by the University of |
michael@0 | 18 | * California, Berkeley and its contributors. |
michael@0 | 19 | * 4. Neither the name of the University nor the names of its contributors |
michael@0 | 20 | * may be used to endorse or promote products derived from this software |
michael@0 | 21 | * without specific prior written permission. |
michael@0 | 22 | * |
michael@0 | 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
michael@0 | 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
michael@0 | 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
michael@0 | 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
michael@0 | 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
michael@0 | 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
michael@0 | 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
michael@0 | 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
michael@0 | 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
michael@0 | 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
michael@0 | 33 | * SUCH DAMAGE. |
michael@0 | 34 | */ |
michael@0 | 35 | |
michael@0 | 36 | /* |
michael@0 | 37 | * Portions Copyright (c) 1993 by Digital Equipment Corporation. |
michael@0 | 38 | * |
michael@0 | 39 | * Permission to use, copy, modify, and distribute this software for any |
michael@0 | 40 | * purpose with or without fee is hereby granted, provided that the above |
michael@0 | 41 | * copyright notice and this permission notice appear in all copies, and that |
michael@0 | 42 | * the name of Digital Equipment Corporation not be used in advertising or |
michael@0 | 43 | * publicity pertaining to distribution of the document or software without |
michael@0 | 44 | * specific, written prior permission. |
michael@0 | 45 | * |
michael@0 | 46 | * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL |
michael@0 | 47 | * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES |
michael@0 | 48 | * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT |
michael@0 | 49 | * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
michael@0 | 50 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
michael@0 | 51 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS |
michael@0 | 52 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
michael@0 | 53 | * SOFTWARE. |
michael@0 | 54 | */ |
michael@0 | 55 | |
michael@0 | 56 | /* |
michael@0 | 57 | * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") |
michael@0 | 58 | * Portions Copyright (c) 1996-1999 by Internet Software Consortium. |
michael@0 | 59 | * |
michael@0 | 60 | * Permission to use, copy, modify, and distribute this software for any |
michael@0 | 61 | * purpose with or without fee is hereby granted, provided that the above |
michael@0 | 62 | * copyright notice and this permission notice appear in all copies. |
michael@0 | 63 | * |
michael@0 | 64 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES |
michael@0 | 65 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
michael@0 | 66 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR |
michael@0 | 67 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
michael@0 | 68 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
michael@0 | 69 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
michael@0 | 70 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
michael@0 | 71 | */ |
michael@0 | 72 | |
michael@0 | 73 | /* |
michael@0 | 74 | * This version of this file is derived from Android 2.3 "Gingerbread", |
michael@0 | 75 | * which contains uncredited changes by Android/Google developers. It has |
michael@0 | 76 | * been modified in 2011 for use in the Android build of Mozilla Firefox by |
michael@0 | 77 | * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>, |
michael@0 | 78 | * and Steve Workman <sjhworkman@gmail.com>). |
michael@0 | 79 | * These changes are offered under the same license as the original NetBSD |
michael@0 | 80 | * file, whose copyright and license are unchanged above. |
michael@0 | 81 | */ |
michael@0 | 82 | |
michael@0 | 83 | #define ANDROID_CHANGES 1 |
michael@0 | 84 | #define MOZILLE_NECKO_EXCLUDE_CODE 1 |
michael@0 | 85 | |
michael@0 | 86 | #include <sys/cdefs.h> |
michael@0 | 87 | #if defined(LIBC_SCCS) && !defined(lint) |
michael@0 | 88 | #ifdef notdef |
michael@0 | 89 | static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; |
michael@0 | 90 | static const char rcsid[] = "Id: res_init.c,v 1.9.2.5.4.2 2004/03/16 12:34:18 marka Exp"; |
michael@0 | 91 | #else |
michael@0 | 92 | __RCSID("$NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $"); |
michael@0 | 93 | #endif |
michael@0 | 94 | #endif /* LIBC_SCCS and not lint */ |
michael@0 | 95 | |
michael@0 | 96 | |
michael@0 | 97 | |
michael@0 | 98 | #include <sys/types.h> |
michael@0 | 99 | #include <sys/param.h> |
michael@0 | 100 | #include <sys/socket.h> |
michael@0 | 101 | #include <sys/time.h> |
michael@0 | 102 | |
michael@0 | 103 | #include <netinet/in.h> |
michael@0 | 104 | #include <arpa/inet.h> |
michael@0 | 105 | #include "arpa_nameser.h" |
michael@0 | 106 | |
michael@0 | 107 | #include <ctype.h> |
michael@0 | 108 | #include <stdio.h> |
michael@0 | 109 | #include <stdlib.h> |
michael@0 | 110 | #include <string.h> |
michael@0 | 111 | #include <unistd.h> |
michael@0 | 112 | #include <netdb.h> |
michael@0 | 113 | |
michael@0 | 114 | #ifdef ANDROID_CHANGES |
michael@0 | 115 | #include <sys/system_properties.h> |
michael@0 | 116 | #endif /* ANDROID_CHANGES */ |
michael@0 | 117 | |
michael@0 | 118 | #ifndef MIN |
michael@0 | 119 | #define MIN(x,y) ((x)<(y)?(x):(y)) |
michael@0 | 120 | #endif |
michael@0 | 121 | |
michael@0 | 122 | /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ |
michael@0 | 123 | #ifdef ANDROID_CHANGES |
michael@0 | 124 | #include "resolv_private.h" |
michael@0 | 125 | #define MAX_DNS_PROPERTIES 8 |
michael@0 | 126 | #define DNS_PROP_NAME_PREFIX "net.dns" |
michael@0 | 127 | #define DNS_CHANGE_PROP_NAME "net.dnschange" |
michael@0 | 128 | #define DNS_SEARCH_PROP_NAME "net.dns.search" |
michael@0 | 129 | const prop_info *dns_change_prop; |
michael@0 | 130 | int dns_last_change_counter; |
michael@0 | 131 | static int _get_dns_change_count(); |
michael@0 | 132 | #else |
michael@0 | 133 | #include <resolv.h> |
michael@0 | 134 | #endif |
michael@0 | 135 | |
michael@0 | 136 | #include "res_private.h" |
michael@0 | 137 | |
michael@0 | 138 | /* Options. Should all be left alone. */ |
michael@0 | 139 | #ifndef DEBUG |
michael@0 | 140 | #define DEBUG |
michael@0 | 141 | #endif |
michael@0 | 142 | |
michael@0 | 143 | static void res_setoptions __P((res_state, const char *, const char *)); |
michael@0 | 144 | |
michael@0 | 145 | static const char sort_mask[] = "/&"; |
michael@0 | 146 | #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) |
michael@0 | 147 | static u_int32_t net_mask __P((struct in_addr)); |
michael@0 | 148 | |
michael@0 | 149 | #if !defined(isascii) /* XXX - could be a function */ |
michael@0 | 150 | # define isascii(c) (!(c & 0200)) |
michael@0 | 151 | #endif |
michael@0 | 152 | |
michael@0 | 153 | /* |
michael@0 | 154 | * Resolver state default settings. |
michael@0 | 155 | */ |
michael@0 | 156 | |
michael@0 | 157 | /* |
michael@0 | 158 | * Set up default settings. If the configuration file exist, the values |
michael@0 | 159 | * there will have precedence. Otherwise, the server address is set to |
michael@0 | 160 | * INADDR_ANY and the default domain name comes from the gethostname(). |
michael@0 | 161 | * |
michael@0 | 162 | * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 |
michael@0 | 163 | * rather than INADDR_ANY ("0.0.0.0") as the default name server address |
michael@0 | 164 | * since it was noted that INADDR_ANY actually meant ``the first interface |
michael@0 | 165 | * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, |
michael@0 | 166 | * it had to be "up" in order for you to reach your own name server. It |
michael@0 | 167 | * was later decided that since the recommended practice is to always |
michael@0 | 168 | * install local static routes through 127.0.0.1 for all your network |
michael@0 | 169 | * interfaces, that we could solve this problem without a code change. |
michael@0 | 170 | * |
michael@0 | 171 | * The configuration file should always be used, since it is the only way |
michael@0 | 172 | * to specify a default domain. If you are running a server on your local |
michael@0 | 173 | * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" |
michael@0 | 174 | * in the configuration file. |
michael@0 | 175 | * |
michael@0 | 176 | * Return 0 if completes successfully, -1 on error |
michael@0 | 177 | */ |
michael@0 | 178 | int |
michael@0 | 179 | res_ninit(res_state statp) { |
michael@0 | 180 | extern int __res_vinit(res_state, int); |
michael@0 | 181 | |
michael@0 | 182 | return (__res_vinit(statp, 0)); |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | #ifdef ANDROID_CHANGES |
michael@0 | 186 | int load_domain_search_list(res_state statp) { |
michael@0 | 187 | char propvalue[PROP_VALUE_MAX]; |
michael@0 | 188 | register char *cp, **pp; |
michael@0 | 189 | |
michael@0 | 190 | if(__system_property_get(DNS_SEARCH_PROP_NAME, propvalue) >= 1) { |
michael@0 | 191 | strlcpy(statp->defdname, propvalue, sizeof(statp->defdname)); |
michael@0 | 192 | if ((cp = strchr(statp->defdname, '\n')) != NULL) |
michael@0 | 193 | *cp = '\0'; |
michael@0 | 194 | cp = statp->defdname; |
michael@0 | 195 | pp = statp->dnsrch; |
michael@0 | 196 | while ( pp < statp->dnsrch + MAXDNSRCH ) { |
michael@0 | 197 | while (*cp == ' ' || *cp == '\t') /* skip leading white space */ |
michael@0 | 198 | cp++; |
michael@0 | 199 | if (*cp == '\0') /* stop if nothing more */ |
michael@0 | 200 | break; |
michael@0 | 201 | *pp++ = cp; /* record this search domain */ |
michael@0 | 202 | while (*cp) { /* zero-terminate it */ |
michael@0 | 203 | if (*cp == ' ' || *cp == '\t') { |
michael@0 | 204 | *cp++ = '\0'; |
michael@0 | 205 | break; |
michael@0 | 206 | } |
michael@0 | 207 | cp++; |
michael@0 | 208 | } |
michael@0 | 209 | } |
michael@0 | 210 | *pp = NULL; /* statp->dnsrch has MAXDNSRCH+1 items */ |
michael@0 | 211 | if (pp > statp->dnsrch) |
michael@0 | 212 | return 1; |
michael@0 | 213 | } |
michael@0 | 214 | statp->defdname[0] = '\0'; /* no default domain name on Android */ |
michael@0 | 215 | statp->dnsrch[0] = NULL; |
michael@0 | 216 | return 0; |
michael@0 | 217 | } |
michael@0 | 218 | #endif |
michael@0 | 219 | |
michael@0 | 220 | /* This function has to be reachable by res_data.c but not publicly. */ |
michael@0 | 221 | int |
michael@0 | 222 | __res_vinit(res_state statp, int preinit) { |
michael@0 | 223 | register FILE *fp; |
michael@0 | 224 | register char *cp, **pp; |
michael@0 | 225 | register int n; |
michael@0 | 226 | char buf[BUFSIZ]; |
michael@0 | 227 | int nserv = 0; /* number of nameserver records read from file */ |
michael@0 | 228 | int haveenv = 0; |
michael@0 | 229 | int havesearch = 0; |
michael@0 | 230 | int nsort = 0; |
michael@0 | 231 | char *net; |
michael@0 | 232 | int dots; |
michael@0 | 233 | union res_sockaddr_union u[2]; |
michael@0 | 234 | #ifdef ANDROID_CHANGES |
michael@0 | 235 | pid_t mypid = getpid(); |
michael@0 | 236 | int use_proc_props = 0; |
michael@0 | 237 | int found_prop; |
michael@0 | 238 | char dnsProperty[PROP_VALUE_MAX]; |
michael@0 | 239 | #endif |
michael@0 | 240 | |
michael@0 | 241 | if (!preinit) { |
michael@0 | 242 | statp->retrans = RES_TIMEOUT; |
michael@0 | 243 | statp->retry = RES_DFLRETRY; |
michael@0 | 244 | statp->options = RES_DEFAULT; |
michael@0 | 245 | statp->id = res_randomid(); |
michael@0 | 246 | } |
michael@0 | 247 | |
michael@0 | 248 | if ((statp->options & RES_INIT) != 0U) |
michael@0 | 249 | res_ndestroy(statp); |
michael@0 | 250 | |
michael@0 | 251 | memset(u, 0, sizeof(u)); |
michael@0 | 252 | #ifdef USELOOPBACK |
michael@0 | 253 | u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); |
michael@0 | 254 | #else |
michael@0 | 255 | u[nserv].sin.sin_addr.s_addr = INADDR_ANY; |
michael@0 | 256 | #endif |
michael@0 | 257 | u[nserv].sin.sin_family = AF_INET; |
michael@0 | 258 | u[nserv].sin.sin_port = htons(NAMESERVER_PORT); |
michael@0 | 259 | #ifdef HAVE_SA_LEN |
michael@0 | 260 | u[nserv].sin.sin_len = sizeof(struct sockaddr_in); |
michael@0 | 261 | #endif |
michael@0 | 262 | nserv++; |
michael@0 | 263 | #ifdef HAS_INET6_STRUCTS |
michael@0 | 264 | #ifdef USELOOPBACK |
michael@0 | 265 | u[nserv].sin6.sin6_addr = in6addr_loopback; |
michael@0 | 266 | #else |
michael@0 | 267 | u[nserv].sin6.sin6_addr = in6addr_any; |
michael@0 | 268 | #endif |
michael@0 | 269 | u[nserv].sin6.sin6_family = AF_INET6; |
michael@0 | 270 | u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT); |
michael@0 | 271 | #ifdef HAVE_SA_LEN |
michael@0 | 272 | u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6); |
michael@0 | 273 | #endif |
michael@0 | 274 | nserv++; |
michael@0 | 275 | #endif |
michael@0 | 276 | statp->nscount = 0; |
michael@0 | 277 | statp->ndots = 1; |
michael@0 | 278 | statp->pfcode = 0; |
michael@0 | 279 | statp->_vcsock = -1; |
michael@0 | 280 | statp->_flags = 0; |
michael@0 | 281 | statp->qhook = NULL; |
michael@0 | 282 | statp->rhook = NULL; |
michael@0 | 283 | statp->_u._ext.nscount = 0; |
michael@0 | 284 | statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); |
michael@0 | 285 | if (statp->_u._ext.ext != NULL) { |
michael@0 | 286 | memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); |
michael@0 | 287 | statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; |
michael@0 | 288 | strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); |
michael@0 | 289 | strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); |
michael@0 | 290 | } |
michael@0 | 291 | statp->nsort = 0; |
michael@0 | 292 | res_setservers(statp, u, nserv); |
michael@0 | 293 | |
michael@0 | 294 | #if 0 /* IGNORE THE ENVIRONMENT */ |
michael@0 | 295 | /* Allow user to override the local domain definition */ |
michael@0 | 296 | if ((cp = getenv("LOCALDOMAIN")) != NULL) { |
michael@0 | 297 | (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); |
michael@0 | 298 | statp->defdname[sizeof(statp->defdname) - 1] = '\0'; |
michael@0 | 299 | haveenv++; |
michael@0 | 300 | |
michael@0 | 301 | /* |
michael@0 | 302 | * Set search list to be blank-separated strings |
michael@0 | 303 | * from rest of env value. Permits users of LOCALDOMAIN |
michael@0 | 304 | * to still have a search list, and anyone to set the |
michael@0 | 305 | * one that they want to use as an individual (even more |
michael@0 | 306 | * important now that the rfc1535 stuff restricts searches) |
michael@0 | 307 | */ |
michael@0 | 308 | cp = statp->defdname; |
michael@0 | 309 | pp = statp->dnsrch; |
michael@0 | 310 | *pp++ = cp; |
michael@0 | 311 | for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { |
michael@0 | 312 | if (*cp == '\n') /* silly backwards compat */ |
michael@0 | 313 | break; |
michael@0 | 314 | else if (*cp == ' ' || *cp == '\t') { |
michael@0 | 315 | *cp = 0; |
michael@0 | 316 | n = 1; |
michael@0 | 317 | } else if (n) { |
michael@0 | 318 | *pp++ = cp; |
michael@0 | 319 | n = 0; |
michael@0 | 320 | havesearch = 1; |
michael@0 | 321 | } |
michael@0 | 322 | } |
michael@0 | 323 | /* null terminate last domain if there are excess */ |
michael@0 | 324 | while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') |
michael@0 | 325 | cp++; |
michael@0 | 326 | *cp = '\0'; |
michael@0 | 327 | *pp++ = 0; |
michael@0 | 328 | } |
michael@0 | 329 | if (nserv > 0) |
michael@0 | 330 | statp->nscount = nserv; |
michael@0 | 331 | #endif |
michael@0 | 332 | #ifdef ANDROID_CHANGES /* READ FROM SYSTEM PROPERTIES */ |
michael@0 | 333 | dns_last_change_counter = _get_dns_change_count(); |
michael@0 | 334 | |
michael@0 | 335 | nserv = 0; |
michael@0 | 336 | for(n = 1; n <= MAX_DNS_PROPERTIES && nserv < MAXNS; n++) { |
michael@0 | 337 | char propname[PROP_NAME_MAX]; |
michael@0 | 338 | char propvalue[PROP_VALUE_MAX]; |
michael@0 | 339 | |
michael@0 | 340 | struct addrinfo hints, *ai; |
michael@0 | 341 | char sbuf[NI_MAXSERV]; |
michael@0 | 342 | const size_t minsiz = sizeof(statp->_u._ext.ext->nsaddrs[0]); |
michael@0 | 343 | |
michael@0 | 344 | /* |
michael@0 | 345 | * Check first for process-specific properties, and if those don't |
michael@0 | 346 | * exist, try the generic properties. |
michael@0 | 347 | */ |
michael@0 | 348 | found_prop = 0; |
michael@0 | 349 | if (n == 1 || use_proc_props) { |
michael@0 | 350 | snprintf(propname, sizeof(propname), "%s%d.%d", DNS_PROP_NAME_PREFIX, n, mypid); |
michael@0 | 351 | if(__system_property_get(propname, propvalue) < 1) { |
michael@0 | 352 | if (use_proc_props) { |
michael@0 | 353 | break; |
michael@0 | 354 | } |
michael@0 | 355 | } else { |
michael@0 | 356 | found_prop = 1; |
michael@0 | 357 | use_proc_props = 1; |
michael@0 | 358 | } |
michael@0 | 359 | } |
michael@0 | 360 | if (!found_prop) { |
michael@0 | 361 | snprintf(propname, sizeof(propname), "%s%d", DNS_PROP_NAME_PREFIX, n); |
michael@0 | 362 | if(__system_property_get(propname, propvalue) < 1) { |
michael@0 | 363 | break; |
michael@0 | 364 | } |
michael@0 | 365 | } |
michael@0 | 366 | |
michael@0 | 367 | cp = propvalue; |
michael@0 | 368 | |
michael@0 | 369 | while (*cp == ' ' || *cp == '\t') |
michael@0 | 370 | cp++; |
michael@0 | 371 | cp[strcspn(cp, ";# \t\n")] = '\0'; |
michael@0 | 372 | if ((*cp != '\0') && (*cp != '\n')) { |
michael@0 | 373 | memset(&hints, 0, sizeof(hints)); |
michael@0 | 374 | hints.ai_family = PF_UNSPEC; |
michael@0 | 375 | hints.ai_socktype = SOCK_DGRAM; /*dummy*/ |
michael@0 | 376 | hints.ai_flags = AI_NUMERICHOST; |
michael@0 | 377 | sprintf(sbuf, "%u", NAMESERVER_PORT); |
michael@0 | 378 | if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && |
michael@0 | 379 | (size_t)ai->ai_addrlen <= minsiz) { |
michael@0 | 380 | if (statp->_u._ext.ext != NULL) { |
michael@0 | 381 | memcpy(&statp->_u._ext.ext->nsaddrs[nserv], |
michael@0 | 382 | ai->ai_addr, ai->ai_addrlen); |
michael@0 | 383 | } |
michael@0 | 384 | if ((size_t)ai->ai_addrlen <= |
michael@0 | 385 | sizeof(statp->nsaddr_list[nserv])) { |
michael@0 | 386 | memcpy(&statp->nsaddr_list[nserv], |
michael@0 | 387 | ai->ai_addr, ai->ai_addrlen); |
michael@0 | 388 | } else { |
michael@0 | 389 | statp->nsaddr_list[nserv].sin_family = 0; |
michael@0 | 390 | } |
michael@0 | 391 | freeaddrinfo(ai); |
michael@0 | 392 | nserv++; |
michael@0 | 393 | } |
michael@0 | 394 | } |
michael@0 | 395 | } |
michael@0 | 396 | |
michael@0 | 397 | /* Add the domain search list */ |
michael@0 | 398 | havesearch = load_domain_search_list(statp); |
michael@0 | 399 | #else /* !ANDROID_CHANGES - IGNORE resolv.conf in Android */ |
michael@0 | 400 | #define MATCH(line, name) \ |
michael@0 | 401 | (!strncmp(line, name, sizeof(name) - 1) && \ |
michael@0 | 402 | (line[sizeof(name) - 1] == ' ' || \ |
michael@0 | 403 | line[sizeof(name) - 1] == '\t')) |
michael@0 | 404 | |
michael@0 | 405 | nserv = 0; |
michael@0 | 406 | if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { |
michael@0 | 407 | /* read the config file */ |
michael@0 | 408 | while (fgets(buf, sizeof(buf), fp) != NULL) { |
michael@0 | 409 | /* skip comments */ |
michael@0 | 410 | if (*buf == ';' || *buf == '#') |
michael@0 | 411 | continue; |
michael@0 | 412 | /* read default domain name */ |
michael@0 | 413 | if (MATCH(buf, "domain")) { |
michael@0 | 414 | if (haveenv) /* skip if have from environ */ |
michael@0 | 415 | continue; |
michael@0 | 416 | cp = buf + sizeof("domain") - 1; |
michael@0 | 417 | while (*cp == ' ' || *cp == '\t') |
michael@0 | 418 | cp++; |
michael@0 | 419 | if ((*cp == '\0') || (*cp == '\n')) |
michael@0 | 420 | continue; |
michael@0 | 421 | strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); |
michael@0 | 422 | statp->defdname[sizeof(statp->defdname) - 1] = '\0'; |
michael@0 | 423 | if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) |
michael@0 | 424 | *cp = '\0'; |
michael@0 | 425 | havesearch = 0; |
michael@0 | 426 | continue; |
michael@0 | 427 | } |
michael@0 | 428 | /* set search list */ |
michael@0 | 429 | if (MATCH(buf, "search")) { |
michael@0 | 430 | if (haveenv) /* skip if have from environ */ |
michael@0 | 431 | continue; |
michael@0 | 432 | cp = buf + sizeof("search") - 1; |
michael@0 | 433 | while (*cp == ' ' || *cp == '\t') |
michael@0 | 434 | cp++; |
michael@0 | 435 | if ((*cp == '\0') || (*cp == '\n')) |
michael@0 | 436 | continue; |
michael@0 | 437 | strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); |
michael@0 | 438 | statp->defdname[sizeof(statp->defdname) - 1] = '\0'; |
michael@0 | 439 | if ((cp = strchr(statp->defdname, '\n')) != NULL) |
michael@0 | 440 | *cp = '\0'; |
michael@0 | 441 | /* |
michael@0 | 442 | * Set search list to be blank-separated strings |
michael@0 | 443 | * on rest of line. |
michael@0 | 444 | */ |
michael@0 | 445 | cp = statp->defdname; |
michael@0 | 446 | pp = statp->dnsrch; |
michael@0 | 447 | *pp++ = cp; |
michael@0 | 448 | for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { |
michael@0 | 449 | if (*cp == ' ' || *cp == '\t') { |
michael@0 | 450 | *cp = 0; |
michael@0 | 451 | n = 1; |
michael@0 | 452 | } else if (n) { |
michael@0 | 453 | *pp++ = cp; |
michael@0 | 454 | n = 0; |
michael@0 | 455 | } |
michael@0 | 456 | } |
michael@0 | 457 | /* null terminate last domain if there are excess */ |
michael@0 | 458 | while (*cp != '\0' && *cp != ' ' && *cp != '\t') |
michael@0 | 459 | cp++; |
michael@0 | 460 | *cp = '\0'; |
michael@0 | 461 | *pp++ = 0; |
michael@0 | 462 | havesearch = 1; |
michael@0 | 463 | continue; |
michael@0 | 464 | } |
michael@0 | 465 | /* read nameservers to query */ |
michael@0 | 466 | if (MATCH(buf, "nameserver") && nserv < MAXNS) { |
michael@0 | 467 | struct addrinfo hints, *ai; |
michael@0 | 468 | char sbuf[NI_MAXSERV]; |
michael@0 | 469 | const size_t minsiz = |
michael@0 | 470 | sizeof(statp->_u._ext.ext->nsaddrs[0]); |
michael@0 | 471 | |
michael@0 | 472 | cp = buf + sizeof("nameserver") - 1; |
michael@0 | 473 | while (*cp == ' ' || *cp == '\t') |
michael@0 | 474 | cp++; |
michael@0 | 475 | cp[strcspn(cp, ";# \t\n")] = '\0'; |
michael@0 | 476 | if ((*cp != '\0') && (*cp != '\n')) { |
michael@0 | 477 | memset(&hints, 0, sizeof(hints)); |
michael@0 | 478 | hints.ai_family = PF_UNSPEC; |
michael@0 | 479 | hints.ai_socktype = SOCK_DGRAM; /*dummy*/ |
michael@0 | 480 | hints.ai_flags = AI_NUMERICHOST; |
michael@0 | 481 | sprintf(sbuf, "%u", NAMESERVER_PORT); |
michael@0 | 482 | if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && |
michael@0 | 483 | ai->ai_addrlen <= minsiz) { |
michael@0 | 484 | if (statp->_u._ext.ext != NULL) { |
michael@0 | 485 | memcpy(&statp->_u._ext.ext->nsaddrs[nserv], |
michael@0 | 486 | ai->ai_addr, ai->ai_addrlen); |
michael@0 | 487 | } |
michael@0 | 488 | if (ai->ai_addrlen <= |
michael@0 | 489 | sizeof(statp->nsaddr_list[nserv])) { |
michael@0 | 490 | memcpy(&statp->nsaddr_list[nserv], |
michael@0 | 491 | ai->ai_addr, ai->ai_addrlen); |
michael@0 | 492 | } else |
michael@0 | 493 | statp->nsaddr_list[nserv].sin_family = 0; |
michael@0 | 494 | freeaddrinfo(ai); |
michael@0 | 495 | nserv++; |
michael@0 | 496 | } |
michael@0 | 497 | } |
michael@0 | 498 | continue; |
michael@0 | 499 | } |
michael@0 | 500 | if (MATCH(buf, "sortlist")) { |
michael@0 | 501 | struct in_addr a; |
michael@0 | 502 | |
michael@0 | 503 | cp = buf + sizeof("sortlist") - 1; |
michael@0 | 504 | while (nsort < MAXRESOLVSORT) { |
michael@0 | 505 | while (*cp == ' ' || *cp == '\t') |
michael@0 | 506 | cp++; |
michael@0 | 507 | if (*cp == '\0' || *cp == '\n' || *cp == ';') |
michael@0 | 508 | break; |
michael@0 | 509 | net = cp; |
michael@0 | 510 | while (*cp && !ISSORTMASK(*cp) && *cp != ';' && |
michael@0 | 511 | isascii(*cp) && !isspace((unsigned char)*cp)) |
michael@0 | 512 | cp++; |
michael@0 | 513 | n = *cp; |
michael@0 | 514 | *cp = 0; |
michael@0 | 515 | if (inet_aton(net, &a)) { |
michael@0 | 516 | statp->sort_list[nsort].addr = a; |
michael@0 | 517 | if (ISSORTMASK(n)) { |
michael@0 | 518 | *cp++ = n; |
michael@0 | 519 | net = cp; |
michael@0 | 520 | while (*cp && *cp != ';' && |
michael@0 | 521 | isascii(*cp) && |
michael@0 | 522 | !isspace((unsigned char)*cp)) |
michael@0 | 523 | cp++; |
michael@0 | 524 | n = *cp; |
michael@0 | 525 | *cp = 0; |
michael@0 | 526 | if (inet_aton(net, &a)) { |
michael@0 | 527 | statp->sort_list[nsort].mask = a.s_addr; |
michael@0 | 528 | } else { |
michael@0 | 529 | statp->sort_list[nsort].mask = |
michael@0 | 530 | net_mask(statp->sort_list[nsort].addr); |
michael@0 | 531 | } |
michael@0 | 532 | } else { |
michael@0 | 533 | statp->sort_list[nsort].mask = |
michael@0 | 534 | net_mask(statp->sort_list[nsort].addr); |
michael@0 | 535 | } |
michael@0 | 536 | nsort++; |
michael@0 | 537 | } |
michael@0 | 538 | *cp = n; |
michael@0 | 539 | } |
michael@0 | 540 | continue; |
michael@0 | 541 | } |
michael@0 | 542 | if (MATCH(buf, "options")) { |
michael@0 | 543 | res_setoptions(statp, buf + sizeof("options") - 1, "conf"); |
michael@0 | 544 | continue; |
michael@0 | 545 | } |
michael@0 | 546 | } |
michael@0 | 547 | if (nserv > 0) |
michael@0 | 548 | statp->nscount = nserv; |
michael@0 | 549 | statp->nsort = nsort; |
michael@0 | 550 | (void) fclose(fp); |
michael@0 | 551 | } |
michael@0 | 552 | #endif /* !ANDROID_CHANGES */ |
michael@0 | 553 | /* |
michael@0 | 554 | * Last chance to get a nameserver. This should not normally |
michael@0 | 555 | * be necessary |
michael@0 | 556 | */ |
michael@0 | 557 | #ifdef NO_RESOLV_CONF |
michael@0 | 558 | if(nserv == 0) |
michael@0 | 559 | nserv = get_nameservers(statp); |
michael@0 | 560 | #endif |
michael@0 | 561 | |
michael@0 | 562 | if (statp->defdname[0] == 0 && |
michael@0 | 563 | gethostname(buf, sizeof(statp->defdname) - 1) == 0 && |
michael@0 | 564 | (cp = strchr(buf, '.')) != NULL) |
michael@0 | 565 | strcpy(statp->defdname, cp + 1); |
michael@0 | 566 | |
michael@0 | 567 | /* find components of local domain that might be searched */ |
michael@0 | 568 | if (havesearch == 0) { |
michael@0 | 569 | pp = statp->dnsrch; |
michael@0 | 570 | *pp++ = statp->defdname; |
michael@0 | 571 | *pp = NULL; |
michael@0 | 572 | |
michael@0 | 573 | dots = 0; |
michael@0 | 574 | for (cp = statp->defdname; *cp; cp++) |
michael@0 | 575 | dots += (*cp == '.'); |
michael@0 | 576 | |
michael@0 | 577 | cp = statp->defdname; |
michael@0 | 578 | while (pp < statp->dnsrch + MAXDFLSRCH) { |
michael@0 | 579 | if (dots < LOCALDOMAINPARTS) |
michael@0 | 580 | break; |
michael@0 | 581 | cp = strchr(cp, '.') + 1; /* we know there is one */ |
michael@0 | 582 | *pp++ = cp; |
michael@0 | 583 | dots--; |
michael@0 | 584 | } |
michael@0 | 585 | *pp = NULL; |
michael@0 | 586 | #ifdef DEBUG |
michael@0 | 587 | if (statp->options & RES_DEBUG) { |
michael@0 | 588 | printf(";; res_init()... default dnsrch list:\n"); |
michael@0 | 589 | for (pp = statp->dnsrch; *pp; pp++) |
michael@0 | 590 | printf(";;\t%s\n", *pp); |
michael@0 | 591 | printf(";;\t..END..\n"); |
michael@0 | 592 | } |
michael@0 | 593 | #endif |
michael@0 | 594 | } |
michael@0 | 595 | |
michael@0 | 596 | if ((cp = getenv("RES_OPTIONS")) != NULL) |
michael@0 | 597 | res_setoptions(statp, cp, "env"); |
michael@0 | 598 | if (nserv > 0) { |
michael@0 | 599 | statp->nscount = nserv; |
michael@0 | 600 | statp->options |= RES_INIT; |
michael@0 | 601 | } |
michael@0 | 602 | return (0); |
michael@0 | 603 | } |
michael@0 | 604 | |
michael@0 | 605 | static void |
michael@0 | 606 | res_setoptions(res_state statp, const char *options, const char *source) |
michael@0 | 607 | { |
michael@0 | 608 | const char *cp = options; |
michael@0 | 609 | int i; |
michael@0 | 610 | struct __res_state_ext *ext = statp->_u._ext.ext; |
michael@0 | 611 | |
michael@0 | 612 | #ifdef DEBUG |
michael@0 | 613 | if (statp->options & RES_DEBUG) |
michael@0 | 614 | printf(";; res_setoptions(\"%s\", \"%s\")...\n", |
michael@0 | 615 | options, source); |
michael@0 | 616 | #endif |
michael@0 | 617 | while (*cp) { |
michael@0 | 618 | /* skip leading and inner runs of spaces */ |
michael@0 | 619 | while (*cp == ' ' || *cp == '\t') |
michael@0 | 620 | cp++; |
michael@0 | 621 | /* search for and process individual options */ |
michael@0 | 622 | if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { |
michael@0 | 623 | i = atoi(cp + sizeof("ndots:") - 1); |
michael@0 | 624 | if (i <= RES_MAXNDOTS) |
michael@0 | 625 | statp->ndots = i; |
michael@0 | 626 | else |
michael@0 | 627 | statp->ndots = RES_MAXNDOTS; |
michael@0 | 628 | #ifdef DEBUG |
michael@0 | 629 | if (statp->options & RES_DEBUG) |
michael@0 | 630 | printf(";;\tndots=%d\n", statp->ndots); |
michael@0 | 631 | #endif |
michael@0 | 632 | } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { |
michael@0 | 633 | i = atoi(cp + sizeof("timeout:") - 1); |
michael@0 | 634 | if (i <= RES_MAXRETRANS) |
michael@0 | 635 | statp->retrans = i; |
michael@0 | 636 | else |
michael@0 | 637 | statp->retrans = RES_MAXRETRANS; |
michael@0 | 638 | #ifdef DEBUG |
michael@0 | 639 | if (statp->options & RES_DEBUG) |
michael@0 | 640 | printf(";;\ttimeout=%d\n", statp->retrans); |
michael@0 | 641 | #endif |
michael@0 | 642 | } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ |
michael@0 | 643 | i = atoi(cp + sizeof("attempts:") - 1); |
michael@0 | 644 | if (i <= RES_MAXRETRY) |
michael@0 | 645 | statp->retry = i; |
michael@0 | 646 | else |
michael@0 | 647 | statp->retry = RES_MAXRETRY; |
michael@0 | 648 | #ifdef DEBUG |
michael@0 | 649 | if (statp->options & RES_DEBUG) |
michael@0 | 650 | printf(";;\tattempts=%d\n", statp->retry); |
michael@0 | 651 | #endif |
michael@0 | 652 | } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { |
michael@0 | 653 | #ifdef DEBUG |
michael@0 | 654 | if (!(statp->options & RES_DEBUG)) { |
michael@0 | 655 | printf(";; res_setoptions(\"%s\", \"%s\")..\n", |
michael@0 | 656 | options, source); |
michael@0 | 657 | statp->options |= RES_DEBUG; |
michael@0 | 658 | } |
michael@0 | 659 | printf(";;\tdebug\n"); |
michael@0 | 660 | #endif |
michael@0 | 661 | } else if (!strncmp(cp, "no_tld_query", |
michael@0 | 662 | sizeof("no_tld_query") - 1) || |
michael@0 | 663 | !strncmp(cp, "no-tld-query", |
michael@0 | 664 | sizeof("no-tld-query") - 1)) { |
michael@0 | 665 | statp->options |= RES_NOTLDQUERY; |
michael@0 | 666 | } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { |
michael@0 | 667 | statp->options |= RES_USE_INET6; |
michael@0 | 668 | } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { |
michael@0 | 669 | statp->options |= RES_ROTATE; |
michael@0 | 670 | } else if (!strncmp(cp, "no-check-names", |
michael@0 | 671 | sizeof("no-check-names") - 1)) { |
michael@0 | 672 | statp->options |= RES_NOCHECKNAME; |
michael@0 | 673 | } |
michael@0 | 674 | #ifdef RES_USE_EDNS0 |
michael@0 | 675 | else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { |
michael@0 | 676 | statp->options |= RES_USE_EDNS0; |
michael@0 | 677 | } |
michael@0 | 678 | #endif |
michael@0 | 679 | else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { |
michael@0 | 680 | statp->options |= RES_USE_DNAME; |
michael@0 | 681 | } |
michael@0 | 682 | else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { |
michael@0 | 683 | if (ext == NULL) |
michael@0 | 684 | goto skip; |
michael@0 | 685 | cp += sizeof("nibble:") - 1; |
michael@0 | 686 | i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); |
michael@0 | 687 | strncpy(ext->nsuffix, cp, (size_t)i); |
michael@0 | 688 | ext->nsuffix[i] = '\0'; |
michael@0 | 689 | } |
michael@0 | 690 | else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { |
michael@0 | 691 | if (ext == NULL) |
michael@0 | 692 | goto skip; |
michael@0 | 693 | cp += sizeof("nibble2:") - 1; |
michael@0 | 694 | i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); |
michael@0 | 695 | strncpy(ext->nsuffix2, cp, (size_t)i); |
michael@0 | 696 | ext->nsuffix2[i] = '\0'; |
michael@0 | 697 | } |
michael@0 | 698 | else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { |
michael@0 | 699 | cp += sizeof("v6revmode:") - 1; |
michael@0 | 700 | /* "nibble" and "bitstring" used to be valid */ |
michael@0 | 701 | if (!strncmp(cp, "single", sizeof("single") - 1)) { |
michael@0 | 702 | statp->options |= RES_NO_NIBBLE2; |
michael@0 | 703 | } else if (!strncmp(cp, "both", sizeof("both") - 1)) { |
michael@0 | 704 | statp->options &= |
michael@0 | 705 | ~RES_NO_NIBBLE2; |
michael@0 | 706 | } |
michael@0 | 707 | } |
michael@0 | 708 | else { |
michael@0 | 709 | /* XXX - print a warning here? */ |
michael@0 | 710 | } |
michael@0 | 711 | skip: |
michael@0 | 712 | /* skip to next run of spaces */ |
michael@0 | 713 | while (*cp && *cp != ' ' && *cp != '\t') |
michael@0 | 714 | cp++; |
michael@0 | 715 | } |
michael@0 | 716 | } |
michael@0 | 717 | |
michael@0 | 718 | /* XXX - should really support CIDR which means explicit masks always. */ |
michael@0 | 719 | static u_int32_t |
michael@0 | 720 | net_mask(in) /* XXX - should really use system's version of this */ |
michael@0 | 721 | struct in_addr in; |
michael@0 | 722 | { |
michael@0 | 723 | register u_int32_t i = ntohl(in.s_addr); |
michael@0 | 724 | |
michael@0 | 725 | if (IN_CLASSA(i)) |
michael@0 | 726 | return (htonl(IN_CLASSA_NET)); |
michael@0 | 727 | else if (IN_CLASSB(i)) |
michael@0 | 728 | return (htonl(IN_CLASSB_NET)); |
michael@0 | 729 | return (htonl(IN_CLASSC_NET)); |
michael@0 | 730 | } |
michael@0 | 731 | |
michael@0 | 732 | u_int |
michael@0 | 733 | res_randomid(void) { |
michael@0 | 734 | struct timeval now; |
michael@0 | 735 | |
michael@0 | 736 | gettimeofday(&now, NULL); |
michael@0 | 737 | return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); |
michael@0 | 738 | } |
michael@0 | 739 | |
michael@0 | 740 | /* |
michael@0 | 741 | * This routine is for closing the socket if a virtual circuit is used and |
michael@0 | 742 | * the program wants to close it. This provides support for endhostent() |
michael@0 | 743 | * which expects to close the socket. |
michael@0 | 744 | * |
michael@0 | 745 | * This routine is not expected to be user visible. |
michael@0 | 746 | */ |
michael@0 | 747 | void |
michael@0 | 748 | res_nclose(res_state statp) { |
michael@0 | 749 | int ns; |
michael@0 | 750 | |
michael@0 | 751 | if (statp->_vcsock >= 0) { |
michael@0 | 752 | (void) close(statp->_vcsock); |
michael@0 | 753 | statp->_vcsock = -1; |
michael@0 | 754 | statp->_flags &= ~(RES_F_VC | RES_F_CONN); |
michael@0 | 755 | } |
michael@0 | 756 | for (ns = 0; ns < statp->_u._ext.nscount; ns++) { |
michael@0 | 757 | if (statp->_u._ext.nssocks[ns] != -1) { |
michael@0 | 758 | (void) close(statp->_u._ext.nssocks[ns]); |
michael@0 | 759 | statp->_u._ext.nssocks[ns] = -1; |
michael@0 | 760 | } |
michael@0 | 761 | } |
michael@0 | 762 | } |
michael@0 | 763 | |
michael@0 | 764 | void |
michael@0 | 765 | res_ndestroy(res_state statp) { |
michael@0 | 766 | res_nclose(statp); |
michael@0 | 767 | if (statp->_u._ext.ext != NULL) |
michael@0 | 768 | free(statp->_u._ext.ext); |
michael@0 | 769 | statp->options &= ~RES_INIT; |
michael@0 | 770 | statp->_u._ext.ext = NULL; |
michael@0 | 771 | } |
michael@0 | 772 | |
michael@0 | 773 | const char * |
michael@0 | 774 | res_get_nibblesuffix(res_state statp) { |
michael@0 | 775 | if (statp->_u._ext.ext) |
michael@0 | 776 | return (statp->_u._ext.ext->nsuffix); |
michael@0 | 777 | return ("ip6.arpa"); |
michael@0 | 778 | } |
michael@0 | 779 | |
michael@0 | 780 | const char * |
michael@0 | 781 | res_get_nibblesuffix2(res_state statp) { |
michael@0 | 782 | if (statp->_u._ext.ext) |
michael@0 | 783 | return (statp->_u._ext.ext->nsuffix2); |
michael@0 | 784 | return ("ip6.int"); |
michael@0 | 785 | } |
michael@0 | 786 | |
michael@0 | 787 | void |
michael@0 | 788 | res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { |
michael@0 | 789 | int i, nserv; |
michael@0 | 790 | size_t size; |
michael@0 | 791 | |
michael@0 | 792 | /* close open servers */ |
michael@0 | 793 | res_nclose(statp); |
michael@0 | 794 | |
michael@0 | 795 | /* cause rtt times to be forgotten */ |
michael@0 | 796 | statp->_u._ext.nscount = 0; |
michael@0 | 797 | |
michael@0 | 798 | nserv = 0; |
michael@0 | 799 | for (i = 0; i < cnt && nserv < MAXNS; i++) { |
michael@0 | 800 | switch (set->sin.sin_family) { |
michael@0 | 801 | case AF_INET: |
michael@0 | 802 | size = sizeof(set->sin); |
michael@0 | 803 | if (statp->_u._ext.ext) |
michael@0 | 804 | memcpy(&statp->_u._ext.ext->nsaddrs[nserv], |
michael@0 | 805 | &set->sin, size); |
michael@0 | 806 | if (size <= sizeof(statp->nsaddr_list[nserv])) |
michael@0 | 807 | memcpy(&statp->nsaddr_list[nserv], |
michael@0 | 808 | &set->sin, size); |
michael@0 | 809 | #ifdef notdef |
michael@0 | 810 | else |
michael@0 | 811 | statp->nsaddr_list[nserv].sin_family = 0; |
michael@0 | 812 | #endif |
michael@0 | 813 | nserv++; |
michael@0 | 814 | break; |
michael@0 | 815 | |
michael@0 | 816 | #ifdef HAS_INET6_STRUCTS |
michael@0 | 817 | case AF_INET6: |
michael@0 | 818 | size = sizeof(set->sin6); |
michael@0 | 819 | if (statp->_u._ext.ext) |
michael@0 | 820 | memcpy(&statp->_u._ext.ext->nsaddrs[nserv], |
michael@0 | 821 | &set->sin6, size); |
michael@0 | 822 | if (size <= sizeof(statp->nsaddr_list[nserv])) |
michael@0 | 823 | memcpy(&statp->nsaddr_list[nserv], |
michael@0 | 824 | &set->sin6, size); |
michael@0 | 825 | else |
michael@0 | 826 | statp->nsaddr_list[nserv].sin_family = 0; |
michael@0 | 827 | nserv++; |
michael@0 | 828 | break; |
michael@0 | 829 | #endif |
michael@0 | 830 | |
michael@0 | 831 | default: |
michael@0 | 832 | break; |
michael@0 | 833 | } |
michael@0 | 834 | set++; |
michael@0 | 835 | } |
michael@0 | 836 | statp->nscount = nserv; |
michael@0 | 837 | |
michael@0 | 838 | } |
michael@0 | 839 | |
michael@0 | 840 | int |
michael@0 | 841 | res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { |
michael@0 | 842 | int i; |
michael@0 | 843 | size_t size; |
michael@0 | 844 | u_int16_t family; |
michael@0 | 845 | |
michael@0 | 846 | for (i = 0; i < statp->nscount && i < cnt; i++) { |
michael@0 | 847 | if (statp->_u._ext.ext) |
michael@0 | 848 | family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; |
michael@0 | 849 | else |
michael@0 | 850 | family = statp->nsaddr_list[i].sin_family; |
michael@0 | 851 | |
michael@0 | 852 | switch (family) { |
michael@0 | 853 | case AF_INET: |
michael@0 | 854 | size = sizeof(set->sin); |
michael@0 | 855 | if (statp->_u._ext.ext) |
michael@0 | 856 | memcpy(&set->sin, |
michael@0 | 857 | &statp->_u._ext.ext->nsaddrs[i], |
michael@0 | 858 | size); |
michael@0 | 859 | else |
michael@0 | 860 | memcpy(&set->sin, &statp->nsaddr_list[i], |
michael@0 | 861 | size); |
michael@0 | 862 | break; |
michael@0 | 863 | |
michael@0 | 864 | #ifdef HAS_INET6_STRUCTS |
michael@0 | 865 | case AF_INET6: |
michael@0 | 866 | size = sizeof(set->sin6); |
michael@0 | 867 | if (statp->_u._ext.ext) |
michael@0 | 868 | memcpy(&set->sin6, |
michael@0 | 869 | &statp->_u._ext.ext->nsaddrs[i], |
michael@0 | 870 | size); |
michael@0 | 871 | else |
michael@0 | 872 | memcpy(&set->sin6, &statp->nsaddr_list[i], |
michael@0 | 873 | size); |
michael@0 | 874 | break; |
michael@0 | 875 | #endif |
michael@0 | 876 | |
michael@0 | 877 | default: |
michael@0 | 878 | set->sin.sin_family = 0; |
michael@0 | 879 | break; |
michael@0 | 880 | } |
michael@0 | 881 | set++; |
michael@0 | 882 | } |
michael@0 | 883 | return (statp->nscount); |
michael@0 | 884 | } |
michael@0 | 885 | |
michael@0 | 886 | #ifdef ANDROID_CHANGES |
michael@0 | 887 | static int _get_dns_change_count() |
michael@0 | 888 | { |
michael@0 | 889 | if (dns_change_prop == NULL) { |
michael@0 | 890 | dns_change_prop = __system_property_find(DNS_CHANGE_PROP_NAME); |
michael@0 | 891 | } |
michael@0 | 892 | if (dns_change_prop != NULL) { |
michael@0 | 893 | char propvalue[PROP_VALUE_MAX]; |
michael@0 | 894 | if (__system_property_read(dns_change_prop, NULL, propvalue) >= 1) { |
michael@0 | 895 | return atoi(propvalue); |
michael@0 | 896 | } |
michael@0 | 897 | } |
michael@0 | 898 | return -1; |
michael@0 | 899 | } |
michael@0 | 900 | |
michael@0 | 901 | int res_get_dns_changed() |
michael@0 | 902 | { |
michael@0 | 903 | int change_count; |
michael@0 | 904 | |
michael@0 | 905 | change_count = _get_dns_change_count(); |
michael@0 | 906 | if (change_count != dns_last_change_counter) { |
michael@0 | 907 | if (change_count != -1) { |
michael@0 | 908 | dns_last_change_counter = change_count; |
michael@0 | 909 | } |
michael@0 | 910 | return 1; |
michael@0 | 911 | } else { |
michael@0 | 912 | return 0; |
michael@0 | 913 | } |
michael@0 | 914 | } |
michael@0 | 915 | #endif /* ANDROID_CHANGES */ |