1 /*- 2 * Copyright (c) 1985, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * - 7 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies, and that 12 * the name of Digital Equipment Corporation not be used in advertising or 13 * publicity pertaining to distribution of the document or software without 14 * specific, written prior permission. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 17 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 19 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 21 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 22 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23 * SOFTWARE. 24 * - 25 * --Copyright-- 26 */ 27 28 #if defined(LIBC_SCCS) && !defined(lint) 29 static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 06/07/93"; 30 static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $"; 31 #endif /* LIBC_SCCS and not lint */ 32 33 #include <sys/param.h> 34 #include <sys/socket.h> 35 #include <netinet/in.h> 36 #include <arpa/inet.h> 37 #include <arpa/nameser.h> 38 #include <resolv.h> 39 #include <unistd.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 /* 45 * Resolver state default settings 46 */ 47 48 struct __res_state _res = { 49 RES_TIMEOUT, /* retransmition time interval */ 50 4, /* number of times to retransmit */ 51 RES_DEFAULT, /* options flags */ 52 1, /* number of name servers */ 53 }; 54 55 /* 56 * Set up default settings. If the configuration file exist, the values 57 * there will have precedence. Otherwise, the server address is set to 58 * INADDR_ANY and the default domain name comes from the gethostname(). 59 * 60 * The configuration file should only be used if you want to redefine your 61 * domain or run without a server on your machine. 62 * 63 * Return 0 if completes successfully, -1 on error 64 */ 65 res_init() 66 { 67 register FILE *fp; 68 register char *cp, **pp; 69 register int n; 70 char buf[BUFSIZ]; 71 int nserv = 0; /* number of nameserver records read from file */ 72 int haveenv = 0; 73 int havesearch = 0; 74 75 #ifdef USELOOPBACK 76 _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); 77 #else 78 _res.nsaddr.sin_addr.s_addr = INADDR_ANY; 79 #endif 80 _res.nsaddr.sin_family = AF_INET; 81 _res.nsaddr.sin_port = htons(NAMESERVER_PORT); 82 _res.nscount = 1; 83 _res.pfcode = 0; 84 85 /* Allow user to override the local domain definition */ 86 if ((cp = getenv("LOCALDOMAIN")) != NULL) { 87 (void)strncpy(_res.defdname, cp, sizeof(_res.defdname)); 88 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) 89 *cp = '\0'; 90 haveenv++; 91 } 92 93 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 94 /* read the config file */ 95 while (fgets(buf, sizeof(buf), fp) != NULL) { 96 /* skip comments */ 97 if ((*buf == ';') || (*buf == '#')) 98 continue; 99 /* read default domain name */ 100 if (!strncmp(buf, "domain", sizeof("domain") - 1)) { 101 if (haveenv) /* skip if have from environ */ 102 continue; 103 cp = buf + sizeof("domain") - 1; 104 while (*cp == ' ' || *cp == '\t') 105 cp++; 106 if ((*cp == '\0') || (*cp == '\n')) 107 continue; 108 (void)strncpy(_res.defdname, cp, 109 sizeof(_res.defdname) - 1); 110 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) 111 *cp = '\0'; 112 havesearch = 0; 113 continue; 114 } 115 /* set search list */ 116 if (!strncmp(buf, "search", sizeof("search") - 1)) { 117 if (haveenv) /* skip if have from environ */ 118 continue; 119 cp = buf + sizeof("search") - 1; 120 while (*cp == ' ' || *cp == '\t') 121 cp++; 122 if ((*cp == '\0') || (*cp == '\n')) 123 continue; 124 (void)strncpy(_res.defdname, cp, 125 sizeof(_res.defdname) - 1); 126 if ((cp = strchr(_res.defdname, '\n')) != NULL) 127 *cp = '\0'; 128 /* 129 * Set search list to be blank-separated strings 130 * on rest of line. 131 */ 132 cp = _res.defdname; 133 pp = _res.dnsrch; 134 *pp++ = cp; 135 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 136 if (*cp == ' ' || *cp == '\t') { 137 *cp = 0; 138 n = 1; 139 } else if (n) { 140 *pp++ = cp; 141 n = 0; 142 } 143 } 144 /* null terminate last domain if there are excess */ 145 while (*cp != '\0' && *cp != ' ' && *cp != '\t') 146 cp++; 147 *cp = '\0'; 148 *pp++ = 0; 149 havesearch = 1; 150 continue; 151 } 152 /* read nameservers to query */ 153 if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) && 154 nserv < MAXNS) { 155 struct in_addr a; 156 157 cp = buf + sizeof("nameserver") - 1; 158 while (*cp == ' ' || *cp == '\t') 159 cp++; 160 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { 161 _res.nsaddr_list[nserv].sin_addr = a; 162 _res.nsaddr_list[nserv].sin_family = AF_INET; 163 _res.nsaddr_list[nserv].sin_port = 164 htons(NAMESERVER_PORT); 165 nserv++; 166 } 167 continue; 168 } 169 } 170 if (nserv > 1) 171 _res.nscount = nserv; 172 (void) fclose(fp); 173 } 174 if (_res.defdname[0] == 0) { 175 if (gethostname(buf, sizeof(_res.defdname)) == 0 && 176 (cp = strchr(buf, '.'))) 177 (void)strcpy(_res.defdname, cp + 1); 178 } 179 180 /* find components of local domain that might be searched */ 181 if (havesearch == 0) { 182 pp = _res.dnsrch; 183 *pp++ = _res.defdname; 184 for (cp = _res.defdname, n = 0; *cp; cp++) 185 if (*cp == '.') 186 n++; 187 cp = _res.defdname; 188 for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; 189 n--) { 190 cp = strchr(cp, '.'); 191 *pp++ = ++cp; 192 } 193 *pp++ = 0; 194 } 195 _res.options |= RES_INIT; 196 return (0); 197 } 198