]>
Commit | Line | Data |
---|---|---|
a7de06ee TL |
1 | /* resolv.c |
2 | ||
3 | Parser for /etc/resolv.conf file. */ | |
4 | ||
5 | /* | |
dc9d7b08 MA |
6 | * Copyright (c) 2009,2013 by Internet Systems Consortium, Inc. ("ISC") |
7 | * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC") | |
98311e4b | 8 | * Copyright (c) 1996-2003 by Internet Software Consortium |
a7de06ee | 9 | * |
98311e4b DH |
10 | * Permission to use, copy, modify, and distribute this software for any |
11 | * purpose with or without fee is hereby granted, provided that the above | |
12 | * copyright notice and this permission notice appear in all copies. | |
a7de06ee | 13 | * |
98311e4b DH |
14 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES |
15 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR | |
17 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
18 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
19 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
20 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
a7de06ee | 21 | * |
98311e4b DH |
22 | * Internet Systems Consortium, Inc. |
23 | * 950 Charter Street | |
24 | * Redwood City, CA 94063 | |
25 | * <info@isc.org> | |
2c85ac9b | 26 | * https://www.isc.org/ |
49733f31 | 27 | * |
98311e4b | 28 | * This software has been written for Internet Systems Consortium |
49733f31 | 29 | * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. |
98311e4b | 30 | * To learn more about Internet Systems Consortium, see |
2c85ac9b | 31 | * ``https://www.isc.org/''. To learn more about Vixie Enterprises, |
49733f31 TL |
32 | * see ``http://www.vix.com''. To learn more about Nominum, Inc., see |
33 | * ``http://www.nominum.com''. | |
a7de06ee TL |
34 | */ |
35 | ||
a7de06ee | 36 | #include "dhcpd.h" |
a7de06ee TL |
37 | |
38 | struct name_server *name_servers; | |
39 | struct domain_search_list *domains; | |
40 | char path_resolv_conf [] = _PATH_RESOLV_CONF; | |
41 | ||
42 | void read_resolv_conf (parse_time) | |
43 | TIME parse_time; | |
44 | { | |
3b4f8a4a TL |
45 | int file; |
46 | struct parse *cfile; | |
b1b7b521 | 47 | const char *val; |
a7de06ee | 48 | int token; |
a7de06ee TL |
49 | struct name_server *sp, *sl, *ns; |
50 | struct domain_search_list *dp, *dl, *nd; | |
c40e954c | 51 | isc_result_t status; |
a7de06ee | 52 | |
3e4618c4 | 53 | if ((file = open (path_resolv_conf, O_RDONLY)) < 0) { |
8ae2d595 | 54 | log_error ("Can't open %s: %m", path_resolv_conf); |
732a90b2 TL |
55 | return; |
56 | } | |
57 | ||
c40e954c EH |
58 | cfile = NULL; |
59 | status = new_parse(&cfile, file, NULL, 0, path_resolv_conf, 1); | |
60 | if (status != ISC_R_SUCCESS || cfile == NULL) | |
61 | return; | |
3b4f8a4a | 62 | |
a7de06ee | 63 | do { |
b3519f23 | 64 | token = next_token (&val, (unsigned *)0, cfile); |
0b69dcc8 | 65 | if (token == END_OF_FILE) |
a7de06ee TL |
66 | break; |
67 | else if (token == EOL) | |
68 | continue; | |
69 | else if (token == DOMAIN || token == SEARCH) { | |
70 | do { | |
71 | struct domain_search_list *nd, **dp; | |
72 | char *dn; | |
73 | ||
74 | dn = parse_host_name (cfile); | |
75 | if (!dn) | |
76 | break; | |
77 | ||
78 | dp = &domains; | |
79 | for (nd = domains; nd; nd = nd -> next) { | |
80 | dp = &nd -> next; | |
81 | if (!strcmp (nd -> domain, dn)) | |
82 | break; | |
83 | } | |
84 | if (!nd) { | |
4bd8800e | 85 | nd = new_domain_search_list (MDL); |
a7de06ee | 86 | if (!nd) |
3b4f8a4a TL |
87 | log_fatal ("No memory for %s", |
88 | dn); | |
a7de06ee TL |
89 | nd -> next = |
90 | (struct domain_search_list *)0; | |
91 | *dp = nd; | |
92 | nd -> domain = dn; | |
a7de06ee TL |
93 | } |
94 | nd -> rcdate = parse_time; | |
b3519f23 TL |
95 | token = peek_token (&val, |
96 | (unsigned *)0, cfile); | |
2c50133e | 97 | } while (token != EOL); |
a7de06ee | 98 | if (token != EOL) { |
3b4f8a4a TL |
99 | parse_warn (cfile, |
100 | "junk after domain declaration"); | |
a7de06ee TL |
101 | skip_to_semi (cfile); |
102 | } | |
dc9d7b08 | 103 | skip_token(&val, (unsigned *)0, cfile); |
a7de06ee TL |
104 | } else if (token == NAMESERVER) { |
105 | struct name_server *ns, **sp; | |
106 | struct iaddr iaddr; | |
107 | ||
108 | parse_ip_addr (cfile, &iaddr); | |
109 | ||
110 | sp = &name_servers; | |
111 | for (ns = name_servers; ns; ns = ns -> next) { | |
112 | sp = &ns -> next; | |
113 | if (!memcmp (&ns -> addr.sin_addr, | |
114 | iaddr.iabuf, iaddr.len)) | |
115 | break; | |
116 | } | |
117 | if (!ns) { | |
4bd8800e | 118 | ns = new_name_server (MDL); |
a7de06ee | 119 | if (!ns) |
3b4f8a4a | 120 | log_fatal ("No memory for nameserver %s", |
a7de06ee TL |
121 | piaddr (iaddr)); |
122 | ns -> next = (struct name_server *)0; | |
123 | *sp = ns; | |
124 | memcpy (&ns -> addr.sin_addr, | |
125 | iaddr.iabuf, iaddr.len); | |
126 | #ifdef HAVE_SA_LEN | |
127 | ns -> addr.sin_len = sizeof ns -> addr; | |
128 | #endif | |
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); | |
133 | } | |
134 | ns -> rcdate = parse_time; | |
135 | skip_to_semi (cfile); | |
357708da TL |
136 | } else |
137 | skip_to_semi (cfile); /* Ignore what we don't grok. */ | |
a7de06ee | 138 | } while (1); |
dc9d7b08 | 139 | skip_token(&val, (unsigned *)0, cfile); |
a7de06ee TL |
140 | |
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) { | |
144 | ns = sp -> next; | |
145 | if (sp -> rcdate != parse_time) { | |
146 | if (sl) | |
147 | sl -> next = sp -> next; | |
148 | else | |
149 | name_servers = sp -> next; | |
7e204261 TL |
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 | |
20ae1aff | 153 | could be a noticeable memory leak. */ |
a7de06ee TL |
154 | } else |
155 | sl = sp; | |
156 | } | |
157 | ||
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) { | |
161 | nd = dp -> next; | |
162 | if (dp -> rcdate != parse_time) { | |
163 | if (dl) | |
164 | dl -> next = dp -> next; | |
165 | else | |
166 | domains = dp -> next; | |
4bd8800e | 167 | free_domain_search_list (dp, MDL); |
a7de06ee TL |
168 | } else |
169 | dl = dp; | |
170 | } | |
3b4f8a4a | 171 | end_parse (&cfile); |
a7de06ee TL |
172 | } |
173 | ||
174 | /* Pick a name server from the /etc/resolv.conf file. */ | |
175 | ||
7e204261 | 176 | struct name_server *first_name_server () |
a7de06ee | 177 | { |
a7de06ee TL |
178 | static TIME rcdate; |
179 | struct stat st; | |
180 | ||
181 | /* Check /etc/resolv.conf and reload it if it's changed. */ | |
182 | if (cur_time > rcdate) { | |
732a90b2 | 183 | if (stat (path_resolv_conf, &st) < 0) { |
8ae2d595 | 184 | log_error ("Can't stat %s", path_resolv_conf); |
7e204261 | 185 | return (struct name_server *)0; |
732a90b2 | 186 | } |
a7de06ee | 187 | if (st.st_mtime > rcdate) { |
a7de06ee TL |
188 | rcdate = cur_time + 1; |
189 | ||
190 | read_resolv_conf (rcdate); | |
191 | } | |
192 | } | |
193 | ||
7e204261 | 194 | return name_servers; |
a7de06ee | 195 | } |