1122394Sharti/* 2122394Sharti * Copyright (c) 1985, 1989, 1993 3122394Sharti * The Regents of the University of California. All rights reserved. 4122394Sharti * 5122394Sharti * Redistribution and use in source and binary forms, with or without 6159063Sharti * modification, are permitted provided that the following conditions 7133211Sharti * are met: 8133211Sharti * 1. Redistributions of source code must retain the above copyright 9133211Sharti * notice, this list of conditions and the following disclaimer. 10122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 11133211Sharti * notice, this list of conditions and the following disclaimer in the 12133211Sharti * documentation and/or other materials provided with the distribution. 13133211Sharti * 4. Neither the name of the University nor the names of its contributors 14133211Sharti * may be used to endorse or promote products derived from this software 15133211Sharti * without specific prior written permission. 16133211Sharti * 17122394Sharti * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18122394Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19122394Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27133211Sharti * SUCH DAMAGE. 28133211Sharti */ 29133211Sharti 30133211Sharti/* 31133211Sharti * Portions Copyright (c) 1993 by Digital Equipment Corporation. 32122394Sharti * 33159063Sharti * Permission to use, copy, modify, and distribute this software for any 34122394Sharti * purpose with or without fee is hereby granted, provided that the above 35122394Sharti * copyright notice and this permission notice appear in all copies, and that 36122394Sharti * the name of Digital Equipment Corporation not be used in advertising or 37122394Sharti * publicity pertaining to distribution of the document or software without 38122394Sharti * specific, written prior permission. 39159063Sharti * 40133211Sharti * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 41159063Sharti * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 42159063Sharti * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 43122394Sharti * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 44122394Sharti * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45122394Sharti * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46122394Sharti * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 47159063Sharti * SOFTWARE. 48122394Sharti */ 49159063Sharti 50122394Sharti/* 51159063Sharti * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 52159063Sharti * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 53159063Sharti * 54159063Sharti * Permission to use, copy, modify, and distribute this software for any 55159063Sharti * purpose with or without fee is hereby granted, provided that the above 56159063Sharti * copyright notice and this permission notice appear in all copies. 57159063Sharti * 58159063Sharti * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 59159063Sharti * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 60159063Sharti * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 61159063Sharti * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 62159063Sharti * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 63122394Sharti * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 64122394Sharti * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 65122394Sharti */ 66122394Sharti 67142810Sharti#if defined(LIBC_SCCS) && !defined(lint) 68122394Shartistatic const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; 69159063Shartistatic const char rcsid[] = "$Id: res_init.c,v 1.16.18.7 2007/07/09 01:52:58 marka Exp $"; 70122394Sharti#endif /* LIBC_SCCS and not lint */ 71159063Sharti#include <sys/cdefs.h> 72159063Sharti__FBSDID("$FreeBSD$"); 73159063Sharti 74159063Sharti#include "port_before.h" 75159063Sharti 76122394Sharti#include "namespace.h" 77122394Sharti 78122394Sharti#include <sys/types.h> 79122394Sharti#include <sys/param.h> 80122394Sharti#include <sys/socket.h> 81122394Sharti#include <sys/time.h> 82122394Sharti 83122394Sharti#include <netinet/in.h> 84122394Sharti#include <arpa/inet.h> 85133429Sharti#include <arpa/nameser.h> 86133211Sharti 87133211Sharti#include <ctype.h> 88122394Sharti#include <stdio.h> 89133211Sharti#include <stdlib.h> 90122394Sharti#include <string.h> 91133211Sharti#include <unistd.h> 92122394Sharti#include <netdb.h> 93122394Sharti 94122394Sharti#include "un-namespace.h" 95122394Sharti 96122394Sharti#include "port_after.h" 97122394Sharti 98122394Sharti/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ 99122394Sharti#include <resolv.h> 100122394Sharti 101122394Sharti#include "res_private.h" 102122394Sharti 103122394Sharti/*% Options. Should all be left alone. */ 104122394Sharti#define RESOLVSORT 105122394Sharti#define DEBUG 106122394Sharti 107122394Sharti#ifdef SOLARIS2 108159063Sharti#include <sys/systeminfo.h> 109159063Sharti#endif 110159063Sharti 111122394Shartistatic void res_setoptions(res_state, const char *, const char *); 112159063Sharti 113159063Sharti#ifdef RESOLVSORT 114159063Shartistatic const char sort_mask[] = "/&"; 115122394Sharti#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) 116159063Shartistatic u_int32_t net_mask(struct in_addr); 117159063Sharti#endif 118159063Sharti 119122394Sharti#if !defined(isascii) /*%< XXX - could be a function */ 120159063Sharti# define isascii(c) (!(c & 0200)) 121159063Sharti#endif 122122394Sharti 123122394Sharti/* 124159063Sharti * Resolver state default settings. 125122394Sharti */ 126122394Sharti 127122394Sharti/*% 128122394Sharti * Set up default settings. If the configuration file exist, the values 129122394Sharti * there will have precedence. Otherwise, the server address is set to 130122394Sharti * INADDR_ANY and the default domain name comes from the gethostname(). 131122394Sharti * 132122394Sharti * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 133122394Sharti * rather than INADDR_ANY ("0.0.0.0") as the default name server address 134122394Sharti * since it was noted that INADDR_ANY actually meant ``the first interface 135122394Sharti * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, 136122394Sharti * it had to be "up" in order for you to reach your own name server. It 137122394Sharti * was later decided that since the recommended practice is to always 138122394Sharti * install local static routes through 127.0.0.1 for all your network 139122394Sharti * interfaces, that we could solve this problem without a code change. 140122394Sharti * 141122394Sharti * The configuration file should always be used, since it is the only way 142122394Sharti * to specify a default domain. If you are running a server on your local 143122394Sharti * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" 144122394Sharti * in the configuration file. 145122394Sharti * 146122394Sharti * Return 0 if completes successfully, -1 on error 147122394Sharti */ 148122394Shartiint 149122394Shartires_ninit(res_state statp) { 150122394Sharti extern int __res_vinit(res_state, int); 151122394Sharti 152122394Sharti return (__res_vinit(statp, 0)); 153122394Sharti} 154122394Sharti 155122394Sharti/*% This function has to be reachable by res_data.c but not publically. */ 156122394Shartiint 157122394Sharti__res_vinit(res_state statp, int preinit) { 158122394Sharti FILE *fp; 159133211Sharti char *cp, **pp; 160122394Sharti int n; 161122394Sharti char buf[BUFSIZ]; 162122394Sharti int nserv = 0; /*%< number of nameserver records read from file */ 163122394Sharti int haveenv = 0; 164122394Sharti int havesearch = 0; 165122394Sharti#ifdef RESOLVSORT 166122394Sharti int nsort = 0; 167122394Sharti char *net; 168122394Sharti#endif 169122394Sharti int dots; 170122394Sharti union res_sockaddr_union u[2]; 171122394Sharti int maxns = MAXNS; 172122394Sharti 173122394Sharti RES_SET_H_ERRNO(statp, 0); 174122394Sharti if (statp->_u._ext.ext != NULL) 175122394Sharti res_ndestroy(statp); 176122394Sharti 177122394Sharti if (!preinit) { 178122394Sharti statp->retrans = RES_TIMEOUT; 179122394Sharti statp->retry = RES_DFLRETRY; 180122394Sharti statp->options = RES_DEFAULT; 181122394Sharti statp->id = res_randomid(); 182159063Sharti } 183159063Sharti 184159063Sharti memset(u, 0, sizeof(u)); 185159063Sharti#ifdef USELOOPBACK 186159063Sharti u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); 187159063Sharti#else 188159063Sharti u[nserv].sin.sin_addr.s_addr = INADDR_ANY; 189159063Sharti#endif 190159063Sharti u[nserv].sin.sin_family = AF_INET; 191159063Sharti u[nserv].sin.sin_port = htons(NAMESERVER_PORT); 192159063Sharti#ifdef HAVE_SA_LEN 193159063Sharti u[nserv].sin.sin_len = sizeof(struct sockaddr_in); 194159063Sharti#endif 195159063Sharti nserv++; 196159063Sharti#ifdef HAS_INET6_STRUCTS 197159063Sharti#ifdef USELOOPBACK 198159063Sharti u[nserv].sin6.sin6_addr = in6addr_loopback; 199159063Sharti#else 200159063Sharti u[nserv].sin6.sin6_addr = in6addr_any; 201159063Sharti#endif 202159063Sharti u[nserv].sin6.sin6_family = AF_INET6; 203159063Sharti u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT); 204159063Sharti#ifdef HAVE_SA_LEN 205122394Sharti u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6); 206122394Sharti#endif 207122394Sharti nserv++; 208122394Sharti#endif 209122394Sharti statp->nscount = 0; 210122394Sharti statp->ndots = 1; 211122394Sharti statp->pfcode = 0; 212122394Sharti statp->_vcsock = -1; 213122394Sharti statp->_flags = 0; 214122394Sharti statp->qhook = NULL; 215145557Sharti statp->rhook = NULL; 216122394Sharti statp->_u._ext.nscount = 0; 217122394Sharti statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); 218122394Sharti if (statp->_u._ext.ext != NULL) { 219122394Sharti memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); 220159063Sharti statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; 221159063Sharti strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); 222159063Sharti strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); 223159063Sharti } else { 224159063Sharti /* 225159063Sharti * Historically res_init() rarely, if at all, failed. 226159063Sharti * Examples and applications exist which do not check 227159063Sharti * our return code. Furthermore several applications 228159063Sharti * simply call us to get the systems domainname. So 229122394Sharti * rather then immediately fail here we store the 230122394Sharti * failure, which is returned later, in h_errno. And 231159063Sharti * prevent the collection of 'nameserver' information 232159063Sharti * by setting maxns to 0. Thus applications that fail 233159063Sharti * to check our return code wont be able to make 234159063Sharti * queries anyhow. 235159063Sharti */ 236159063Sharti RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 237159063Sharti maxns = 0; 238159063Sharti } 239159063Sharti#ifdef RESOLVSORT 240159063Sharti statp->nsort = 0; 241159063Sharti#endif 242159063Sharti res_setservers(statp, u, nserv); 243159063Sharti 244159063Sharti#ifdef SOLARIS2 245159063Sharti /* 246159063Sharti * The old libresolv derived the defaultdomain from NIS/NIS+. 247159063Sharti * We want to keep this behaviour 248159063Sharti */ 249159063Sharti { 250159063Sharti char buf[sizeof(statp->defdname)], *cp; 251159063Sharti int ret; 252159063Sharti 253159063Sharti if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 && 254159063Sharti (unsigned int)ret <= sizeof(buf)) { 255159063Sharti if (buf[0] == '+') 256159063Sharti buf[0] = '.'; 257159063Sharti cp = strchr(buf, '.'); 258159063Sharti cp = (cp == NULL) ? buf : (cp + 1); 259159063Sharti strncpy(statp->defdname, cp, 260159063Sharti sizeof(statp->defdname) - 1); 261159063Sharti statp->defdname[sizeof(statp->defdname) - 1] = '\0'; 262159063Sharti } 263159063Sharti } 264159063Sharti#endif /* SOLARIS2 */ 265159063Sharti 266159063Sharti /* Allow user to override the local domain definition */ 267159063Sharti if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) { 268159063Sharti (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); 269159063Sharti statp->defdname[sizeof(statp->defdname) - 1] = '\0'; 270159063Sharti haveenv++; 271159063Sharti 272159063Sharti /* 273159063Sharti * Set search list to be blank-separated strings 274159063Sharti * from rest of env value. Permits users of LOCALDOMAIN 275159063Sharti * to still have a search list, and anyone to set the 276159063Sharti * one that they want to use as an individual (even more 277159063Sharti * important now that the rfc1535 stuff restricts searches) 278159063Sharti */ 279159063Sharti cp = statp->defdname; 280159063Sharti pp = statp->dnsrch; 281159063Sharti *pp++ = cp; 282159063Sharti for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { 283159063Sharti if (*cp == '\n') /*%< silly backwards compat */ 284159063Sharti break; 285159063Sharti else if (*cp == ' ' || *cp == '\t') { 286159063Sharti *cp = 0; 287159063Sharti n = 1; 288159063Sharti } else if (n) { 289159063Sharti *pp++ = cp; 290159063Sharti n = 0; 291159063Sharti havesearch = 1; 292159063Sharti } 293159063Sharti } 294159063Sharti /* null terminate last domain if there are excess */ 295159063Sharti while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') 296159063Sharti cp++; 297159063Sharti *cp = '\0'; 298159063Sharti *pp++ = 0; 299159063Sharti } 300159063Sharti 301159063Sharti#define MATCH(line, name) \ 302159063Sharti (!strncmp(line, name, sizeof(name) - 1) && \ 303159063Sharti (line[sizeof(name) - 1] == ' ' || \ 304159063Sharti line[sizeof(name) - 1] == '\t')) 305159063Sharti 306159063Sharti nserv = 0; 307159063Sharti if ((fp = fopen(_PATH_RESCONF, "re")) != NULL) { 308159063Sharti /* read the config file */ 309159063Sharti while (fgets(buf, sizeof(buf), fp) != NULL) { 310159063Sharti /* skip comments */ 311159063Sharti if (*buf == ';' || *buf == '#') 312159063Sharti continue; 313159063Sharti /* read default domain name */ 314159063Sharti if (MATCH(buf, "domain")) { 315159063Sharti if (haveenv) /*%< skip if have from environ */ 316159063Sharti continue; 317159063Sharti cp = buf + sizeof("domain") - 1; 318159063Sharti while (*cp == ' ' || *cp == '\t') 319159063Sharti cp++; 320159063Sharti if ((*cp == '\0') || (*cp == '\n')) 321159063Sharti continue; 322159063Sharti strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); 323159063Sharti statp->defdname[sizeof(statp->defdname) - 1] = '\0'; 324159063Sharti if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) 325159063Sharti *cp = '\0'; 326159063Sharti havesearch = 0; 327159063Sharti continue; 328159063Sharti } 329159063Sharti /* set search list */ 330159063Sharti if (MATCH(buf, "search")) { 331159063Sharti if (haveenv) /*%< skip if have from environ */ 332159063Sharti continue; 333159063Sharti cp = buf + sizeof("search") - 1; 334159063Sharti while (*cp == ' ' || *cp == '\t') 335159063Sharti cp++; 336159063Sharti if ((*cp == '\0') || (*cp == '\n')) 337159063Sharti continue; 338159063Sharti strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); 339159063Sharti statp->defdname[sizeof(statp->defdname) - 1] = '\0'; 340159063Sharti if ((cp = strchr(statp->defdname, '\n')) != NULL) 341159063Sharti *cp = '\0'; 342159063Sharti /* 343159063Sharti * Set search list to be blank-separated strings 344159063Sharti * on rest of line. 345159063Sharti */ 346159063Sharti cp = statp->defdname; 347159063Sharti pp = statp->dnsrch; 348159063Sharti *pp++ = cp; 349159063Sharti for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { 350159063Sharti if (*cp == ' ' || *cp == '\t') { 351159063Sharti *cp = 0; 352159063Sharti n = 1; 353159063Sharti } else if (n) { 354159063Sharti *pp++ = cp; 355159063Sharti n = 0; 356159063Sharti } 357159063Sharti } 358159063Sharti /* null terminate last domain if there are excess */ 359159063Sharti while (*cp != '\0' && *cp != ' ' && *cp != '\t') 360159063Sharti cp++; 361159063Sharti *cp = '\0'; 362159063Sharti *pp++ = 0; 363159063Sharti havesearch = 1; 364159063Sharti continue; 365159063Sharti } 366159063Sharti /* read nameservers to query */ 367159063Sharti if (MATCH(buf, "nameserver") && nserv < maxns) { 368159063Sharti struct addrinfo hints, *ai; 369159063Sharti char sbuf[NI_MAXSERV]; 370159063Sharti const size_t minsiz = 371159063Sharti sizeof(statp->_u._ext.ext->nsaddrs[0]); 372159063Sharti 373159063Sharti cp = buf + sizeof("nameserver") - 1; 374159063Sharti while (*cp == ' ' || *cp == '\t') 375159063Sharti cp++; 376159063Sharti cp[strcspn(cp, ";# \t\n")] = '\0'; 377159063Sharti if ((*cp != '\0') && (*cp != '\n')) { 378159063Sharti memset(&hints, 0, sizeof(hints)); 379159063Sharti hints.ai_family = PF_UNSPEC; 380122394Sharti hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 381122394Sharti hints.ai_flags = AI_NUMERICHOST; 382122394Sharti sprintf(sbuf, "%u", NAMESERVER_PORT); 383122394Sharti if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && 384122394Sharti ai->ai_addrlen <= minsiz) { 385122394Sharti if (statp->_u._ext.ext != NULL) { 386122394Sharti memcpy(&statp->_u._ext.ext->nsaddrs[nserv], 387122394Sharti ai->ai_addr, ai->ai_addrlen); 388159063Sharti } 389159063Sharti if (ai->ai_addrlen <= 390159063Sharti sizeof(statp->nsaddr_list[nserv])) { 391159063Sharti memcpy(&statp->nsaddr_list[nserv], 392159063Sharti ai->ai_addr, ai->ai_addrlen); 393159063Sharti } else 394122394Sharti statp->nsaddr_list[nserv].sin_family = 0; 395122394Sharti freeaddrinfo(ai); 396122394Sharti nserv++; 397122394Sharti } 398122394Sharti } 399122394Sharti continue; 400122394Sharti } 401122394Sharti#ifdef RESOLVSORT 402122394Sharti if (MATCH(buf, "sortlist")) { 403122394Sharti struct in_addr a; 404122394Sharti struct in6_addr a6; 405122394Sharti int m, i; 406122394Sharti u_char *u; 407122394Sharti struct __res_state_ext *ext = statp->_u._ext.ext; 408122394Sharti 409122394Sharti cp = buf + sizeof("sortlist") - 1; 410122394Sharti while (nsort < MAXRESOLVSORT) { 411122394Sharti while (*cp == ' ' || *cp == '\t') 412122394Sharti cp++; 413122394Sharti if (*cp == '\0' || *cp == '\n' || *cp == ';') 414159063Sharti break; 415159063Sharti net = cp; 416159063Sharti while (*cp && !ISSORTMASK(*cp) && *cp != ';' && 417159063Sharti isascii(*cp) && !isspace((unsigned char)*cp)) 418122394Sharti cp++; 419122394Sharti n = *cp; 420122394Sharti *cp = 0; 421122394Sharti if (inet_aton(net, &a)) { 422122394Sharti statp->sort_list[nsort].addr = a; 423122394Sharti if (ISSORTMASK(n)) { 424122394Sharti *cp++ = n; 425133211Sharti net = cp; 426159063Sharti while (*cp && *cp != ';' && 427122394Sharti isascii(*cp) && 428122394Sharti !isspace((unsigned char)*cp)) 429122394Sharti cp++; 430122394Sharti n = *cp; 431122394Sharti *cp = 0; 432122394Sharti if (inet_aton(net, &a)) { 433122394Sharti statp->sort_list[nsort].mask = a.s_addr; 434122394Sharti } else { 435122394Sharti statp->sort_list[nsort].mask = 436122394Sharti net_mask(statp->sort_list[nsort].addr); 437122394Sharti } 438159063Sharti } else { 439122394Sharti statp->sort_list[nsort].mask = 440122394Sharti net_mask(statp->sort_list[nsort].addr); 441122394Sharti } 442159063Sharti ext->sort_list[nsort].af = AF_INET; 443122394Sharti ext->sort_list[nsort].addr.ina = 444122394Sharti statp->sort_list[nsort].addr; 445122394Sharti ext->sort_list[nsort].mask.ina.s_addr = 446122394Sharti statp->sort_list[nsort].mask; 447122394Sharti nsort++; 448122394Sharti } 449122394Sharti else if (inet_pton(AF_INET6, net, &a6) == 1) { 450122394Sharti 451122394Sharti ext->sort_list[nsort].af = AF_INET6; 452122394Sharti ext->sort_list[nsort].addr.in6a = a6; 453122394Sharti u = (u_char *)&ext->sort_list[nsort].mask.in6a; 454122394Sharti *cp++ = n; 455122394Sharti net = cp; 456122394Sharti while (*cp && *cp != ';' && 457122394Sharti isascii(*cp) && !isspace(*cp)) 458122394Sharti cp++; 459122394Sharti m = n; 460122394Sharti n = *cp; 461122394Sharti *cp = 0; 462122394Sharti switch (m) { 463122394Sharti case '/': 464122394Sharti m = atoi(net); 465122394Sharti break; 466122394Sharti case '&': 467159063Sharti if (inet_pton(AF_INET6, net, u) == 1) { 468122394Sharti m = -1; 469122394Sharti break; 470122394Sharti } 471122394Sharti /*FALLTHROUGH*/ 472122394Sharti default: 473122394Sharti m = sizeof(struct in6_addr) * CHAR_BIT; 474159063Sharti break; 475122394Sharti } 476122394Sharti if (m >= 0) { 477159063Sharti for (i = 0; i < sizeof(struct in6_addr); i++) { 478122394Sharti if (m <= 0) { 479159063Sharti *u = 0; 480159063Sharti } else { 481159063Sharti m -= CHAR_BIT; 482159063Sharti *u = (u_char)~0; 483159063Sharti if (m < 0) 484159063Sharti *u <<= -m; 485122394Sharti } 486122394Sharti u++; 487122394Sharti } 488122394Sharti } 489159063Sharti statp->sort_list[nsort].addr.s_addr = 490122394Sharti (u_int32_t)0xffffffff; 491159063Sharti statp->sort_list[nsort].mask = 492122394Sharti (u_int32_t)0xffffffff; 493122394Sharti nsort++; 494122394Sharti } 495122394Sharti *cp = n; 496122394Sharti } 497122394Sharti continue; 498122394Sharti } 499122394Sharti#endif 500122394Sharti if (MATCH(buf, "options")) { 501122394Sharti res_setoptions(statp, buf + sizeof("options") - 1, "conf"); 502122394Sharti continue; 503122394Sharti } 504159063Sharti } 505122394Sharti if (nserv > 0) 506159063Sharti statp->nscount = nserv; 507122394Sharti#ifdef RESOLVSORT 508122394Sharti statp->nsort = nsort; 509122394Sharti#endif 510122394Sharti (void) fclose(fp); 511122394Sharti } 512122394Sharti/* 513122394Sharti * Last chance to get a nameserver. This should not normally 514122394Sharti * be necessary 515122394Sharti */ 516159063Sharti#ifdef NO_RESOLV_CONF 517122394Sharti if(nserv == 0) 518122394Sharti nserv = get_nameservers(statp); 519159063Sharti#endif 520159063Sharti 521159063Sharti if (statp->defdname[0] == 0 && 522159063Sharti gethostname(buf, sizeof(statp->defdname) - 1) == 0 && 523159063Sharti (cp = strchr(buf, '.')) != NULL) 524159063Sharti strcpy(statp->defdname, cp + 1); 525159063Sharti 526159063Sharti /* find components of local domain that might be searched */ 527159063Sharti if (havesearch == 0) { 528159063Sharti pp = statp->dnsrch; 529159063Sharti *pp++ = statp->defdname; 530159063Sharti *pp = NULL; 531159063Sharti 532159063Sharti dots = 0; 533159063Sharti for (cp = statp->defdname; *cp; cp++) 534159063Sharti dots += (*cp == '.'); 535159063Sharti 536159063Sharti cp = statp->defdname; 537159063Sharti while (pp < statp->dnsrch + MAXDFLSRCH) { 538159063Sharti if (dots < LOCALDOMAINPARTS) 539159063Sharti break; 540159063Sharti cp = strchr(cp, '.') + 1; /*%< we know there is one */ 541159063Sharti *pp++ = cp; 542122394Sharti dots--; 543122394Sharti } 544122394Sharti *pp = NULL; 545122394Sharti#ifdef DEBUG 546159063Sharti if (statp->options & RES_DEBUG) { 547159063Sharti printf(";; res_init()... default dnsrch list:\n"); 548159063Sharti for (pp = statp->dnsrch; *pp; pp++) 549159063Sharti printf(";;\t%s\n", *pp); 550159063Sharti printf(";;\t..END..\n"); 551159063Sharti } 552159063Sharti#endif 553159063Sharti } 554159063Sharti 555159063Sharti if (issetugid()) 556159063Sharti statp->options |= RES_NOALIASES; 557159063Sharti else if ((cp = getenv("RES_OPTIONS")) != NULL) 558159063Sharti res_setoptions(statp, cp, "env"); 559159063Sharti statp->options |= RES_INIT; 560159063Sharti return (statp->res_h_errno); 561122394Sharti} 562122394Sharti 563122394Shartistatic void 564122394Shartires_setoptions(res_state statp, const char *options, const char *source) 565122394Sharti{ 566122394Sharti const char *cp = options; 567122394Sharti int i; 568122394Sharti#ifndef _LIBC 569122394Sharti struct __res_state_ext *ext = statp->_u._ext.ext; 570159063Sharti#endif 571159063Sharti 572159063Sharti#ifdef DEBUG 573122394Sharti if (statp->options & RES_DEBUG) 574122394Sharti printf(";; res_setoptions(\"%s\", \"%s\")...\n", 575122394Sharti options, source); 576122394Sharti#endif 577122394Sharti while (*cp) { 578122394Sharti /* skip leading and inner runs of spaces */ 579122394Sharti while (*cp == ' ' || *cp == '\t') 580122394Sharti cp++; 581122394Sharti /* search for and process individual options */ 582122394Sharti if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { 583122394Sharti i = atoi(cp + sizeof("ndots:") - 1); 584122394Sharti if (i <= RES_MAXNDOTS) 585122394Sharti statp->ndots = i; 586122394Sharti else 587122394Sharti statp->ndots = RES_MAXNDOTS; 588122394Sharti#ifdef DEBUG 589122394Sharti if (statp->options & RES_DEBUG) 590122394Sharti printf(";;\tndots=%d\n", statp->ndots); 591122394Sharti#endif 592159063Sharti } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { 593159063Sharti i = atoi(cp + sizeof("timeout:") - 1); 594159063Sharti if (i <= RES_MAXRETRANS) 595159063Sharti statp->retrans = i; 596159063Sharti else 597159063Sharti statp->retrans = RES_MAXRETRANS; 598122394Sharti#ifdef DEBUG 599122394Sharti if (statp->options & RES_DEBUG) 600122394Sharti printf(";;\ttimeout=%d\n", statp->retrans); 601159063Sharti#endif 602122394Sharti#ifdef SOLARIS2 603159063Sharti } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) { 604159063Sharti /* 605122394Sharti * For backward compatibility, 'retrans' is 606159063Sharti * supported as an alias for 'timeout', though 607159063Sharti * without an imposed maximum. 608159063Sharti */ 609159063Sharti statp->retrans = atoi(cp + sizeof("retrans:") - 1); 610122394Sharti } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){ 611159063Sharti /* 612159063Sharti * For backward compatibility, 'retry' is 613159063Sharti * supported as an alias for 'attempts', though 614159063Sharti * without an imposed maximum. 615159063Sharti */ 616159063Sharti statp->retry = atoi(cp + sizeof("retry:") - 1); 617159063Sharti#endif /* SOLARIS2 */ 618159063Sharti } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ 619159063Sharti i = atoi(cp + sizeof("attempts:") - 1); 620159063Sharti if (i <= RES_MAXRETRY) 621159063Sharti statp->retry = i; 622159063Sharti else 623159063Sharti statp->retry = RES_MAXRETRY; 624159063Sharti#ifdef DEBUG 625159063Sharti if (statp->options & RES_DEBUG) 626159063Sharti printf(";;\tattempts=%d\n", statp->retry); 627159063Sharti#endif 628159063Sharti } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { 629159063Sharti#ifdef DEBUG 630159063Sharti if (!(statp->options & RES_DEBUG)) { 631159063Sharti printf(";; res_setoptions(\"%s\", \"%s\")..\n", 632159063Sharti options, source); 633159063Sharti statp->options |= RES_DEBUG; 634159063Sharti } 635159063Sharti printf(";;\tdebug\n"); 636159063Sharti#endif 637159063Sharti } else if (!strncmp(cp, "no_tld_query", 638159063Sharti sizeof("no_tld_query") - 1) || 639159063Sharti !strncmp(cp, "no-tld-query", 640159063Sharti sizeof("no-tld-query") - 1)) { 641159063Sharti statp->options |= RES_NOTLDQUERY; 642159063Sharti } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { 643159063Sharti statp->options |= RES_USE_INET6; 644159063Sharti } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) { 645159063Sharti statp->options |= RES_INSECURE1; 646159063Sharti } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) { 647159063Sharti statp->options |= RES_INSECURE2; 648159063Sharti } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { 649159063Sharti statp->options |= RES_ROTATE; 650159063Sharti } else if (!strncmp(cp, "no-check-names", 651159063Sharti sizeof("no-check-names") - 1)) { 652159063Sharti statp->options |= RES_NOCHECKNAME; 653159063Sharti } 654159063Sharti#ifdef RES_USE_EDNS0 655159063Sharti else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { 656159063Sharti statp->options |= RES_USE_EDNS0; 657159063Sharti } 658159063Sharti#endif 659159063Sharti#ifndef _LIBC 660159063Sharti else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { 661159063Sharti statp->options |= RES_USE_DNAME; 662159063Sharti } 663159063Sharti else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { 664159063Sharti if (ext == NULL) 665159063Sharti goto skip; 666159063Sharti cp += sizeof("nibble:") - 1; 667159063Sharti i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); 668159063Sharti strncpy(ext->nsuffix, cp, i); 669159063Sharti ext->nsuffix[i] = '\0'; 670159063Sharti } 671159063Sharti else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { 672159063Sharti if (ext == NULL) 673159063Sharti goto skip; 674159063Sharti cp += sizeof("nibble2:") - 1; 675159063Sharti i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); 676159063Sharti strncpy(ext->nsuffix2, cp, i); 677159063Sharti ext->nsuffix2[i] = '\0'; 678159063Sharti } 679159063Sharti else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { 680159063Sharti cp += sizeof("v6revmode:") - 1; 681159063Sharti /* "nibble" and "bitstring" used to be valid */ 682159063Sharti if (!strncmp(cp, "single", sizeof("single") - 1)) { 683159063Sharti statp->options |= RES_NO_NIBBLE2; 684159063Sharti } else if (!strncmp(cp, "both", sizeof("both") - 1)) { 685159063Sharti statp->options &= 686122394Sharti ~RES_NO_NIBBLE2; 687159063Sharti } 688159063Sharti } 689159063Sharti#endif 690159063Sharti else { 691159063Sharti /* XXX - print a warning here? */ 692159063Sharti } 693159063Sharti#ifndef _LIBC 694159063Sharti skip: 695159063Sharti#endif 696159063Sharti /* skip to next run of spaces */ 697159063Sharti while (*cp && *cp != ' ' && *cp != '\t') 698159063Sharti cp++; 699159063Sharti } 700159063Sharti} 701159063Sharti 702159063Sharti#ifdef RESOLVSORT 703159063Sharti/* XXX - should really support CIDR which means explicit masks always. */ 704159063Shartistatic u_int32_t 705159063Shartinet_mask(in) /*!< XXX - should really use system's version of this */ 706159063Sharti struct in_addr in; 707159063Sharti{ 708159063Sharti u_int32_t i = ntohl(in.s_addr); 709159063Sharti 710159063Sharti if (IN_CLASSA(i)) 711159063Sharti return (htonl(IN_CLASSA_NET)); 712159063Sharti else if (IN_CLASSB(i)) 713159063Sharti return (htonl(IN_CLASSB_NET)); 714159063Sharti return (htonl(IN_CLASSC_NET)); 715159063Sharti} 716159063Sharti#endif 717159063Sharti 718159063Shartiu_int 719159063Shartires_randomid(void) { 720159063Sharti struct timeval now; 721159063Sharti 722159063Sharti gettimeofday(&now, NULL); 723159063Sharti return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); 724159063Sharti} 725159063Sharti 726159063Sharti/*% 727159063Sharti * This routine is for closing the socket if a virtual circuit is used and 728159063Sharti * the program wants to close it. This provides support for endhostent() 729159063Sharti * which expects to close the socket. 730159063Sharti * 731159063Sharti * This routine is not expected to be user visible. 732159063Sharti */ 733159063Shartivoid 734159063Shartires_nclose(res_state statp) { 735159063Sharti int ns; 736159063Sharti 737159063Sharti if (statp->_vcsock >= 0) { 738159063Sharti (void) _close(statp->_vcsock); 739159063Sharti statp->_vcsock = -1; 740159063Sharti statp->_flags &= ~(RES_F_VC | RES_F_CONN); 741159063Sharti } 742159063Sharti for (ns = 0; ns < statp->_u._ext.nscount; ns++) { 743159063Sharti if (statp->_u._ext.nssocks[ns] != -1) { 744159063Sharti (void) _close(statp->_u._ext.nssocks[ns]); 745159063Sharti statp->_u._ext.nssocks[ns] = -1; 746298450Sngie } 747298450Sngie } 748159063Sharti} 749159063Sharti 750159063Shartivoid 751159063Shartires_ndestroy(res_state statp) { 752159063Sharti res_nclose(statp); 753159063Sharti if (statp->_u._ext.ext != NULL) 754159063Sharti free(statp->_u._ext.ext); 755159063Sharti statp->options &= ~RES_INIT; 756159063Sharti statp->_u._ext.ext = NULL; 757159063Sharti} 758159063Sharti 759159063Sharti#ifndef _LIBC 760159063Sharticonst char * 761159063Shartires_get_nibblesuffix(res_state statp) { 762159063Sharti if (statp->_u._ext.ext) 763159063Sharti return (statp->_u._ext.ext->nsuffix); 764159063Sharti return ("ip6.arpa"); 765159063Sharti} 766159063Sharti 767159063Sharticonst char * 768122394Shartires_get_nibblesuffix2(res_state statp) { 769122394Sharti if (statp->_u._ext.ext) 770122394Sharti return (statp->_u._ext.ext->nsuffix2); 771122394Sharti return ("ip6.int"); 772122394Sharti} 773122394Sharti#endif 774122394Sharti 775122394Shartivoid 776122394Shartires_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { 777122394Sharti int i, nserv; 778159063Sharti size_t size; 779154182Sharti 780122394Sharti /* close open servers */ 781122394Sharti res_nclose(statp); 782122394Sharti 783122394Sharti /* cause rtt times to be forgotten */ 784122394Sharti statp->_u._ext.nscount = 0; 785122394Sharti 786122394Sharti nserv = 0; 787122394Sharti for (i = 0; i < cnt && nserv < MAXNS; i++) { 788122394Sharti switch (set->sin.sin_family) { 789122394Sharti case AF_INET: 790122394Sharti size = sizeof(set->sin); 791122394Sharti if (statp->_u._ext.ext) 792159063Sharti memcpy(&statp->_u._ext.ext->nsaddrs[nserv], 793159063Sharti &set->sin, size); 794122394Sharti if (size <= sizeof(statp->nsaddr_list[nserv])) 795159063Sharti memcpy(&statp->nsaddr_list[nserv], 796122394Sharti &set->sin, size); 797159063Sharti else 798122394Sharti statp->nsaddr_list[nserv].sin_family = 0; 799122394Sharti nserv++; 800122394Sharti break; 801122394Sharti 802122394Sharti#ifdef HAS_INET6_STRUCTS 803122394Sharti case AF_INET6: 804122394Sharti size = sizeof(set->sin6); 805122394Sharti if (statp->_u._ext.ext) 806122394Sharti memcpy(&statp->_u._ext.ext->nsaddrs[nserv], 807122394Sharti &set->sin6, size); 808122394Sharti if (size <= sizeof(statp->nsaddr_list[nserv])) 809122394Sharti memcpy(&statp->nsaddr_list[nserv], 810122394Sharti &set->sin6, size); 811122394Sharti else 812122394Sharti statp->nsaddr_list[nserv].sin_family = 0; 813122394Sharti nserv++; 814122394Sharti break; 815122394Sharti#endif 816122394Sharti 817122394Sharti default: 818122394Sharti break; 819122394Sharti } 820122394Sharti set++; 821122394Sharti } 822122394Sharti statp->nscount = nserv; 823159063Sharti 824159063Sharti} 825159063Sharti 826159063Shartiint 827122394Shartires_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { 828122394Sharti int i; 829122394Sharti size_t size; 830159063Sharti u_int16_t family; 831122394Sharti 832122394Sharti for (i = 0; i < statp->nscount && i < cnt; i++) { 833122394Sharti if (statp->_u._ext.ext) 834122394Sharti family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; 835122394Sharti else 836122394Sharti family = statp->nsaddr_list[i].sin_family; 837122394Sharti 838122394Sharti switch (family) { 839122394Sharti case AF_INET: 840122394Sharti size = sizeof(set->sin); 841122394Sharti if (statp->_u._ext.ext) 842122394Sharti memcpy(&set->sin, 843122394Sharti &statp->_u._ext.ext->nsaddrs[i], 844122394Sharti size); 845122394Sharti else 846122394Sharti memcpy(&set->sin, &statp->nsaddr_list[i], 847122394Sharti size); 848122394Sharti break; 849122394Sharti 850122394Sharti#ifdef HAS_INET6_STRUCTS 851122394Sharti case AF_INET6: 852122394Sharti size = sizeof(set->sin6); 853122394Sharti if (statp->_u._ext.ext) 854122394Sharti memcpy(&set->sin6, 855122394Sharti &statp->_u._ext.ext->nsaddrs[i], 856122394Sharti size); 857122394Sharti else 858122394Sharti memcpy(&set->sin6, &statp->nsaddr_list[i], 859122394Sharti size); 860122394Sharti break; 861122394Sharti#endif 862122394Sharti 863159063Sharti default: 864159063Sharti set->sin.sin_family = 0; 865159063Sharti break; 866159063Sharti } 867159063Sharti set++; 868159063Sharti } 869159063Sharti return (statp->nscount); 870159063Sharti} 871159063Sharti 872159063Sharti/*! \file */ 873159063Sharti