]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/resolv.c
f59cae88f770f62e4c0f6fa9096dcbf6b165dc69
[thirdparty/dhcp.git] / common / resolv.c
1 /* resolv.c
2
3 Parser for /etc/resolv.conf file. */
4
5 /*
6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
8 *
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 *
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.
20 *
21 * Internet Systems Consortium, Inc.
22 * PO Box 360
23 * Newmarket, NH 03857 USA
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
29 #include "dhcpd.h"
30
31 struct name_server *name_servers;
32 struct domain_search_list *domains;
33 char path_resolv_conf [] = _PATH_RESOLV_CONF;
34
35 void read_resolv_conf (parse_time)
36 TIME parse_time;
37 {
38 int file;
39 struct parse *cfile;
40 const char *val;
41 int token;
42 struct name_server *sp, *sl, *ns;
43 struct domain_search_list *dp, *dl, *nd;
44 isc_result_t status;
45
46 if ((file = open (path_resolv_conf, O_RDONLY)) < 0) {
47 log_error ("Can't open %s: %m", path_resolv_conf);
48 return;
49 }
50
51 cfile = NULL;
52 status = new_parse(&cfile, file, NULL, 0, path_resolv_conf, 1);
53 if (status != ISC_R_SUCCESS || cfile == NULL)
54 return;
55
56 do {
57 token = next_token (&val, (unsigned *)0, cfile);
58 if (token == END_OF_FILE)
59 break;
60 else if (token == EOL)
61 continue;
62 else if (token == DOMAIN || token == SEARCH) {
63 do {
64 struct domain_search_list *nd, **dp;
65 char *dn;
66
67 dn = parse_host_name (cfile);
68 if (!dn)
69 break;
70
71 dp = &domains;
72 for (nd = domains; nd; nd = nd -> next) {
73 dp = &nd -> next;
74 if (!strcmp (nd -> domain, dn))
75 break;
76 }
77 if (!nd) {
78 nd = new_domain_search_list (MDL);
79 if (!nd)
80 log_fatal ("No memory for %s",
81 dn);
82 nd -> next =
83 (struct domain_search_list *)0;
84 *dp = nd;
85 nd -> domain = dn;
86 }
87 nd -> rcdate = parse_time;
88 token = peek_token (&val,
89 (unsigned *)0, cfile);
90 } while (token != EOL);
91 if (token != EOL) {
92 parse_warn (cfile,
93 "junk after domain declaration");
94 skip_to_semi (cfile);
95 }
96 skip_token(&val, (unsigned *)0, cfile);
97 } else if (token == NAMESERVER) {
98 struct name_server *ns, **sp;
99 struct iaddr iaddr;
100
101 parse_ip_addr (cfile, &iaddr);
102
103 sp = &name_servers;
104 for (ns = name_servers; ns; ns = ns -> next) {
105 sp = &ns -> next;
106 if (!memcmp (&ns -> addr.sin_addr,
107 iaddr.iabuf, iaddr.len))
108 break;
109 }
110 if (!ns) {
111 ns = new_name_server (MDL);
112 if (!ns)
113 log_fatal ("No memory for nameserver %s",
114 piaddr (iaddr));
115 ns -> next = (struct name_server *)0;
116 *sp = ns;
117 memcpy (&ns -> addr.sin_addr,
118 iaddr.iabuf, iaddr.len);
119 #ifdef HAVE_SA_LEN
120 ns -> addr.sin_len = sizeof ns -> addr;
121 #endif
122 ns -> addr.sin_family = AF_INET;
123 ns -> addr.sin_port = htons (53);
124 memset (ns -> addr.sin_zero, 0,
125 sizeof ns -> addr.sin_zero);
126 }
127 ns -> rcdate = parse_time;
128 skip_to_semi (cfile);
129 } else
130 skip_to_semi (cfile); /* Ignore what we don't grok. */
131 } while (1);
132 skip_token(&val, (unsigned *)0, cfile);
133
134 /* Lose servers that are no longer in /etc/resolv.conf. */
135 sl = (struct name_server *)0;
136 for (sp = name_servers; sp; sp = ns) {
137 ns = sp -> next;
138 if (sp -> rcdate != parse_time) {
139 if (sl)
140 sl -> next = sp -> next;
141 else
142 name_servers = sp -> next;
143 /* We can't actually free the name server structure,
144 because somebody might be hanging on to it. If
145 your /etc/resolv.conf file changes a lot, this
146 could be a noticeable memory leak. */
147 } else
148 sl = sp;
149 }
150
151 /* Lose domains that are no longer in /etc/resolv.conf. */
152 dl = (struct domain_search_list *)0;
153 for (dp = domains; dp; dp = nd) {
154 nd = dp -> next;
155 if (dp -> rcdate != parse_time) {
156 if (dl)
157 dl -> next = dp -> next;
158 else
159 domains = dp -> next;
160 free_domain_search_list (dp, MDL);
161 } else
162 dl = dp;
163 }
164 end_parse (&cfile);
165 }
166
167 /* Pick a name server from the /etc/resolv.conf file. */
168
169 struct name_server *first_name_server ()
170 {
171 static TIME rcdate;
172 struct stat st;
173
174 /* Check /etc/resolv.conf and reload it if it's changed. */
175 if (cur_time > rcdate) {
176 if (stat (path_resolv_conf, &st) < 0) {
177 log_error ("Can't stat %s", path_resolv_conf);
178 return (struct name_server *)0;
179 }
180 if (st.st_mtime > rcdate) {
181 rcdate = cur_time + 1;
182
183 read_resolv_conf (rcdate);
184 }
185 }
186
187 return name_servers;
188 }