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