1/* 2 * Copyright (c) 1985, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Portions copyright (c) 1999, 2000 6 * Intel Corporation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * 23 * This product includes software developed by the University of 24 * California, Berkeley, Intel Corporation, and its contributors. 25 * 26 * 4. Neither the name of University, Intel Corporation, or their respective 27 * contributors may be used to endorse or promote products derived from 28 * this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND 31 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 32 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS, 34 * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 * 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 */ 47 48/* 49 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 50 * 51 * Permission to use, copy, modify, and distribute this software for any 52 * purpose with or without fee is hereby granted, provided that the above 53 * copyright notice and this permission notice appear in all copies, and that 54 * the name of Digital Equipment Corporation not be used in advertising or 55 * publicity pertaining to distribution of the document or software without 56 * specific, written prior permission. 57 * 58 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 59 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 61 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 62 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 63 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 64 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 65 * SOFTWARE. 66 */ 67 68/* 69 * Portions Copyright (c) 1996 by Internet Software Consortium. 70 * 71 * Permission to use, copy, modify, and distribute this software for any 72 * purpose with or without fee is hereby granted, provided that the above 73 * copyright notice and this permission notice appear in all copies. 74 * 75 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 76 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 77 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 78 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 79 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 80 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 81 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 82 * SOFTWARE. 83 */ 84 85#if defined(LIBC_SCCS) && !defined(lint) 86static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; 87static char orig_rcsid[] = "From: Id: res_init.c,v 8.7 1996/11/18 09:10:04 vixie Exp $"; 88static char rcsid[] = "$Id: res_init.c,v 1.1.1.1 2003/11/19 01:51:37 kyu3 Exp $"; 89#endif /* LIBC_SCCS and not lint */ 90 91#include <sys/types.h> 92#include <sys/param.h> 93#include <sys/socket.h> 94#include <sys/time.h> 95#include <netinet/in.h> 96#include <arpa/inet.h> 97#include <arpa/nameser.h> 98#include <ctype.h> 99#include <resolv.h> 100#include <stdio.h> 101#include <stdlib.h> 102#include <string.h> 103#include <unistd.h> 104 105#include "res_config.h" 106 107static void res_setoptions __P((char *, char *)); 108 109#ifdef RESOLVSORT 110static const char sort_mask[] = "/&"; 111#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) 112static u_int32_t net_mask __P((struct in_addr)); 113#endif 114 115#if !defined(isascii) /* XXX - could be a function */ 116# define isascii(c) (!(c & 0200)) 117#endif 118 119/* 120 * Resolver state default settings. 121 */ 122 123struct __res_state _res 124# if defined(__BIND_RES_TEXT) 125 = { RES_TIMEOUT, } /* Motorola, et al. */ 126# endif 127 ; 128 129 130/* 131 * Set up default settings. If the configuration file exist, the values 132 * there will have precedence. Otherwise, the server address is set to 133 * INADDR_ANY and the default domain name comes from the gethostname(). 134 * 135 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 136 * rather than INADDR_ANY ("0.0.0.0") as the default name server address 137 * since it was noted that INADDR_ANY actually meant ``the first interface 138 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, 139 * it had to be "up" in order for you to reach your own name server. It 140 * was later decided that since the recommended practice is to always 141 * install local static routes through 127.0.0.1 for all your network 142 * interfaces, that we could solve this problem without a code change. 143 * 144 * The configuration file should always be used, since it is the only way 145 * to specify a default domain. If you are running a server on your local 146 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" 147 * in the configuration file. 148 * 149 * Return 0 if completes successfully, -1 on error 150 */ 151int 152res_init() 153{ 154 register FILE *fp; 155 register char *cp, **pp; 156 register int n; 157 char buf[MAXDNAME]; 158 int nserv = 0; /* number of nameserver records read from file */ 159 int haveenv = 0; 160 int havesearch = 0; 161#ifdef RESOLVSORT 162 int nsort = 0; 163 char *net; 164#endif 165#ifndef RFC1535 166 int dots; 167#endif 168 169 /* 170 * These three fields used to be statically initialized. This made 171 * it hard to use this code in a shared library. It is necessary, 172 * now that we're doing dynamic initialization here, that we preserve 173 * the old semantics: if an application modifies one of these three 174 * fields of _res before res_init() is called, res_init() will not 175 * alter them. Of course, if an application is setting them to 176 * _zero_ before calling res_init(), hoping to override what used 177 * to be the static default, we can't detect it and unexpected results 178 * will follow. Zero for any of these fields would make no sense, 179 * so one can safely assume that the applications were already getting 180 * unexpected results. 181 * 182 * _res.options is tricky since some apps were known to diddle the bits 183 * before res_init() was first called. We can't replicate that semantic 184 * with dynamic initialization (they may have turned bits off that are 185 * set in RES_DEFAULT). Our solution is to declare such applications 186 * "broken". They could fool us by setting RES_INIT but none do (yet). 187 */ 188 if (!_res.retrans) 189 _res.retrans = RES_TIMEOUT; 190 if (!_res.retry) 191 _res.retry = 4; 192 if (!(_res.options & RES_INIT)) 193 _res.options = RES_DEFAULT; 194 195 /* 196 * This one used to initialize implicitly to zero, so unless the app 197 * has set it to something in particular, we can randomize it now. 198 */ 199 if (!_res.id) 200 _res.id = (u_short)res_randomid(); 201 202#ifdef USELOOPBACK 203 _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); 204#else 205 _res.nsaddr.sin_addr.s_addr = INADDR_ANY; 206#endif 207 _res.nsaddr.sin_family = AF_INET; 208 _res.nsaddr.sin_port = htons(NAMESERVER_PORT); 209 _res.nscount = 1; 210 _res.ndots = 1; 211 _res.pfcode = 0; 212 213 /* Allow user to override the local domain definition */ 214#ifdef _ORG_FREEBSD_ 215 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) 216#else 217 if ((cp = getenv("LOCALDOMAIN")) != NULL) 218#endif 219 { 220 (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); 221 _res.defdname[sizeof(_res.defdname) - 1] = '\0'; 222 haveenv++; 223 224 /* 225 * Set search list to be blank-separated strings 226 * from rest of env value. Permits users of LOCALDOMAIN 227 * to still have a search list, and anyone to set the 228 * one that they want to use as an individual (even more 229 * important now that the rfc1535 stuff restricts searches) 230 */ 231 cp = _res.defdname; 232 pp = _res.dnsrch; 233 *pp++ = cp; 234 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 235 if (*cp == '\n') /* silly backwards compat */ 236 break; 237 else if (*cp == ' ' || *cp == '\t') { 238 *cp = 0; 239 n = 1; 240 } else if (n) { 241 *pp++ = cp; 242 n = 0; 243 havesearch = 1; 244 } 245 } 246 /* null terminate last domain if there are excess */ 247 while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') 248 cp++; 249 *cp = '\0'; 250 *pp++ = 0; 251 } 252 253#define MATCH(line, name) \ 254 (!strncmp(line, name, sizeof(name) - 1) && \ 255 (line[sizeof(name) - 1] == ' ' || \ 256 line[sizeof(name) - 1] == '\t')) 257 258 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 259 /* read the config file */ 260 while (fgets(buf, sizeof(buf), fp) != NULL) { 261 /* skip comments */ 262 if (*buf == ';' || *buf == '#') 263 continue; 264 /* read default domain name */ 265 if (MATCH(buf, "domain")) { 266 if (haveenv) /* skip if have from environ */ 267 continue; 268 cp = buf + sizeof("domain") - 1; 269 while (*cp == ' ' || *cp == '\t') 270 cp++; 271 if ((*cp == '\0') || (*cp == '\n')) 272 continue; 273 strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); 274 _res.defdname[sizeof(_res.defdname) - 1] = '\0'; 275 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) 276 *cp = '\0'; 277 havesearch = 0; 278 continue; 279 } 280 /* set search list */ 281 if (MATCH(buf, "search")) { 282 if (haveenv) /* skip if have from environ */ 283 continue; 284 cp = buf + sizeof("search") - 1; 285 while (*cp == ' ' || *cp == '\t') 286 cp++; 287 if ((*cp == '\0') || (*cp == '\n')) 288 continue; 289 strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); 290 _res.defdname[sizeof(_res.defdname) - 1] = '\0'; 291 if ((cp = strchr(_res.defdname, '\n')) != NULL) 292 *cp = '\0'; 293 /* 294 * Set search list to be blank-separated strings 295 * on rest of line. 296 */ 297 cp = _res.defdname; 298 pp = _res.dnsrch; 299 *pp++ = cp; 300 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 301 if (*cp == ' ' || *cp == '\t') { 302 *cp = 0; 303 n = 1; 304 } else if (n) { 305 *pp++ = cp; 306 n = 0; 307 } 308 } 309 /* null terminate last domain if there are excess */ 310 while (*cp != '\0' && *cp != ' ' && *cp != '\t') 311 cp++; 312 *cp = '\0'; 313 *pp++ = 0; 314 havesearch = 1; 315 continue; 316 } 317 /* read nameservers to query */ 318 if (MATCH(buf, "nameserver") && nserv < MAXNS) { 319 struct in_addr a; 320 321 cp = buf + sizeof("nameserver") - 1; 322 while (*cp == ' ' || *cp == '\t') 323 cp++; 324 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { 325 _res.nsaddr_list[nserv].sin_addr = a; 326 _res.nsaddr_list[nserv].sin_family = AF_INET; 327 _res.nsaddr_list[nserv].sin_port = 328 htons(NAMESERVER_PORT); 329 nserv++; 330 } 331 continue; 332 } 333#ifdef RESOLVSORT 334 if (MATCH(buf, "sortlist")) { 335 struct in_addr a; 336 337 cp = buf + sizeof("sortlist") - 1; 338 while (nsort < MAXRESOLVSORT) { 339 while (*cp == ' ' || *cp == '\t') 340 cp++; 341 if (*cp == '\0' || *cp == '\n' || *cp == ';') 342 break; 343 net = cp; 344 while (*cp && !ISSORTMASK(*cp) && *cp != ';' && 345 isascii(*cp) && !isspace(*cp)) 346 cp++; 347 n = *cp; 348 *cp = 0; 349 if (inet_aton(net, &a)) { 350 _res.sort_list[nsort].addr = a; 351 if (ISSORTMASK(n)) { 352 *cp++ = (char)n; 353 net = cp; 354 while (*cp && *cp != ';' && 355 isascii(*cp) && !isspace(*cp)) 356 cp++; 357 n = *cp; 358 *cp = 0; 359 if (inet_aton(net, &a)) { 360 _res.sort_list[nsort].mask = a.s_addr; 361 } else { 362 _res.sort_list[nsort].mask = 363 net_mask(_res.sort_list[nsort].addr); 364 } 365 } else { 366 _res.sort_list[nsort].mask = 367 net_mask(_res.sort_list[nsort].addr); 368 } 369 nsort++; 370 } 371 *cp = (char)n; 372 } 373 continue; 374 } 375#endif 376 if (MATCH(buf, "options")) { 377 res_setoptions(buf + sizeof("options") - 1, "conf"); 378 continue; 379 } 380 } 381 if (nserv > 1) 382 _res.nscount = nserv; 383#ifdef RESOLVSORT 384 _res.nsort = nsort; 385#endif 386 (void) fclose(fp); 387 } 388 if (_res.defdname[0] == 0 && 389 gethostname(buf, sizeof(_res.defdname) - 1) == 0 && 390 (cp = strchr(buf, '.')) != NULL) 391 strcpy(_res.defdname, cp + 1); 392 393 /* find components of local domain that might be searched */ 394 if (havesearch == 0) { 395 pp = _res.dnsrch; 396 *pp++ = _res.defdname; 397 *pp = NULL; 398 399#ifndef RFC1535 400 dots = 0; 401 for (cp = _res.defdname; *cp; cp++) 402 dots += (*cp == '.'); 403 404 cp = _res.defdname; 405 while (pp < _res.dnsrch + MAXDFLSRCH) { 406 if (dots < LOCALDOMAINPARTS) 407 break; 408 cp = strchr(cp, '.') + 1; /* we know there is one */ 409 *pp++ = cp; 410 dots--; 411 } 412 *pp = NULL; 413#ifdef DEBUG 414 if (_res.options & RES_DEBUG) { 415 printf(";; res_init()... default dnsrch list:\n"); 416 for (pp = _res.dnsrch; *pp; pp++) 417 printf(";;\t%s\n", *pp); 418 printf(";;\t..END..\n"); 419 } 420#endif 421#endif /* !RFC1535 */ 422 } 423 424#ifdef _ORG_FREEBSD_ 425 if (issetugid()) 426#else 427 if (1) 428#endif 429 _res.options |= RES_NOALIASES; 430 else if ((cp = getenv("RES_OPTIONS")) != NULL) 431 res_setoptions(cp, "env"); 432 _res.options |= RES_INIT; 433 if ( 0 == nserv ) { 434 return -1; 435 } 436 return (0); 437} 438 439static void 440res_setoptions( 441 char *options, 442 char *source 443 ) 444{ 445 char *cp = options; 446 int i; 447 448#ifdef DEBUG 449 if (_res.options & RES_DEBUG) 450 printf(";; res_setoptions(\"%s\", \"%s\")...\n", 451 options, source); 452#endif 453 while (*cp) { 454 /* skip leading and inner runs of spaces */ 455 while (*cp == ' ' || *cp == '\t') 456 cp++; 457 /* search for and process individual options */ 458 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { 459 i = atoi(cp + sizeof("ndots:") - 1); 460 if (i <= RES_MAXNDOTS) 461 _res.ndots = i; 462 else 463 _res.ndots = RES_MAXNDOTS; 464#ifdef DEBUG 465 if (_res.options & RES_DEBUG) 466 printf(";;\tndots=%d\n", _res.ndots); 467#endif 468 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { 469#ifdef DEBUG 470 if (!(_res.options & RES_DEBUG)) { 471 printf(";; res_setoptions(\"%s\", \"%s\")..\n", 472 options, source); 473 _res.options |= RES_DEBUG; 474 } 475 printf(";;\tdebug\n"); 476#endif 477 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { 478 _res.options |= RES_USE_INET6; 479 } else if (!strncmp(cp, "no_tld_query", sizeof("no_tld_query") - 1)) { 480 _res.options |= RES_NOTLDQUERY; 481 } else { 482 /* XXX - print a warning here? */ 483 } 484 /* skip to next run of spaces */ 485 while (*cp && *cp != ' ' && *cp != '\t') 486 cp++; 487 } 488} 489 490#ifdef RESOLVSORT 491/* XXX - should really support CIDR which means explicit masks always. */ 492static u_int32_t 493net_mask( 494 struct in_addr in 495 ) 496{ 497 register u_int32_t i = ntohl(in.s_addr); 498 499 if (IN_CLASSA(i)) 500 return (htonl(IN_CLASSA_NET)); 501 else if (IN_CLASSB(i)) 502 return (htonl(IN_CLASSB_NET)); 503 return (htonl(IN_CLASSC_NET)); 504} 505#endif 506 507u_int 508res_randomid() 509{ 510 struct timeval now; 511 512 gettimeofday(&now, NULL); 513 return (0xffff & (now.tv_sec ^ now.tv_usec /* ^ getpid() */)); 514} 515