3 Parser for /etc/resolv.conf file. */
6 * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
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.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
37 struct name_server *name_servers;
38 struct domain_search_list *domains;
39 char path_resolv_conf [] = _PATH_RESOLV_CONF;
41 void read_resolv_conf (parse_time)
48 struct name_server *sp, *sl, *ns;
49 struct domain_search_list *dp, *dl, *nd;
52 if ((file = open (path_resolv_conf, O_RDONLY)) < 0) {
53 log_error ("Can't open %s: %m", path_resolv_conf);
58 status = new_parse(&cfile, file, NULL, 0, path_resolv_conf, 1);
59 if (status != ISC_R_SUCCESS || cfile == NULL)
63 token = next_token (&val, (unsigned *)0, cfile);
64 if (token == END_OF_FILE)
66 else if (token == EOL)
68 else if (token == DOMAIN || token == SEARCH) {
70 struct domain_search_list *nd, **dp;
73 dn = parse_host_name (cfile);
78 for (nd = domains; nd; nd = nd -> next) {
80 if (!strcmp (nd -> domain, dn))
84 nd = new_domain_search_list (MDL);
86 log_fatal ("No memory for %s",
89 (struct domain_search_list *)0;
94 nd -> rcdate = parse_time;
95 token = peek_token (&val,
96 (unsigned *)0, cfile);
97 } while (token != EOL);
100 "junk after domain declaration");
101 skip_to_semi (cfile);
103 token = next_token (&val, (unsigned *)0, cfile);
104 } else if (token == NAMESERVER) {
105 struct name_server *ns, **sp;
108 parse_ip_addr (cfile, &iaddr);
111 for (ns = name_servers; ns; ns = ns -> next) {
113 if (!memcmp (&ns -> addr.sin_addr,
114 iaddr.iabuf, iaddr.len))
118 ns = new_name_server (MDL);
120 log_fatal ("No memory for nameserver %s",
122 ns -> next = (struct name_server *)0;
124 memcpy (&ns -> addr.sin_addr,
125 iaddr.iabuf, iaddr.len);
127 ns -> addr.sin_len = sizeof ns -> addr;
129 ns -> addr.sin_family = AF_INET;
130 ns -> addr.sin_port = htons (53);
131 memset (ns -> addr.sin_zero, 0,
132 sizeof ns -> addr.sin_zero);
134 ns -> rcdate = parse_time;
135 skip_to_semi (cfile);
137 skip_to_semi (cfile); /* Ignore what we don't grok. */
139 token = next_token (&val, (unsigned *)0, cfile);
141 /* Lose servers that are no longer in /etc/resolv.conf. */
142 sl = (struct name_server *)0;
143 for (sp = name_servers; sp; sp = ns) {
145 if (sp -> rcdate != parse_time) {
147 sl -> next = sp -> next;
149 name_servers = sp -> next;
150 /* We can't actually free the name server structure,
151 because somebody might be hanging on to it. If
152 your /etc/resolv.conf file changes a lot, this
153 could be a noticeable memory leak. */
158 /* Lose domains that are no longer in /etc/resolv.conf. */
159 dl = (struct domain_search_list *)0;
160 for (dp = domains; dp; dp = nd) {
162 if (dp -> rcdate != parse_time) {
164 dl -> next = dp -> next;
166 domains = dp -> next;
167 free_domain_search_list (dp, MDL);
174 /* Pick a name server from the /etc/resolv.conf file. */
176 struct name_server *first_name_server ()
181 /* Check /etc/resolv.conf and reload it if it's changed. */
182 if (cur_time > rcdate) {
183 if (stat (path_resolv_conf, &st) < 0) {
184 log_error ("Can't stat %s", path_resolv_conf);
185 return (struct name_server *)0;
187 if (st.st_mtime > rcdate) {
188 rcdate = cur_time + 1;
190 read_resolv_conf (rcdate);