PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

lib/libc/resolv/res_init.c

http://www.minix3.org/
C | 955 lines | 713 code | 71 blank | 171 comment | 238 complexity | acd5e87c5e97c771c989845bd12776a6 MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /* $NetBSD: res_init.c,v 1.22 2009/10/24 17:24:01 christos Exp $ */
  2. /*
  3. * Copyright (c) 1985, 1989, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. All advertising materials mentioning features or use of this software
  15. * must display the following acknowledgement:
  16. * This product includes software developed by the University of
  17. * California, Berkeley and its contributors.
  18. * 4. Neither the name of the University nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. */
  34. /*
  35. * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  36. *
  37. * Permission to use, copy, modify, and distribute this software for any
  38. * purpose with or without fee is hereby granted, provided that the above
  39. * copyright notice and this permission notice appear in all copies, and that
  40. * the name of Digital Equipment Corporation not be used in advertising or
  41. * publicity pertaining to distribution of the document or software without
  42. * specific, written prior permission.
  43. *
  44. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  45. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  46. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  47. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  48. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  49. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  50. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  51. * SOFTWARE.
  52. */
  53. /*
  54. * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  55. * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
  56. *
  57. * Permission to use, copy, modify, and distribute this software for any
  58. * purpose with or without fee is hereby granted, provided that the above
  59. * copyright notice and this permission notice appear in all copies.
  60. *
  61. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
  62. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  63. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
  64. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  65. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  66. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  67. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  68. */
  69. #include <sys/cdefs.h>
  70. #if defined(LIBC_SCCS) && !defined(lint)
  71. #ifdef notdef
  72. static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
  73. static const char rcsid[] = "Id: res_init.c,v 1.26 2008/12/11 09:59:00 marka Exp";
  74. #else
  75. __RCSID("$NetBSD: res_init.c,v 1.22 2009/10/24 17:24:01 christos Exp $");
  76. #endif
  77. #endif /* LIBC_SCCS and not lint */
  78. #include "port_before.h"
  79. #include "namespace.h"
  80. #include <sys/types.h>
  81. #include <sys/param.h>
  82. #include <sys/socket.h>
  83. #include <sys/stat.h>
  84. #include <sys/time.h>
  85. #ifndef __minix
  86. #include <sys/event.h>
  87. #endif /* !__minix */
  88. #include <netinet/in.h>
  89. #include <arpa/inet.h>
  90. #include <arpa/nameser.h>
  91. #include <ctype.h>
  92. #include <stdio.h>
  93. #include <stdlib.h>
  94. #include <string.h>
  95. #include <unistd.h>
  96. #include <fcntl.h>
  97. #include <netdb.h>
  98. #define HAVE_MD5
  99. #include <md5.h>
  100. #ifndef HAVE_MD5
  101. # include "../dst/md5.h"
  102. #else
  103. # ifdef SOLARIS2
  104. # include <sys/md5.h>
  105. # endif
  106. #endif
  107. #ifndef _MD5_H_
  108. # define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */
  109. #endif
  110. #include "port_after.h"
  111. #if 0
  112. #ifdef __weak_alias
  113. __weak_alias(res_ninit,_res_ninit)
  114. __weak_alias(res_randomid,__res_randomid)
  115. __weak_alias(res_nclose,_res_nclose)
  116. __weak_alias(res_ndestroy,_res_ndestroy)
  117. __weak_alias(res_get_nibblesuffix,__res_get_nibblesuffix)
  118. __weak_alias(res_get_nibblesuffix2,__res_get_nibblesuffix2)
  119. __weak_alias(res_getservers,__res_getservers)
  120. __weak_alias(res_setservers,__res_setservers)
  121. #endif
  122. #endif
  123. /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
  124. #include <resolv.h>
  125. #include "res_private.h"
  126. #define RESOLVSORT
  127. /*% Options. Should all be left alone. */
  128. #ifndef DEBUG
  129. #define DEBUG
  130. #endif
  131. #ifdef SOLARIS2
  132. #include <sys/systeminfo.h>
  133. #endif
  134. static void res_setoptions __P((res_state, const char *, const char *));
  135. #ifdef RESOLVSORT
  136. static const char sort_mask[] = "/&";
  137. #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
  138. static u_int32_t net_mask __P((struct in_addr));
  139. #endif
  140. #if !defined(isascii) /*%< XXX - could be a function */
  141. # define isascii(c) (!(c & 0200))
  142. #endif
  143. static struct timespec __res_conf_time;
  144. static const struct timespec ts = { 0, 0 };
  145. /*
  146. * Resolver state default settings.
  147. */
  148. /*%
  149. * Set up default settings. If the configuration file exist, the values
  150. * there will have precedence. Otherwise, the server address is set to
  151. * INADDR_ANY and the default domain name comes from the gethostname().
  152. *
  153. * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
  154. * rather than INADDR_ANY ("0.0.0.0") as the default name server address
  155. * since it was noted that INADDR_ANY actually meant ``the first interface
  156. * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
  157. * it had to be "up" in order for you to reach your own name server. It
  158. * was later decided that since the recommended practice is to always
  159. * install local static routes through 127.0.0.1 for all your network
  160. * interfaces, that we could solve this problem without a code change.
  161. *
  162. * The configuration file should always be used, since it is the only way
  163. * to specify a default domain. If you are running a server on your local
  164. * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
  165. * in the configuration file.
  166. *
  167. * Return 0 if completes successfully, -1 on error
  168. */
  169. int
  170. res_ninit(res_state statp) {
  171. return (__res_vinit(statp, 0));
  172. }
  173. /*% This function has to be reachable by res_data.c but not publically. */
  174. int
  175. __res_vinit(res_state statp, int preinit) {
  176. register FILE *fp;
  177. register char *cp, **pp;
  178. register int n;
  179. char buf[BUFSIZ];
  180. int nserv = 0; /*%< number of nameserver records read from file */
  181. int haveenv = 0;
  182. int havesearch = 0;
  183. #ifdef RESOLVSORT
  184. int nsort = 0;
  185. char *net;
  186. #endif
  187. int dots;
  188. union res_sockaddr_union u[2];
  189. int maxns = MAXNS;
  190. RES_SET_H_ERRNO(statp, 0);
  191. if ((statp->options & RES_INIT) != 0U)
  192. res_ndestroy(statp);
  193. if (!preinit) {
  194. statp->retrans = RES_TIMEOUT;
  195. statp->retry = RES_DFLRETRY;
  196. statp->options = RES_DEFAULT;
  197. }
  198. statp->_rnd = malloc(16);
  199. res_rndinit(statp);
  200. statp->id = res_nrandomid(statp);
  201. memset(u, 0, sizeof(u));
  202. #ifdef USELOOPBACK
  203. u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
  204. #else
  205. u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
  206. #endif
  207. u[nserv].sin.sin_family = AF_INET;
  208. u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
  209. #ifdef HAVE_SA_LEN
  210. u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
  211. #endif
  212. nserv++;
  213. #ifdef HAS_INET6_STRUCTS
  214. #ifdef USELOOPBACK
  215. u[nserv].sin6.sin6_addr = in6addr_loopback;
  216. #else
  217. u[nserv].sin6.sin6_addr = in6addr_any;
  218. #endif
  219. u[nserv].sin6.sin6_family = AF_INET6;
  220. u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
  221. #ifdef HAVE_SA_LEN
  222. u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
  223. #endif
  224. nserv++;
  225. #endif
  226. statp->nscount = 0;
  227. statp->ndots = 1;
  228. statp->pfcode = 0;
  229. statp->_vcsock = -1;
  230. statp->_flags = 0;
  231. statp->qhook = NULL;
  232. statp->rhook = NULL;
  233. statp->_u._ext.nscount = 0;
  234. statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
  235. if (statp->_u._ext.ext != NULL) {
  236. memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
  237. statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
  238. strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
  239. strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
  240. } else {
  241. /*
  242. * Historically res_init() rarely, if at all, failed.
  243. * Examples and applications exist which do not check
  244. * our return code. Furthermore several applications
  245. * simply call us to get the systems domainname. So
  246. * rather then immediately fail here we store the
  247. * failure, which is returned later, in h_errno. And
  248. * prevent the collection of 'nameserver' information
  249. * by setting maxns to 0. Thus applications that fail
  250. * to check our return code wont be able to make
  251. * queries anyhow.
  252. */
  253. RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
  254. maxns = 0;
  255. }
  256. #ifdef RESOLVSORT
  257. statp->nsort = 0;
  258. #endif
  259. res_setservers(statp, u, nserv);
  260. #ifdef SOLARIS2
  261. /*
  262. * The old libresolv derived the defaultdomain from NIS/NIS+.
  263. * We want to keep this behaviour
  264. */
  265. {
  266. char buf[sizeof(statp->defdname)], *cp;
  267. int ret;
  268. if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 &&
  269. (unsigned int)ret <= sizeof(buf)) {
  270. if (buf[0] == '+')
  271. buf[0] = '.';
  272. cp = strchr(buf, '.');
  273. cp = (cp == NULL) ? buf : (cp + 1);
  274. (void)strlcpy(statp->defdname, cp,
  275. sizeof(statp->defdname));
  276. }
  277. }
  278. #endif /* SOLARIS2 */
  279. /* Allow user to override the local domain definition */
  280. if ((cp = getenv("LOCALDOMAIN")) != NULL) {
  281. (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
  282. statp->defdname[sizeof(statp->defdname) - 1] = '\0';
  283. haveenv++;
  284. /*
  285. * Set search list to be blank-separated strings
  286. * from rest of env value. Permits users of LOCALDOMAIN
  287. * to still have a search list, and anyone to set the
  288. * one that they want to use as an individual (even more
  289. * important now that the rfc1535 stuff restricts searches)
  290. */
  291. cp = statp->defdname;
  292. pp = statp->dnsrch;
  293. *pp++ = cp;
  294. for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
  295. if (*cp == '\n') /*%< silly backwards compat */
  296. break;
  297. else if (*cp == ' ' || *cp == '\t') {
  298. *cp = 0;
  299. n = 1;
  300. } else if (n) {
  301. *pp++ = cp;
  302. n = 0;
  303. havesearch = 1;
  304. }
  305. }
  306. /* null terminate last domain if there are excess */
  307. while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
  308. cp++;
  309. *cp = '\0';
  310. *pp++ = 0;
  311. }
  312. #define MATCH(line, name) \
  313. (!strncmp(line, name, sizeof(name) - 1) && \
  314. (line[sizeof(name) - 1] == ' ' || \
  315. line[sizeof(name) - 1] == '\t'))
  316. nserv = 0;
  317. if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
  318. struct stat st;
  319. #ifndef __minix
  320. struct kevent kc;
  321. #endif /* !__minix */
  322. /* read the config file */
  323. while (fgets(buf, sizeof(buf), fp) != NULL) {
  324. /* skip comments */
  325. if (*buf == ';' || *buf == '#')
  326. continue;
  327. /* read default domain name */
  328. if (MATCH(buf, "domain")) {
  329. if (haveenv) /*%< skip if have from environ */
  330. continue;
  331. cp = buf + sizeof("domain") - 1;
  332. while (*cp == ' ' || *cp == '\t')
  333. cp++;
  334. if ((*cp == '\0') || (*cp == '\n'))
  335. continue;
  336. strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
  337. statp->defdname[sizeof(statp->defdname) - 1] = '\0';
  338. if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
  339. *cp = '\0';
  340. havesearch = 0;
  341. continue;
  342. }
  343. /* set search list */
  344. if (MATCH(buf, "search")) {
  345. if (haveenv) /*%< skip if have from environ */
  346. continue;
  347. cp = buf + sizeof("search") - 1;
  348. while (*cp == ' ' || *cp == '\t')
  349. cp++;
  350. if ((*cp == '\0') || (*cp == '\n'))
  351. continue;
  352. strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
  353. statp->defdname[sizeof(statp->defdname) - 1] = '\0';
  354. if ((cp = strchr(statp->defdname, '\n')) != NULL)
  355. *cp = '\0';
  356. /*
  357. * Set search list to be blank-separated strings
  358. * on rest of line.
  359. */
  360. cp = statp->defdname;
  361. pp = statp->dnsrch;
  362. *pp++ = cp;
  363. for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
  364. if (*cp == ' ' || *cp == '\t') {
  365. *cp = 0;
  366. n = 1;
  367. } else if (n) {
  368. *pp++ = cp;
  369. n = 0;
  370. }
  371. }
  372. /* null terminate last domain if there are excess */
  373. while (*cp != '\0' && *cp != ' ' && *cp != '\t')
  374. cp++;
  375. *cp = '\0';
  376. *pp++ = 0;
  377. havesearch = 1;
  378. continue;
  379. }
  380. /* read nameservers to query */
  381. if (MATCH(buf, "nameserver") && nserv < maxns) {
  382. struct addrinfo hints, *ai;
  383. char sbuf[NI_MAXSERV];
  384. const size_t minsiz =
  385. sizeof(statp->_u._ext.ext->nsaddrs[0]);
  386. cp = buf + sizeof("nameserver") - 1;
  387. while (*cp == ' ' || *cp == '\t')
  388. cp++;
  389. cp[strcspn(cp, ";# \t\n")] = '\0';
  390. if ((*cp != '\0') && (*cp != '\n')) {
  391. memset(&hints, 0, sizeof(hints));
  392. hints.ai_family = PF_UNSPEC;
  393. hints.ai_socktype = SOCK_DGRAM; /*dummy*/
  394. hints.ai_flags = AI_NUMERICHOST;
  395. sprintf(sbuf, "%u", NAMESERVER_PORT);
  396. if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
  397. ai->ai_addrlen <= minsiz) {
  398. if (statp->_u._ext.ext != NULL) {
  399. memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
  400. ai->ai_addr, ai->ai_addrlen);
  401. }
  402. if (ai->ai_addrlen <=
  403. sizeof(statp->nsaddr_list[nserv])) {
  404. memcpy(&statp->nsaddr_list[nserv],
  405. ai->ai_addr, ai->ai_addrlen);
  406. } else
  407. statp->nsaddr_list[nserv].sin_family = 0;
  408. freeaddrinfo(ai);
  409. nserv++;
  410. }
  411. }
  412. continue;
  413. }
  414. #ifdef RESOLVSORT
  415. if (MATCH(buf, "sortlist")) {
  416. struct in_addr a;
  417. cp = buf + sizeof("sortlist") - 1;
  418. while (nsort < MAXRESOLVSORT) {
  419. while (*cp == ' ' || *cp == '\t')
  420. cp++;
  421. if (*cp == '\0' || *cp == '\n' || *cp == ';')
  422. break;
  423. net = cp;
  424. while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
  425. isascii(*cp) && !isspace((unsigned char)*cp))
  426. cp++;
  427. n = *cp;
  428. *cp = 0;
  429. if (inet_aton(net, &a)) {
  430. statp->sort_list[nsort].addr = a;
  431. if (ISSORTMASK(n)) {
  432. *cp++ = n;
  433. net = cp;
  434. while (*cp && *cp != ';' &&
  435. isascii(*cp) &&
  436. !isspace((unsigned char)*cp))
  437. cp++;
  438. n = *cp;
  439. *cp = 0;
  440. if (inet_aton(net, &a)) {
  441. statp->sort_list[nsort].mask = a.s_addr;
  442. } else {
  443. statp->sort_list[nsort].mask =
  444. net_mask(statp->sort_list[nsort].addr);
  445. }
  446. } else {
  447. statp->sort_list[nsort].mask =
  448. net_mask(statp->sort_list[nsort].addr);
  449. }
  450. nsort++;
  451. }
  452. *cp = n;
  453. }
  454. continue;
  455. }
  456. #endif
  457. if (MATCH(buf, "options")) {
  458. res_setoptions(statp, buf + sizeof("options") - 1, "conf");
  459. continue;
  460. }
  461. }
  462. if (nserv > 0)
  463. statp->nscount = nserv;
  464. #ifdef RESOLVSORT
  465. statp->nsort = nsort;
  466. #endif
  467. statp->_u._ext.ext->resfd = dup(fileno(fp));
  468. (void) fclose(fp);
  469. if (fstat(statp->_u._ext.ext->resfd, &st) != -1)
  470. __res_conf_time = statp->_u._ext.ext->res_conf_time =
  471. st.st_mtimespec;
  472. #ifndef __minix
  473. statp->_u._ext.ext->kq = kqueue();
  474. (void)fcntl(statp->_u._ext.ext->kq, F_SETFD, FD_CLOEXEC);
  475. (void)fcntl(statp->_u._ext.ext->resfd, F_SETFD, FD_CLOEXEC);
  476. EV_SET(&kc, statp->_u._ext.ext->resfd, EVFILT_VNODE,
  477. EV_ADD|EV_ENABLE|EV_CLEAR, NOTE_DELETE|NOTE_WRITE| NOTE_EXTEND|
  478. NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE, 0, 0);
  479. (void)kevent(statp->_u._ext.ext->kq, &kc, 1, NULL, 0, &ts);
  480. #else /* __minix */
  481. statp->_u._ext.ext->kq = -1;
  482. #endif /* !__minix */
  483. } else {
  484. statp->_u._ext.ext->kq = -1;
  485. statp->_u._ext.ext->resfd = -1;
  486. }
  487. /*
  488. * Last chance to get a nameserver. This should not normally
  489. * be necessary
  490. */
  491. #ifdef NO_RESOLV_CONF
  492. if(nserv == 0)
  493. nserv = get_nameservers(statp);
  494. #endif
  495. if (statp->defdname[0] == 0 &&
  496. gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
  497. (cp = strchr(buf, '.')) != NULL)
  498. strcpy(statp->defdname, cp + 1);
  499. /* find components of local domain that might be searched */
  500. if (havesearch == 0) {
  501. pp = statp->dnsrch;
  502. *pp++ = statp->defdname;
  503. *pp = NULL;
  504. dots = 0;
  505. for (cp = statp->defdname; *cp; cp++)
  506. dots += (*cp == '.');
  507. cp = statp->defdname;
  508. while (pp < statp->dnsrch + MAXDFLSRCH) {
  509. if (dots < LOCALDOMAINPARTS)
  510. break;
  511. cp = strchr(cp, '.') + 1; /*%< we know there is one */
  512. *pp++ = cp;
  513. dots--;
  514. }
  515. *pp = NULL;
  516. #ifdef DEBUG
  517. if (statp->options & RES_DEBUG) {
  518. printf(";; res_init()... default dnsrch list:\n");
  519. for (pp = statp->dnsrch; *pp; pp++)
  520. printf(";;\t%s\n", *pp);
  521. printf(";;\t..END..\n");
  522. }
  523. #endif
  524. }
  525. if ((cp = getenv("RES_OPTIONS")) != NULL)
  526. res_setoptions(statp, cp, "env");
  527. statp->options |= RES_INIT;
  528. return (statp->res_h_errno);
  529. }
  530. int
  531. res_check(res_state statp, struct timespec *mtime)
  532. {
  533. #ifdef __minix
  534. /*
  535. * XXX: No update on change.
  536. */
  537. return 0;
  538. #else /* !__minix */
  539. /*
  540. * If the times are equal, then we check if there
  541. * was a kevent related to resolv.conf and reload.
  542. * If the times are not equal, then we don't bother
  543. * to check the kevent, because another thread already
  544. * did, loaded and changed the time.
  545. */
  546. if (timespeccmp(&statp->_u._ext.ext->res_conf_time,
  547. &__res_conf_time, ==)) {
  548. struct kevent ke;
  549. if (statp->_u._ext.ext->kq == -1)
  550. goto out;
  551. switch (kevent(statp->_u._ext.ext->kq, NULL, 0, &ke, 1, &ts)) {
  552. case 0:
  553. case -1:
  554. out:
  555. if (mtime)
  556. *mtime = __res_conf_time;
  557. return 0;
  558. default:
  559. break;
  560. }
  561. }
  562. (void)__res_vinit(statp, 0);
  563. if (mtime)
  564. *mtime = __res_conf_time;
  565. return 1;
  566. #endif /* !__minix */
  567. }
  568. static void
  569. res_setoptions(res_state statp, const char *options, const char *source)
  570. {
  571. const char *cp = options;
  572. int i;
  573. struct __res_state_ext *ext = statp->_u._ext.ext;
  574. #ifdef DEBUG
  575. if (statp->options & RES_DEBUG)
  576. printf(";; res_setoptions(\"%s\", \"%s\")...\n",
  577. options, source);
  578. #endif
  579. while (*cp) {
  580. /* skip leading and inner runs of spaces */
  581. while (*cp == ' ' || *cp == '\t')
  582. cp++;
  583. /* search for and process individual options */
  584. if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
  585. i = atoi(cp + sizeof("ndots:") - 1);
  586. if (i <= RES_MAXNDOTS)
  587. statp->ndots = i;
  588. else
  589. statp->ndots = RES_MAXNDOTS;
  590. #ifdef DEBUG
  591. if (statp->options & RES_DEBUG)
  592. printf(";;\tndots=%d\n", statp->ndots);
  593. #endif
  594. } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
  595. i = atoi(cp + sizeof("timeout:") - 1);
  596. if (i <= RES_MAXRETRANS)
  597. statp->retrans = i;
  598. else
  599. statp->retrans = RES_MAXRETRANS;
  600. #ifdef DEBUG
  601. if (statp->options & RES_DEBUG)
  602. printf(";;\ttimeout=%d\n", statp->retrans);
  603. #endif
  604. #ifdef SOLARIS2
  605. } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) {
  606. /*
  607. * For backward compatibility, 'retrans' is
  608. * supported as an alias for 'timeout', though
  609. * without an imposed maximum.
  610. */
  611. statp->retrans = atoi(cp + sizeof("retrans:") - 1);
  612. } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){
  613. /*
  614. * For backward compatibility, 'retry' is
  615. * supported as an alias for 'attempts', though
  616. * without an imposed maximum.
  617. */
  618. statp->retry = atoi(cp + sizeof("retry:") - 1);
  619. #endif /* SOLARIS2 */
  620. } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
  621. i = atoi(cp + sizeof("attempts:") - 1);
  622. if (i <= RES_MAXRETRY)
  623. statp->retry = i;
  624. else
  625. statp->retry = RES_MAXRETRY;
  626. #ifdef DEBUG
  627. if (statp->options & RES_DEBUG)
  628. printf(";;\tattempts=%d\n", statp->retry);
  629. #endif
  630. } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
  631. #ifdef DEBUG
  632. if (!(statp->options & RES_DEBUG)) {
  633. printf(";; res_setoptions(\"%s\", \"%s\")..\n",
  634. options, source);
  635. statp->options |= RES_DEBUG;
  636. }
  637. printf(";;\tdebug\n");
  638. #endif
  639. } else if (!strncmp(cp, "no_tld_query",
  640. sizeof("no_tld_query") - 1) ||
  641. !strncmp(cp, "no-tld-query",
  642. sizeof("no-tld-query") - 1)) {
  643. statp->options |= RES_NOTLDQUERY;
  644. } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
  645. statp->options |= RES_USE_INET6;
  646. } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
  647. statp->options |= RES_ROTATE;
  648. } else if (!strncmp(cp, "no-check-names",
  649. sizeof("no-check-names") - 1)) {
  650. statp->options |= RES_NOCHECKNAME;
  651. }
  652. #ifdef RES_USE_EDNS0
  653. else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
  654. statp->options |= RES_USE_EDNS0;
  655. }
  656. #endif
  657. else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
  658. statp->options |= RES_USE_DNAME;
  659. }
  660. else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
  661. if (ext == NULL)
  662. goto skip;
  663. cp += sizeof("nibble:") - 1;
  664. i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
  665. strncpy(ext->nsuffix, cp, (size_t)i);
  666. ext->nsuffix[i] = '\0';
  667. }
  668. else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
  669. if (ext == NULL)
  670. goto skip;
  671. cp += sizeof("nibble2:") - 1;
  672. i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
  673. strncpy(ext->nsuffix2, cp, (size_t)i);
  674. ext->nsuffix2[i] = '\0';
  675. }
  676. else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
  677. cp += sizeof("v6revmode:") - 1;
  678. /* "nibble" and "bitstring" used to be valid */
  679. if (!strncmp(cp, "single", sizeof("single") - 1)) {
  680. statp->options |= RES_NO_NIBBLE2;
  681. } else if (!strncmp(cp, "both", sizeof("both") - 1)) {
  682. statp->options &=
  683. ~RES_NO_NIBBLE2;
  684. }
  685. }
  686. else {
  687. /* XXX - print a warning here? */
  688. }
  689. skip:
  690. /* skip to next run of spaces */
  691. while (*cp && *cp != ' ' && *cp != '\t')
  692. cp++;
  693. }
  694. }
  695. #ifdef RESOLVSORT
  696. /* XXX - should really support CIDR which means explicit masks always. */
  697. static u_int32_t
  698. net_mask(in) /*!< XXX - should really use system's version of this */
  699. struct in_addr in;
  700. {
  701. register u_int32_t i = ntohl(in.s_addr);
  702. if (IN_CLASSA(i))
  703. return (htonl(IN_CLASSA_NET));
  704. else if (IN_CLASSB(i))
  705. return (htonl(IN_CLASSB_NET));
  706. return (htonl(IN_CLASSC_NET));
  707. }
  708. #endif
  709. static u_char srnd[16];
  710. void
  711. res_rndinit(res_state statp)
  712. {
  713. struct timeval now;
  714. u_int32_t u32;
  715. u_int16_t u16;
  716. u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd;
  717. gettimeofday(&now, NULL);
  718. u32 = (u_int32_t)now.tv_sec;
  719. memcpy(rnd, &u32, 4);
  720. u32 = now.tv_usec;
  721. memcpy(rnd + 4, &u32, 4);
  722. u32 += (u_int32_t)now.tv_sec;
  723. memcpy(rnd + 8, &u32, 4);
  724. u16 = getpid();
  725. memcpy(rnd + 12, &u16, 2);
  726. }
  727. u_int
  728. res_nrandomid(res_state statp) {
  729. struct timeval now;
  730. u_int16_t u16;
  731. MD5_CTX ctx;
  732. u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd;
  733. gettimeofday(&now, NULL);
  734. u16 = (u_int16_t) (now.tv_sec ^ now.tv_usec);
  735. memcpy(rnd + 14, &u16, 2);
  736. #ifndef HAVE_MD5
  737. MD5_Init(&ctx);
  738. MD5_Update(&ctx, rnd, 16);
  739. MD5_Final(rnd, &ctx);
  740. #else
  741. MD5Init(&ctx);
  742. MD5Update(&ctx, rnd, 16);
  743. MD5Final(rnd, &ctx);
  744. #endif
  745. memcpy(&u16, rnd + 14, 2);
  746. return ((u_int) u16);
  747. }
  748. /*%
  749. * This routine is for closing the socket if a virtual circuit is used and
  750. * the program wants to close it. This provides support for endhostent()
  751. * which expects to close the socket.
  752. *
  753. * This routine is not expected to be user visible.
  754. */
  755. void
  756. res_nclose(res_state statp) {
  757. int ns;
  758. if (statp->_vcsock >= 0) {
  759. (void) close(statp->_vcsock);
  760. statp->_vcsock = -1;
  761. statp->_flags &= ~(RES_F_VC | RES_F_CONN);
  762. }
  763. for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
  764. if (statp->_u._ext.nssocks[ns] != -1) {
  765. (void) close(statp->_u._ext.nssocks[ns]);
  766. statp->_u._ext.nssocks[ns] = -1;
  767. }
  768. }
  769. }
  770. void
  771. res_ndestroy(res_state statp) {
  772. res_nclose(statp);
  773. if (statp->_u._ext.ext != NULL) {
  774. if (statp->_u._ext.ext->kq != -1)
  775. (void)close(statp->_u._ext.ext->kq);
  776. if (statp->_u._ext.ext->resfd != -1)
  777. (void)close(statp->_u._ext.ext->resfd);
  778. free(statp->_u._ext.ext);
  779. statp->_u._ext.ext = NULL;
  780. }
  781. if (statp->_rnd != NULL) {
  782. free(statp->_rnd);
  783. statp->_rnd = NULL;
  784. }
  785. statp->options &= ~RES_INIT;
  786. }
  787. const char *
  788. res_get_nibblesuffix(res_state statp) {
  789. if (statp->_u._ext.ext)
  790. return (statp->_u._ext.ext->nsuffix);
  791. return ("ip6.arpa");
  792. }
  793. const char *
  794. res_get_nibblesuffix2(res_state statp) {
  795. if (statp->_u._ext.ext)
  796. return (statp->_u._ext.ext->nsuffix2);
  797. return ("ip6.int");
  798. }
  799. void
  800. res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
  801. int i, nserv;
  802. size_t size;
  803. /* close open servers */
  804. res_nclose(statp);
  805. /* cause rtt times to be forgotten */
  806. statp->_u._ext.nscount = 0;
  807. nserv = 0;
  808. for (i = 0; i < cnt && nserv < MAXNS; i++) {
  809. switch (set->sin.sin_family) {
  810. case AF_INET:
  811. size = sizeof(set->sin);
  812. if (statp->_u._ext.ext)
  813. memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
  814. &set->sin, size);
  815. if (size <= sizeof(statp->nsaddr_list[nserv]))
  816. memcpy(&statp->nsaddr_list[nserv],
  817. &set->sin, size);
  818. else
  819. statp->nsaddr_list[nserv].sin_family = 0;
  820. nserv++;
  821. break;
  822. #ifdef HAS_INET6_STRUCTS
  823. case AF_INET6:
  824. size = sizeof(set->sin6);
  825. if (statp->_u._ext.ext)
  826. memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
  827. &set->sin6, size);
  828. if (size <= sizeof(statp->nsaddr_list[nserv]))
  829. memcpy(&statp->nsaddr_list[nserv],
  830. &set->sin6, size);
  831. else
  832. statp->nsaddr_list[nserv].sin_family = 0;
  833. nserv++;
  834. break;
  835. #endif
  836. default:
  837. break;
  838. }
  839. set++;
  840. }
  841. statp->nscount = nserv;
  842. }
  843. int
  844. res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
  845. int i;
  846. size_t size;
  847. u_int16_t family;
  848. for (i = 0; i < statp->nscount && i < cnt; i++) {
  849. if (statp->_u._ext.ext)
  850. family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
  851. else
  852. family = statp->nsaddr_list[i].sin_family;
  853. switch (family) {
  854. case AF_INET:
  855. size = sizeof(set->sin);
  856. if (statp->_u._ext.ext)
  857. memcpy(&set->sin,
  858. &statp->_u._ext.ext->nsaddrs[i],
  859. size);
  860. else
  861. memcpy(&set->sin, &statp->nsaddr_list[i],
  862. size);
  863. break;
  864. #ifdef HAS_INET6_STRUCTS
  865. case AF_INET6:
  866. size = sizeof(set->sin6);
  867. if (statp->_u._ext.ext)
  868. memcpy(&set->sin6,
  869. &statp->_u._ext.ext->nsaddrs[i],
  870. size);
  871. else
  872. memcpy(&set->sin6, &statp->nsaddr_list[i],
  873. size);
  874. break;
  875. #endif
  876. default:
  877. set->sin.sin_family = 0;
  878. break;
  879. }
  880. set++;
  881. }
  882. return (statp->nscount);
  883. }
  884. /*! \file */