]>
Commit | Line | Data |
---|---|---|
a7de06ee TL |
1 | /* resolv.c |
2 | ||
3 | Parser for /etc/resolv.conf file. */ | |
4 | ||
5 | /* | |
49a7fb58 | 6 | * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC") |
98311e4b | 7 | * Copyright (c) 1996-2003 by Internet Software Consortium |
a7de06ee | 8 | * |
7512d88b TM |
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/. | |
a7de06ee | 12 | * |
98311e4b DH |
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. | |
a7de06ee | 20 | * |
98311e4b | 21 | * Internet Systems Consortium, Inc. |
429a56d7 TM |
22 | * PO Box 360 |
23 | * Newmarket, NH 03857 USA | |
98311e4b | 24 | * <info@isc.org> |
2c85ac9b | 25 | * https://www.isc.org/ |
49733f31 | 26 | * |
a7de06ee TL |
27 | */ |
28 | ||
a7de06ee | 29 | #include "dhcpd.h" |
a7de06ee TL |
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 | { | |
3b4f8a4a TL |
38 | int file; |
39 | struct parse *cfile; | |
b1b7b521 | 40 | const char *val; |
a7de06ee | 41 | int token; |
a7de06ee TL |
42 | struct name_server *sp, *sl, *ns; |
43 | struct domain_search_list *dp, *dl, *nd; | |
c40e954c | 44 | isc_result_t status; |
a7de06ee | 45 | |
3e4618c4 | 46 | if ((file = open (path_resolv_conf, O_RDONLY)) < 0) { |
8ae2d595 | 47 | log_error ("Can't open %s: %m", path_resolv_conf); |
732a90b2 TL |
48 | return; |
49 | } | |
50 | ||
c40e954c EH |
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; | |
3b4f8a4a | 55 | |
a7de06ee | 56 | do { |
b3519f23 | 57 | token = next_token (&val, (unsigned *)0, cfile); |
0b69dcc8 | 58 | if (token == END_OF_FILE) |
a7de06ee TL |
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) { | |
4bd8800e | 78 | nd = new_domain_search_list (MDL); |
a7de06ee | 79 | if (!nd) |
3b4f8a4a TL |
80 | log_fatal ("No memory for %s", |
81 | dn); | |
a7de06ee TL |
82 | nd -> next = |
83 | (struct domain_search_list *)0; | |
84 | *dp = nd; | |
85 | nd -> domain = dn; | |
a7de06ee TL |
86 | } |
87 | nd -> rcdate = parse_time; | |
b3519f23 TL |
88 | token = peek_token (&val, |
89 | (unsigned *)0, cfile); | |
2c50133e | 90 | } while (token != EOL); |
a7de06ee | 91 | if (token != EOL) { |
3b4f8a4a TL |
92 | parse_warn (cfile, |
93 | "junk after domain declaration"); | |
a7de06ee TL |
94 | skip_to_semi (cfile); |
95 | } | |
dc9d7b08 | 96 | skip_token(&val, (unsigned *)0, cfile); |
a7de06ee TL |
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) { | |
4bd8800e | 111 | ns = new_name_server (MDL); |
a7de06ee | 112 | if (!ns) |
3b4f8a4a | 113 | log_fatal ("No memory for nameserver %s", |
a7de06ee TL |
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); | |
357708da TL |
129 | } else |
130 | skip_to_semi (cfile); /* Ignore what we don't grok. */ | |
a7de06ee | 131 | } while (1); |
dc9d7b08 | 132 | skip_token(&val, (unsigned *)0, cfile); |
a7de06ee TL |
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; | |
7e204261 TL |
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 | |
20ae1aff | 146 | could be a noticeable memory leak. */ |
a7de06ee TL |
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; | |
4bd8800e | 160 | free_domain_search_list (dp, MDL); |
a7de06ee TL |
161 | } else |
162 | dl = dp; | |
163 | } | |
3b4f8a4a | 164 | end_parse (&cfile); |
a7de06ee TL |
165 | } |
166 | ||
167 | /* Pick a name server from the /etc/resolv.conf file. */ | |
168 | ||
7e204261 | 169 | struct name_server *first_name_server () |
a7de06ee | 170 | { |
a7de06ee TL |
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) { | |
732a90b2 | 176 | if (stat (path_resolv_conf, &st) < 0) { |
8ae2d595 | 177 | log_error ("Can't stat %s", path_resolv_conf); |
7e204261 | 178 | return (struct name_server *)0; |
732a90b2 | 179 | } |
a7de06ee | 180 | if (st.st_mtime > rcdate) { |
a7de06ee | 181 | rcdate = cur_time + 1; |
f6b8f48d | 182 | |
a7de06ee TL |
183 | read_resolv_conf (rcdate); |
184 | } | |
185 | } | |
186 | ||
7e204261 | 187 | return name_servers; |
a7de06ee | 188 | } |