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 /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ 108 #ifdef ANDROID_CHANGES 109 #include "resolv_netid.h" 110 #include "resolv_private.h" 111 #else 112 #include <resolv.h> 113 #endif 114 115 #include "res_private.h" 116 117 /* Options. Should all be left alone. */ 118 #ifndef DEBUG 119 #define DEBUG 120 #endif 121 122 static void res_setoptions __P((res_state, const char *, const char *)); 123 124 #ifdef RESOLVSORT 125 static const char sort_mask[] = "/&"; 126 #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) 127 static uint32_t net_mask(struct in_addr); 128 #endif 129 130 #if !defined(isascii) /* XXX - could be a function */ 131 # define isascii(c) (!(c & 0200)) 132 #endif 133 134 /* 135 * Resolver state default settings. 136 */ 137 138 /* 139 * Set up default settings. If the configuration file exist, the values 140 * there will have precedence. Otherwise, the server address is set to 141 * INADDR_ANY and the default domain name comes from the gethostname(). 142 * 143 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 144 * rather than INADDR_ANY ("0.0.0.0") as the default name server address 145 * since it was noted that INADDR_ANY actually meant ``the first interface 146 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, 147 * it had to be "up" in order for you to reach your own name server. It 148 * was later decided that since the recommended practice is to always 149 * install local static routes through 127.0.0.1 for all your network 150 * interfaces, that we could solve this problem without a code change. 151 * 152 * The configuration file should always be used, since it is the only way 153 * to specify a default domain. If you are running a server on your local 154 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" 155 * in the configuration file. 156 * 157 * Return 0 if completes successfully, -1 on error 158 */ 159 int 160 res_ninit(res_state statp) { 161 extern int __res_vinit(res_state, int); 162 163 return (__res_vinit(statp, 0)); 164 } 165 166 /* This function has to be reachable by res_data.c but not publicly. */ 167 int 168 __res_vinit(res_state statp, int preinit) { 169 #if !defined(__ANDROID__) 170 register FILE *fp; 171 #endif 172 register char *cp, **pp; 173 #if !defined(__ANDROID__) 174 register int n; 175 #endif 176 char buf[BUFSIZ]; 177 int nserv = 0; /* number of nameserver records read from file */ 178 #if !defined(__ANDROID__) 179 int haveenv = 0; 180 #endif 181 int havesearch = 0; 182 #ifdef RESOLVSORT 183 int nsort = 0; 184 #endif 185 #if !defined(__ANDROID__) 186 char *net; 187 #endif 188 int dots; 189 union res_sockaddr_union u[2]; 190 191 if ((statp->options & RES_INIT) != 0U) 192 res_ndestroy(statp); 193 194 if (!preinit) { 195 statp->netid = NETID_UNSET; 196 statp->retrans = RES_TIMEOUT; 197 statp->retry = RES_DFLRETRY; 198 statp->options = RES_DEFAULT; 199 statp->id = res_randomid(); 200 statp->_mark = MARK_UNSET; 201 } 202 203 memset(u, 0, sizeof(u)); 204 #ifdef USELOOPBACK 205 u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); 206 #else 207 u[nserv].sin.sin_addr.s_addr = INADDR_ANY; 208 #endif 209 u[nserv].sin.sin_family = AF_INET; 210 u[nserv].sin.sin_port = htons(NAMESERVER_PORT); 211 #ifdef HAVE_SA_LEN 212 u[nserv].sin.sin_len = sizeof(struct sockaddr_in); 213 #endif 214 nserv++; 215 #ifdef HAS_INET6_STRUCTS 216 #ifdef USELOOPBACK 217 u[nserv].sin6.sin6_addr = in6addr_loopback; 218 #else 219 u[nserv].sin6.sin6_addr = in6addr_any; 220 #endif 221 u[nserv].sin6.sin6_family = AF_INET6; 222 u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT); 223 #ifdef HAVE_SA_LEN 224 u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6); 225 #endif 226 nserv++; 227 #endif 228 statp->nscount = 0; 229 statp->ndots = 1; 230 statp->pfcode = 0; 231 statp->_vcsock = -1; 232 statp->_flags = 0; 233 statp->qhook = NULL; 234 statp->rhook = NULL; 235 statp->_u._ext.nscount = 0; 236 statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); 237 if (statp->_u._ext.ext != NULL) { 238 memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); 239 statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; 240 strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); 241 strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); 242 } 243 statp->nsort = 0; 244 res_setservers(statp, u, nserv); 245 246 #if !defined(__ANDROID__) /* IGNORE THE ENVIRONMENT */ 247 /* Allow user to override the local domain definition */ 248 if ((cp = getenv("LOCALDOMAIN")) != NULL) { 249 (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); 250 statp->defdname[sizeof(statp->defdname) - 1] = '\0'; 251 haveenv++; 252 253 /* 254 * Set search list to be blank-separated strings 255 * from rest of env value. Permits users of LOCALDOMAIN 256 * to still have a search list, and anyone to set the 257 * one that they want to use as an individual (even more 258 * important now that the rfc1535 stuff restricts searches) 259 */ 260 cp = statp->defdname; 261 pp = statp->dnsrch; 262 *pp++ = cp; 263 for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { 264 if (*cp == '\n') /* silly backwards compat */ 265 break; 266 else if (*cp == ' ' || *cp == '\t') { 267 *cp = 0; 268 n = 1; 269 } else if (n) { 270 *pp++ = cp; 271 n = 0; 272 havesearch = 1; 273 } 274 } 275 /* null terminate last domain if there are excess */ 276 while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') 277 cp++; 278 *cp = '\0'; 279 *pp++ = 0; 280 } 281 if (nserv > 0) 282 statp->nscount = nserv; 283 #endif 284 285 #ifndef ANDROID_CHANGES /* !ANDROID_CHANGES - IGNORE resolv.conf in Android */ 286 #define MATCH(line, name) \ 287 (!strncmp(line, name, sizeof(name) - 1) && \ 288 (line[sizeof(name) - 1] == ' ' || \ 289 line[sizeof(name) - 1] == '\t')) 290 291 nserv = 0; 292 if ((fp = fopen(_PATH_RESCONF, "re")) != NULL) { 293 /* read the config file */ 294 while (fgets(buf, sizeof(buf), fp) != NULL) { 295 /* skip comments */ 296 if (*buf == ';' || *buf == '#') 297 continue; 298 /* read default domain name */ 299 if (MATCH(buf, "domain")) { 300 if (haveenv) /* skip if have from environ */ 301 continue; 302 cp = buf + sizeof("domain") - 1; 303 while (*cp == ' ' || *cp == '\t') 304 cp++; 305 if ((*cp == '\0') || (*cp == '\n')) 306 continue; 307 strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); 308 statp->defdname[sizeof(statp->defdname) - 1] = '\0'; 309 if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) 310 *cp = '\0'; 311 havesearch = 0; 312 continue; 313 } 314 /* set search list */ 315 if (MATCH(buf, "search")) { 316 if (haveenv) /* skip if have from environ */ 317 continue; 318 cp = buf + sizeof("search") - 1; 319 while (*cp == ' ' || *cp == '\t') 320 cp++; 321 if ((*cp == '\0') || (*cp == '\n')) 322 continue; 323 strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); 324 statp->defdname[sizeof(statp->defdname) - 1] = '\0'; 325 if ((cp = strchr(statp->defdname, '\n')) != NULL) 326 *cp = '\0'; 327 /* 328 * Set search list to be blank-separated strings 329 * on rest of line. 330 */ 331 cp = statp->defdname; 332 pp = statp->dnsrch; 333 *pp++ = cp; 334 for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { 335 if (*cp == ' ' || *cp == '\t') { 336 *cp = 0; 337 n = 1; 338 } else if (n) { 339 *pp++ = cp; 340 n = 0; 341 } 342 } 343 /* null terminate last domain if there are excess */ 344 while (*cp != '\0' && *cp != ' ' && *cp != '\t') 345 cp++; 346 *cp = '\0'; 347 *pp++ = 0; 348 havesearch = 1; 349 continue; 350 } 351 /* read nameservers to query */ 352 if (MATCH(buf, "nameserver") && nserv < MAXNS) { 353 struct addrinfo hints, *ai; 354 char sbuf[NI_MAXSERV]; 355 const size_t minsiz = 356 sizeof(statp->_u._ext.ext->nsaddrs[0]); 357 358 cp = buf + sizeof("nameserver") - 1; 359 while (*cp == ' ' || *cp == '\t') 360 cp++; 361 cp[strcspn(cp, ";# \t\n")] = '\0'; 362 if ((*cp != '\0') && (*cp != '\n')) { 363 memset(&hints, 0, sizeof(hints)); 364 hints.ai_family = PF_UNSPEC; 365 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 366 hints.ai_flags = AI_NUMERICHOST; 367 sprintf(sbuf, "%u", NAMESERVER_PORT); 368 if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && 369 ai->ai_addrlen <= minsiz) { 370 if (statp->_u._ext.ext != NULL) { 371 memcpy(&statp->_u._ext.ext->nsaddrs[nserv], 372 ai->ai_addr, ai->ai_addrlen); 373 } 374 if (ai->ai_addrlen <= 375 sizeof(statp->nsaddr_list[nserv])) { 376 memcpy(&statp->nsaddr_list[nserv], 377 ai->ai_addr, ai->ai_addrlen); 378 } else 379 statp->nsaddr_list[nserv].sin_family = 0; 380 freeaddrinfo(ai); 381 nserv++; 382 } 383 } 384 continue; 385 } 386 if (MATCH(buf, "sortlist")) { 387 struct in_addr a; 388 389 cp = buf + sizeof("sortlist") - 1; 390 while (nsort < MAXRESOLVSORT) { 391 while (*cp == ' ' || *cp == '\t') 392 cp++; 393 if (*cp == '\0' || *cp == '\n' || *cp == ';') 394 break; 395 net = cp; 396 while (*cp && !ISSORTMASK(*cp) && *cp != ';' && 397 isascii(*cp) && !isspace((unsigned char)*cp)) 398 cp++; 399 n = *cp; 400 *cp = 0; 401 if (inet_aton(net, &a)) { 402 statp->sort_list[nsort].addr = a; 403 if (ISSORTMASK(n)) { 404 *cp++ = n; 405 net = cp; 406 while (*cp && *cp != ';' && 407 isascii(*cp) && 408 !isspace((unsigned char)*cp)) 409 cp++; 410 n = *cp; 411 *cp = 0; 412 if (inet_aton(net, &a)) { 413 statp->sort_list[nsort].mask = a.s_addr; 414 } else { 415 statp->sort_list[nsort].mask = 416 net_mask(statp->sort_list[nsort].addr); 417 } 418 } else { 419 statp->sort_list[nsort].mask = 420 net_mask(statp->sort_list[nsort].addr); 421 } 422 nsort++; 423 } 424 *cp = n; 425 } 426 continue; 427 } 428 if (MATCH(buf, "options")) { 429 res_setoptions(statp, buf + sizeof("options") - 1, "conf"); 430 continue; 431 } 432 } 433 if (nserv > 0) 434 statp->nscount = nserv; 435 statp->nsort = nsort; 436 (void) fclose(fp); 437 } 438 #endif /* !ANDROID_CHANGES */ 439 /* 440 * Last chance to get a nameserver. This should not normally 441 * be necessary 442 */ 443 #ifdef NO_RESOLV_CONF 444 if(nserv == 0) 445 nserv = get_nameservers(statp); 446 #endif 447 448 if (statp->defdname[0] == 0 && 449 gethostname(buf, sizeof(statp->defdname) - 1) == 0 && 450 (cp = strchr(buf, '.')) != NULL) 451 strcpy(statp->defdname, cp + 1); 452 453 /* find components of local domain that might be searched */ 454 if (havesearch == 0) { 455 pp = statp->dnsrch; 456 *pp++ = statp->defdname; 457 *pp = NULL; 458 459 dots = 0; 460 for (cp = statp->defdname; *cp; cp++) 461 dots += (*cp == '.'); 462 463 cp = statp->defdname; 464 while (pp < statp->dnsrch + MAXDFLSRCH) { 465 if (dots < LOCALDOMAINPARTS) 466 break; 467 cp = strchr(cp, '.') + 1; /* we know there is one */ 468 *pp++ = cp; 469 dots--; 470 } 471 *pp = NULL; 472 #ifdef DEBUG 473 if (statp->options & RES_DEBUG) { 474 printf(";; res_init()... default dnsrch list:\n"); 475 for (pp = statp->dnsrch; *pp; pp++) 476 printf(";;\t%s\n", *pp); 477 printf(";;\t..END..\n"); 478 } 479 #endif 480 } 481 482 if ((cp = getenv("RES_OPTIONS")) != NULL) 483 res_setoptions(statp, cp, "env"); 484 if (nserv > 0) { 485 statp->nscount = nserv; 486 statp->options |= RES_INIT; 487 } 488 return (0); 489 } 490 491 static void 492 res_setoptions(res_state statp, const char *options, const char *source) 493 { 494 const char *cp = options; 495 int i; 496 struct __res_state_ext *ext = statp->_u._ext.ext; 497 498 #ifdef DEBUG 499 if (statp->options & RES_DEBUG) 500 printf(";; res_setoptions(\"%s\", \"%s\")...\n", 501 options, source); 502 #endif 503 while (*cp) { 504 /* skip leading and inner runs of spaces */ 505 while (*cp == ' ' || *cp == '\t') 506 cp++; 507 /* search for and process individual options */ 508 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { 509 i = atoi(cp + sizeof("ndots:") - 1); 510 if (i <= RES_MAXNDOTS) 511 statp->ndots = i; 512 else 513 statp->ndots = RES_MAXNDOTS; 514 #ifdef DEBUG 515 if (statp->options & RES_DEBUG) 516 printf(";;\tndots=%d\n", statp->ndots); 517 #endif 518 } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { 519 i = atoi(cp + sizeof("timeout:") - 1); 520 if (i <= RES_MAXRETRANS) 521 statp->retrans = i; 522 else 523 statp->retrans = RES_MAXRETRANS; 524 #ifdef DEBUG 525 if (statp->options & RES_DEBUG) 526 printf(";;\ttimeout=%d\n", statp->retrans); 527 #endif 528 } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ 529 i = atoi(cp + sizeof("attempts:") - 1); 530 if (i <= RES_MAXRETRY) 531 statp->retry = i; 532 else 533 statp->retry = RES_MAXRETRY; 534 #ifdef DEBUG 535 if (statp->options & RES_DEBUG) 536 printf(";;\tattempts=%d\n", statp->retry); 537 #endif 538 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { 539 #ifdef DEBUG 540 if (!(statp->options & RES_DEBUG)) { 541 printf(";; res_setoptions(\"%s\", \"%s\")..\n", 542 options, source); 543 statp->options |= RES_DEBUG; 544 } 545 printf(";;\tdebug\n"); 546 #endif 547 } else if (!strncmp(cp, "no_tld_query", 548 sizeof("no_tld_query") - 1) || 549 !strncmp(cp, "no-tld-query", 550 sizeof("no-tld-query") - 1)) { 551 statp->options |= RES_NOTLDQUERY; 552 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { 553 statp->options |= RES_USE_INET6; 554 } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { 555 statp->options |= RES_ROTATE; 556 } else if (!strncmp(cp, "no-check-names", 557 sizeof("no-check-names") - 1)) { 558 statp->options |= RES_NOCHECKNAME; 559 } 560 #ifdef RES_USE_EDNS0 561 else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { 562 statp->options |= RES_USE_EDNS0; 563 } 564 #endif 565 else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { 566 statp->options |= RES_USE_DNAME; 567 } 568 else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { 569 if (ext == NULL) 570 goto skip; 571 cp += sizeof("nibble:") - 1; 572 i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); 573 strncpy(ext->nsuffix, cp, (size_t)i); 574 ext->nsuffix[i] = '\0'; 575 } 576 else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { 577 if (ext == NULL) 578 goto skip; 579 cp += sizeof("nibble2:") - 1; 580 i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); 581 strncpy(ext->nsuffix2, cp, (size_t)i); 582 ext->nsuffix2[i] = '\0'; 583 } 584 else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { 585 cp += sizeof("v6revmode:") - 1; 586 /* "nibble" and "bitstring" used to be valid */ 587 if (!strncmp(cp, "single", sizeof("single") - 1)) { 588 statp->options |= RES_NO_NIBBLE2; 589 } else if (!strncmp(cp, "both", sizeof("both") - 1)) { 590 statp->options &= 591 ~RES_NO_NIBBLE2; 592 } 593 } 594 else { 595 /* XXX - print a warning here? */ 596 } 597 skip: 598 /* skip to next run of spaces */ 599 while (*cp && *cp != ' ' && *cp != '\t') 600 cp++; 601 } 602 } 603 604 #ifdef RESOLVSORT 605 /* XXX - should really support CIDR which means explicit masks always. */ 606 static uint32_t 607 net_mask(struct in_addr in) /*!< XXX - should really use system's version of this */ 608 { 609 register uint32_t i = ntohl(in.s_addr); 610 611 if (IN_CLASSA(i)) 612 return (htonl(IN_CLASSA_NET)); 613 else if (IN_CLASSB(i)) 614 return (htonl(IN_CLASSB_NET)); 615 return (htonl(IN_CLASSC_NET)); 616 } 617 #endif 618 619 /*% 620 * This routine is for closing the socket if a virtual circuit is used and 621 * the program wants to close it. This provides support for endhostent() 622 * which expects to close the socket. 623 * 624 * This routine is not expected to be user visible. 625 */ 626 void 627 res_nclose(res_state statp) 628 { 629 int ns; 630 631 if (statp->_vcsock >= 0) { 632 (void) close(statp->_vcsock); 633 statp->_vcsock = -1; 634 statp->_flags &= ~(RES_F_VC | RES_F_CONN); 635 } 636 for (ns = 0; ns < statp->_u._ext.nscount; ns++) { 637 if (statp->_u._ext.nssocks[ns] != -1) { 638 (void) close(statp->_u._ext.nssocks[ns]); 639 statp->_u._ext.nssocks[ns] = -1; 640 } 641 } 642 } 643 644 void 645 res_ndestroy(res_state statp) 646 { 647 res_nclose(statp); 648 if (statp->_u._ext.ext != NULL) 649 free(statp->_u._ext.ext); 650 statp->options &= ~RES_INIT; 651 statp->_u._ext.ext = NULL; 652 } 653 654 const char * 655 res_get_nibblesuffix(res_state statp) 656 { 657 if (statp->_u._ext.ext) 658 return (statp->_u._ext.ext->nsuffix); 659 return ("ip6.arpa"); 660 } 661 662 const char * 663 res_get_nibblesuffix2(res_state statp) 664 { 665 if (statp->_u._ext.ext) 666 return (statp->_u._ext.ext->nsuffix2); 667 return ("ip6.int"); 668 } 669 670 void 671 res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) 672 { 673 int i, nserv; 674 size_t size; 675 676 /* close open servers */ 677 res_nclose(statp); 678 679 /* cause rtt times to be forgotten */ 680 statp->_u._ext.nscount = 0; 681 682 nserv = 0; 683 for (i = 0; i < cnt && nserv < MAXNS; i++) { 684 switch (set->sin.sin_family) { 685 case AF_INET: 686 size = sizeof(set->sin); 687 if (statp->_u._ext.ext) 688 memcpy(&statp->_u._ext.ext->nsaddrs[nserv], 689 &set->sin, size); 690 if (size <= sizeof(statp->nsaddr_list[nserv])) 691 memcpy(&statp->nsaddr_list[nserv], 692 &set->sin, size); 693 else 694 statp->nsaddr_list[nserv].sin_family = 0; 695 nserv++; 696 break; 697 698 #ifdef HAS_INET6_STRUCTS 699 case AF_INET6: 700 size = sizeof(set->sin6); 701 if (statp->_u._ext.ext) 702 memcpy(&statp->_u._ext.ext->nsaddrs[nserv], 703 &set->sin6, size); 704 if (size <= sizeof(statp->nsaddr_list[nserv])) 705 memcpy(&statp->nsaddr_list[nserv], 706 &set->sin6, size); 707 else 708 statp->nsaddr_list[nserv].sin_family = 0; 709 nserv++; 710 break; 711 #endif 712 713 default: 714 break; 715 } 716 set++; 717 } 718 statp->nscount = nserv; 719 720 } 721 722 int 723 res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) 724 { 725 int i; 726 size_t size; 727 uint16_t family; 728 729 for (i = 0; i < statp->nscount && i < cnt; i++) { 730 if (statp->_u._ext.ext) 731 family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; 732 else 733 family = statp->nsaddr_list[i].sin_family; 734 735 switch (family) { 736 case AF_INET: 737 size = sizeof(set->sin); 738 if (statp->_u._ext.ext) 739 memcpy(&set->sin, 740 &statp->_u._ext.ext->nsaddrs[i], 741 size); 742 else 743 memcpy(&set->sin, &statp->nsaddr_list[i], 744 size); 745 break; 746 747 #ifdef HAS_INET6_STRUCTS 748 case AF_INET6: 749 size = sizeof(set->sin6); 750 if (statp->_u._ext.ext) 751 memcpy(&set->sin6, 752 &statp->_u._ext.ext->nsaddrs[i], 753 size); 754 else 755 memcpy(&set->sin6, &statp->nsaddr_list[i], 756 size); 757 break; 758 #endif 759 760 default: 761 set->sin.sin_family = 0; 762 break; 763 } 764 set++; 765 } 766 return (statp->nscount); 767 } 768 769 #ifdef ANDROID_CHANGES 770 void res_setnetid(res_state statp, unsigned netid) 771 { 772 if (statp != NULL) { 773 statp->netid = netid; 774 } 775 } 776 777 void res_setmark(res_state statp, unsigned mark) 778 { 779 if (statp != NULL) { 780 statp->_mark = mark; 781 } 782 } 783 784 #endif /* ANDROID_CHANGES */ 785