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