1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include <sys/types.h> 43 #include <sys/sockio.h> 44 #include <sys/socket.h> 45 #include <netinet/in.h> 46 #include <stdio.h> 47 #include <arpa/nameser.h> 48 #include <resolv.h> 49 50 #include <netinet/in.h> 51 #include <net/if.h> 52 #include <netinet/if_ether.h> 53 #include <arpa/inet.h> 54 55 #define MAXIFS 256 56 57 /* 58 * Resolver state default settings 59 */ 60 61 struct state _res = { 62 RES_TIMEOUT, /* retransmition time interval */ 63 4, /* number of times to retransmit */ 64 RES_DEFAULT, /* options flags */ 65 1, /* number of name servers */ 66 }; 67 68 /* 69 * Set up default settings. If the configuration file exist, the values 70 * there will have precedence. Otherwise, the server address is set to 71 * INADDR_LOOPBACK and the default domain name comes from the gethostname(). 72 * BUT if the NIS/RPC domain name is set, that is used if all else fails. 73 * 74 * The configuration file should only be used if you want to redefine your 75 * domain or run without a server on your machine. 76 * 77 * Note the user can always override then domain name with the environment 78 * variable LOCALDOMAIN which has absolute priority. 79 * 80 * 81 * Return 0 if completes successfully, -1 on error 82 */ 83 int 84 res_init(void) 85 { 86 register FILE *fp; 87 register char *cp, **pp; 88 register int n; 89 char buf[BUFSIZ]; 90 #ifdef SYSV 91 extern char *strchr(); 92 #else 93 extern char *index(); 94 #endif 95 extern char *strcpy(), *strncpy(); 96 extern char *getenv(); 97 int nserv = 0; /* number of nameserver records read from file */ 98 int haveenv = 0; 99 int havesearch = 0; 100 101 _res.nsaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* INADDR_ANY */ 102 _res.nsaddr.sin_family = AF_INET; 103 _res.nsaddr.sin_port = htons(NAMESERVER_PORT); 104 _res.nscount = 1; 105 106 #ifdef SIOCGIFNUM 107 { int numifs, s, n, int_up; 108 struct ifconf ifc; 109 register struct ifreq *ifrp; 110 struct ifreq ifr; 111 unsigned bufsize; 112 unsigned int flags; 113 char *buf; 114 extern void *malloc(); 115 116 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 117 perror("socket"); 118 return (-1); 119 } 120 if (ioctl(s, SIOCGIFNUM, (char *)&numifs) < 0) { 121 numifs = MAXIFS; 122 } 123 bufsize = numifs * sizeof (struct ifreq); 124 buf = (char *)malloc(bufsize); 125 if (buf == NULL) { 126 perror("out of memory"); 127 close(s); 128 return (-1); 129 } 130 ifc.ifc_len = bufsize; 131 ifc.ifc_buf = buf; 132 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { 133 perror("ifconfig: SIOCGIFCONF"); 134 close(s); 135 free(buf); 136 return (-1); 137 } 138 139 int_up = 0; 140 ifrp = ifc.ifc_req; 141 for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; 142 n--, ifrp++) { 143 memset((void *) &ifr, 0, sizeof (ifr)); 144 strncpy(ifr.ifr_name, ifrp->ifr_name, 145 sizeof (ifr.ifr_name)); 146 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifr) < 0) { 147 perror("SIOCGIFFLAGS"); 148 close(s); 149 free(buf); 150 return (-1); 151 } 152 flags = ifr.ifr_flags; 153 /* we are looking for a non-loopback interface */ 154 if ((flags & IFF_UP) && ((flags & IFF_LOOPBACK) == 0)) 155 int_up = 1; 156 } 157 close(s); 158 free(buf); 159 if (int_up == 0) /* all the non-LOOPBACK interfaces are DOWN */ 160 return (-1); 161 } 162 #endif /* SIOCGIFNUM */ 163 164 165 /* 166 * for the benefit of hidden NIS domains, we use the same procedure 167 * as sendmail: convert leading + to dot, then drop to first dot 168 */ 169 getdomainname(buf, BUFSIZ); 170 if (buf[0] == '+') 171 buf[0] = '.'; 172 #ifdef SYSV 173 cp = strchr(buf, (int)'.'); 174 #else 175 cp = index(buf, '.'); 176 #endif 177 if (cp == NULL) 178 strcpy(_res.defdname, buf); 179 else 180 strcpy(_res.defdname, cp+1); 181 182 /* Allow user to override the local domain definition */ 183 if ((cp = getenv("LOCALDOMAIN")) != NULL) { 184 (void) strncpy(_res.defdname, cp, sizeof (_res.defdname)); 185 haveenv++; 186 } 187 188 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 189 /* read the config file */ 190 while (fgets(buf, sizeof (buf), fp) != NULL) { 191 /* read default domain name */ 192 if (!strncmp(buf, "domain", sizeof ("domain") - 1)) { 193 if (haveenv) /* skip if have from environ */ 194 continue; 195 cp = buf + sizeof ("domain") - 1; 196 while (*cp == ' ' || *cp == '\t') 197 cp++; 198 if ((*cp == '\0') || (*cp == '\n')) 199 continue; 200 (void) strncpy(_res.defdname, cp, sizeof (_res.defdname) - 1); 201 #ifdef SYSV 202 if ((cp = strchr(_res.defdname, (int)'\n')) != NULL) 203 #else 204 if ((cp = index(_res.defdname, '\n')) != NULL) 205 #endif 206 *cp = '\0'; 207 havesearch = 0; 208 continue; 209 } 210 /* set search list */ 211 if (!strncmp(buf, "search", sizeof ("search") - 1)) { 212 if (haveenv) /* skip if have from environ */ 213 continue; 214 cp = buf + sizeof ("search") - 1; 215 while (*cp == ' ' || *cp == '\t') 216 cp++; 217 if ((*cp == '\0') || (*cp == '\n')) 218 continue; 219 (void) strncpy(_res.defdname, cp, sizeof (_res.defdname) - 1); 220 #ifdef SYSV 221 if ((cp = strchr(_res.defdname, (int)'\n')) != NULL) 222 #else 223 if ((cp = index(_res.defdname, '\n')) != NULL) 224 #endif 225 *cp = '\0'; 226 /* 227 * Set search list to be blank-separated strings 228 * on rest of line. 229 */ 230 cp = _res.defdname; 231 pp = _res.dnsrch; 232 *pp++ = cp; 233 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 234 if (*cp == ' ' || *cp == '\t') { 235 *cp = 0; 236 n = 1; 237 } else if (n) { 238 *pp++ = cp; 239 n = 0; 240 } 241 } 242 /* null terminate last domain if there are excess */ 243 while (*cp != '\0' && *cp != ' ' && *cp != '\t') 244 cp++; 245 *cp = '\0'; 246 *pp++ = 0; 247 havesearch = 1; 248 continue; 249 } 250 /* read nameservers to query */ 251 if (!strncmp(buf, "nameserver", sizeof ("nameserver") - 1) && 252 (nserv < MAXNS)) { 253 cp = buf + sizeof ("nameserver") - 1; 254 while (*cp == ' ' || *cp == '\t') 255 cp++; 256 if ((*cp == '\0') || (*cp == '\n')) 257 continue; 258 if ((_res.nsaddr_list[nserv].sin_addr.s_addr = 259 inet_addr(cp)) == (unsigned) -1) { 260 _res.nsaddr_list[n].sin_addr.s_addr = INADDR_ANY; 261 continue; 262 } 263 _res.nsaddr_list[nserv].sin_family = AF_INET; 264 _res.nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT); 265 nserv++; 266 continue; 267 } 268 } 269 if (nserv > 1) 270 _res.nscount = nserv; 271 (void) fclose(fp); 272 } 273 if (_res.defdname[0] == 0) { 274 if (gethostname(buf, sizeof (_res.defdname)) == 0 && 275 #ifdef SYSV 276 (cp = strchr(buf, (int)'.'))) 277 #else 278 (cp = index(buf, '.'))) 279 #endif 280 (void) strcpy(_res.defdname, cp + 1); 281 } 282 283 /* find components of local domain that might be searched */ 284 if (havesearch == 0) { 285 pp = _res.dnsrch; 286 *pp++ = _res.defdname; 287 for (cp = _res.defdname, n = 0; *cp; cp++) 288 if (*cp == '.') 289 n++; 290 cp = _res.defdname; 291 for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; n--) { 292 #ifdef SYSV 293 cp = strchr(cp, (int)'.'); 294 #else 295 cp = index(cp, '.'); 296 #endif 297 *pp++ = ++cp; 298 } 299 *pp++ = 0; 300 } 301 _res.options |= RES_INIT; 302 return (0); 303 } 304