]>
Commit | Line | Data |
---|---|---|
fbcc3cb7 MF |
1 | --- a/src/cache.c Wed Dec 16 19:24:12 2015 |
2 | +++ b/src/cache.c Wed Dec 16 19:37:37 2015 | |
45e65f1d MT |
3 | @@ -17,7 +17,7 @@ |
4 | #include "dnsmasq.h" | |
5 | ||
6 | static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL; | |
7 | -#ifdef HAVE_DHCP | |
8 | +#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER) | |
9 | static struct crec *dhcp_spare = NULL; | |
10 | #endif | |
11 | static struct crec *new_chain = NULL; | |
fbcc3cb7 | 12 | @@ -217,6 +217,9 @@ |
45e65f1d MT |
13 | crecp->flags &= ~F_BIGNAME; |
14 | } | |
15 | ||
16 | + if (crecp->flags & F_DHCP) | |
17 | + free(crecp->name.namep); | |
18 | + | |
19 | #ifdef HAVE_DNSSEC | |
20 | cache_blockdata_free(crecp); | |
21 | #endif | |
a6cd8b9b | 22 | @@ -1138,7 +1141,7 @@ |
32e321b2 | 23 | |
45e65f1d MT |
24 | } |
25 | ||
26 | -#ifdef HAVE_DHCP | |
27 | +#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER) | |
28 | struct in_addr a_record_from_hosts(char *name, time_t now) | |
29 | { | |
30 | struct crec *crecp = NULL; | |
a6cd8b9b | 31 | @@ -1281,7 +1284,11 @@ |
45e65f1d MT |
32 | else |
33 | crec->ttd = ttd; | |
34 | crec->addr.addr = *host_address; | |
35 | +#ifdef HAVE_ISC_READER | |
36 | + crec->name.namep = strdup(host_name); | |
37 | +#else | |
38 | crec->name.namep = host_name; | |
39 | +#endif | |
40 | crec->uid = next_uid(); | |
41 | cache_hash(crec); | |
42 | ||
fbcc3cb7 MF |
43 | --- a/src/dnsmasq.c Thu Jul 30 20:59:06 2015 |
44 | +++ b/src/dnsmasq.c Wed Dec 16 19:38:32 2015 | |
c3afb9c6 | 45 | @@ -1017,6 +1017,11 @@ |
45e65f1d MT |
46 | |
47 | poll_resolv(0, daemon->last_resolv != 0, now); | |
48 | daemon->last_resolv = now; | |
49 | + | |
50 | +#ifdef HAVE_ISC_READER | |
51 | + if (daemon->lease_file && !daemon->dhcp) | |
52 | + load_dhcp(now); | |
53 | +#endif | |
54 | } | |
32e321b2 MT |
55 | #endif |
56 | ||
fbcc3cb7 MF |
57 | --- a/src/dnsmasq.h Wed Dec 16 19:24:12 2015 |
58 | +++ b/src/dnsmasq.h Wed Dec 16 19:40:11 2015 | |
c3afb9c6 | 59 | @@ -1516,6 +1516,11 @@ |
d08045ea MT |
60 | void poll_listen(int fd, short event); |
61 | int do_poll(int timeout); | |
62 | ||
45e65f1d MT |
63 | +/* isc.c */ |
64 | +#ifdef HAVE_ISC_READER | |
65 | +void load_dhcp(time_t now); | |
66 | +#endif | |
fbcc3cb7 MF |
67 | + |
68 | /* rrfilter.c */ | |
69 | size_t rrfilter(struct dns_header *header, size_t plen, int mode); | |
70 | u16 *rrfilter_desc(int type); | |
71 | int expand_workspace(unsigned char ***wkspc, int *szp, int new); | |
72 | - | |
73 | --- /dev/null Wed Dec 16 19:48:08 2015 | |
74 | +++ b/src/isc.c Wed Dec 16 19:41:35 2015 | |
3f877ebd | 75 | @@ -0,0 +1,266 @@ |
45e65f1d MT |
76 | +/* dnsmasq is Copyright (c) 2014 John Volpe, Simon Kelley and |
77 | + Michael Tremer | |
78 | + | |
79 | + This program is free software; you can redistribute it and/or modify | |
80 | + it under the terms of the GNU General Public License as published by | |
81 | + the Free Software Foundation; version 2 dated June, 1991, or | |
82 | + (at your option) version 3 dated 29 June, 2007. | |
83 | + | |
84 | + This program is distributed in the hope that it will be useful, | |
85 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
86 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
87 | + GNU General Public License for more details. | |
88 | + | |
89 | + You should have received a copy of the GNU General Public License | |
90 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
91 | + | |
92 | + Code in this file is based on contributions by John Volpe and | |
93 | + Simon Kelley. Updated for recent versions of dnsmasq by | |
94 | + Michael Tremer. | |
95 | +*/ | |
96 | + | |
3f877ebd MF |
97 | + |
98 | +#define _GNU_SOURCE | |
99 | + | |
100 | +#include <assert.h> | |
101 | +#include <stdio.h> | |
102 | + | |
45e65f1d MT |
103 | +#include "dnsmasq.h" |
104 | + | |
105 | +#ifdef HAVE_ISC_READER | |
106 | +#define MAXTOK 50 | |
107 | + | |
108 | +struct isc_dhcp_lease { | |
109 | + char* name; | |
110 | + char* fqdn; | |
111 | + time_t expires; | |
112 | + struct in_addr addr; | |
113 | + struct isc_dhcp_lease* next; | |
114 | +}; | |
115 | + | |
3da4cc02 | 116 | +static struct isc_dhcp_lease* dhcp_lease_new(const char* hostname) { |
45e65f1d | 117 | + struct isc_dhcp_lease* lease = whine_malloc(sizeof(*lease)); |
3f877ebd MF |
118 | + if (!lease) |
119 | + return NULL; | |
45e65f1d | 120 | + |
3da4cc02 MT |
121 | + lease->name = strdup(hostname); |
122 | + if (daemon->domain_suffix) { | |
3f877ebd MF |
123 | + int r = asprintf(&lease->fqdn, "%s.%s", hostname, daemon->domain_suffix); |
124 | + | |
125 | + // Handle OOM | |
126 | + if (r < 0) { | |
127 | + free(lease); | |
128 | + return NULL; | |
129 | + } | |
3da4cc02 MT |
130 | + } |
131 | + lease->expires = 0; | |
45e65f1d MT |
132 | + lease->next = NULL; |
133 | + | |
134 | + return lease; | |
135 | +} | |
136 | + | |
137 | +static void dhcp_lease_free(struct isc_dhcp_lease* lease) { | |
138 | + if (!lease) | |
139 | + return; | |
140 | + | |
141 | + if (lease->name) | |
142 | + free(lease->name); | |
143 | + if (lease->fqdn) | |
144 | + free(lease->fqdn); | |
145 | + free(lease); | |
146 | +} | |
147 | + | |
148 | +static int next_token(char* token, int buffsize, FILE* fp) { | |
149 | + int c, count = 0; | |
150 | + char* cp = token; | |
151 | + | |
152 | + while ((c = getc(fp)) != EOF) { | |
153 | + if (c == '#') { | |
154 | + do { | |
155 | + c = getc(fp); | |
156 | + } while (c != '\n' && c != EOF); | |
157 | + } | |
158 | + | |
159 | + if (c == ' ' || c == '\t' || c == '\n' || c == ';') { | |
160 | + if (count) | |
161 | + break; | |
162 | + } else if ((c != '"') && (count < buffsize - 1)) { | |
163 | + *cp++ = c; | |
164 | + count++; | |
165 | + } | |
166 | + } | |
167 | + | |
168 | + *cp = 0; | |
169 | + return count ? 1 : 0; | |
170 | +} | |
171 | + | |
3da4cc02 MT |
172 | +static long get_utc_offset() { |
173 | + time_t t = time(NULL); | |
174 | + struct tm* time_struct = localtime(&t); | |
175 | + | |
176 | + return time_struct->tm_gmtoff; | |
177 | +} | |
178 | + | |
45e65f1d MT |
179 | +static time_t parse_lease_time(const char* token_date, const char* token_time) { |
180 | + time_t time = (time_t)(-1); | |
181 | + struct tm lease_time; | |
182 | + | |
45e65f1d | 183 | + if (sscanf(token_date, "%d/%d/%d", &lease_time.tm_year, &lease_time.tm_mon, &lease_time.tm_mday) == 3) { |
3da4cc02 MT |
184 | + lease_time.tm_year -= 1900; |
185 | + lease_time.tm_mon -= 1; | |
186 | + | |
45e65f1d | 187 | + if (sscanf(token_time, "%d:%d:%d", &lease_time.tm_hour, &lease_time.tm_min, &lease_time.tm_sec) == 3) { |
3da4cc02 | 188 | + time = mktime(&lease_time) + get_utc_offset(); |
45e65f1d MT |
189 | + } |
190 | + } | |
191 | + | |
192 | + return time; | |
193 | +} | |
194 | + | |
3da4cc02 MT |
195 | +static struct isc_dhcp_lease* find_lease(const char* hostname, struct isc_dhcp_lease* leases) { |
196 | + struct isc_dhcp_lease* lease = leases; | |
197 | + | |
198 | + while (lease) { | |
199 | + if (strcmp(hostname, lease->name) == 0) { | |
200 | + return lease; | |
201 | + } | |
202 | + lease = lease->next; | |
203 | + } | |
204 | + | |
205 | + return NULL; | |
206 | +} | |
207 | + | |
45e65f1d MT |
208 | +static off_t lease_file_size = (off_t)0; |
209 | +static ino_t lease_file_inode = (ino_t)0; | |
210 | + | |
211 | +void load_dhcp(time_t now) { | |
212 | + struct isc_dhcp_lease* leases = NULL; | |
213 | + | |
214 | + struct stat statbuf; | |
215 | + if (stat(daemon->lease_file, &statbuf) == -1) { | |
216 | + return; | |
217 | + } | |
218 | + | |
219 | + /* Do nothing if the lease file has not changed. */ | |
220 | + if ((statbuf.st_size <= lease_file_size) && (statbuf.st_ino == lease_file_inode)) | |
221 | + return; | |
222 | + | |
223 | + lease_file_size = statbuf.st_size; | |
224 | + lease_file_inode = statbuf.st_ino; | |
225 | + | |
226 | + FILE* fp = fopen(daemon->lease_file, "r"); | |
227 | + if (!fp) { | |
228 | + my_syslog(LOG_ERR, _("failed to load %s:%s"), daemon->lease_file, strerror(errno)); | |
229 | + return; | |
230 | + } | |
231 | + | |
232 | + my_syslog(LOG_INFO, _("reading %s"), daemon->lease_file); | |
233 | + | |
234 | + char* hostname = daemon->namebuff; | |
235 | + struct in_addr host_address; | |
236 | + time_t time_starts = -1; | |
237 | + time_t time_ends = -1; | |
238 | + int nomem; | |
239 | + | |
240 | + char token[MAXTOK]; | |
241 | + while ((next_token(token, MAXTOK, fp))) { | |
242 | + if (strcmp(token, "lease") == 0) { | |
243 | + hostname[0] = '\0'; | |
244 | + | |
245 | + if (next_token(token, MAXTOK, fp) && ((host_address.s_addr = inet_addr(token)) != (in_addr_t)-1)) { | |
246 | + if (next_token(token, MAXTOK, fp) && *token == '{') { | |
247 | + while (next_token(token, MAXTOK, fp) && *token != '}') { | |
248 | + if ((strcmp(token, "client-hostname") == 0) || (strcmp(token, "hostname") == 0)) { | |
249 | + if (next_token(hostname, MAXDNAME, fp)) { | |
250 | + if (!canonicalise(hostname, &nomem)) { | |
251 | + *hostname = 0; | |
252 | + my_syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file); | |
253 | + } | |
254 | + } | |
255 | + } else if ((strcmp(token, "starts") == 0) || (strcmp(token, "ends") == 0)) { | |
256 | + char token_date[MAXTOK]; | |
257 | + char token_time[MAXTOK]; | |
258 | + | |
259 | + int is_starts = strcmp(token, "starts") == 0; | |
260 | + | |
261 | + // Throw away the weekday and parse the date. | |
262 | + if (next_token(token, MAXTOK, fp) && next_token(token_date, MAXTOK, fp) && next_token(token_time, MAXTOK, fp)) { | |
263 | + time_t time = parse_lease_time(token_date, token_time); | |
264 | + | |
265 | + if (is_starts) | |
266 | + time_starts = time; | |
267 | + else | |
268 | + time_ends = time; | |
269 | + } | |
270 | + } | |
271 | + } | |
272 | + | |
273 | + if (!*hostname) | |
274 | + continue; | |
275 | + | |
276 | + if ((time_starts == -1) || (time_ends == -1)) | |
277 | + continue; | |
278 | + | |
279 | + if (difftime(now, time_ends) > 0) | |
280 | + continue; | |
281 | + | |
282 | + char* dot = strchr(hostname, '.'); | |
283 | + if (dot) { | |
284 | + if (!daemon->domain_suffix || hostname_isequal(dot + 1, daemon->domain_suffix)) { | |
285 | + my_syslog(LOG_WARNING, | |
286 | + _("Ignoring DHCP lease for %s because it has an illegal domain part"), | |
287 | + hostname); | |
288 | + continue; | |
289 | + } | |
290 | + *dot = 0; | |
291 | + } | |
292 | + | |
3da4cc02 MT |
293 | + // Search for an existing lease in the list |
294 | + // with the given host name and update the data | |
295 | + // if needed. | |
296 | + struct isc_dhcp_lease* lease = find_lease(hostname, leases); | |
45e65f1d | 297 | + |
3da4cc02 MT |
298 | + // If no lease already exists, we create a new one |
299 | + // and append it to the list. | |
300 | + if (!lease) { | |
301 | + lease = dhcp_lease_new(hostname); | |
3f877ebd | 302 | + assert(lease); |
45e65f1d | 303 | + |
3da4cc02 | 304 | + lease->next = leases; |
45e65f1d | 305 | + leases = lease; |
3da4cc02 MT |
306 | + } |
307 | + | |
308 | + // Only update more recent leases. | |
309 | + if (lease->expires > time_ends) | |
310 | + continue; | |
311 | + | |
312 | + lease->addr = host_address; | |
313 | + lease->expires = time_ends; | |
45e65f1d MT |
314 | + } |
315 | + } | |
316 | + } | |
317 | + } | |
318 | + | |
319 | + fclose(fp); | |
320 | + | |
321 | + // Drop all entries. | |
322 | + cache_unhash_dhcp(); | |
323 | + | |
324 | + while (leases) { | |
325 | + struct isc_dhcp_lease *lease = leases; | |
326 | + leases = lease->next; | |
327 | + | |
328 | + if (lease->fqdn) { | |
329 | + cache_add_dhcp_entry(lease->fqdn, AF_INET, (struct all_addr*)&lease->addr.s_addr, lease->expires); | |
330 | + } | |
331 | + | |
332 | + if (lease->name) { | |
333 | + cache_add_dhcp_entry(lease->name, AF_INET, (struct all_addr*)&lease->addr.s_addr, lease->expires); | |
334 | + } | |
335 | + | |
336 | + // Cleanup | |
337 | + dhcp_lease_free(lease); | |
338 | + } | |
339 | +} | |
340 | + | |
341 | +#endif | |
fbcc3cb7 MF |
342 | --- a/src/option.c Wed Dec 16 19:24:12 2015 |
343 | +++ b/src/option.c Wed Dec 16 19:42:48 2015 | |
c3afb9c6 | 344 | @@ -1771,7 +1771,7 @@ |
45e65f1d MT |
345 | ret_err(_("bad MX target")); |
346 | break; | |
347 | ||
348 | -#ifdef HAVE_DHCP | |
349 | +#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER) | |
350 | case 'l': /* --dhcp-leasefile */ | |
351 | daemon->lease_file = opt_string_alloc(arg); | |
352 | break; | |
fbcc3cb7 MF |
353 | --- a/Makefile Wed Dec 16 19:24:12 2015 |
354 | +++ b/Makefile Wed Dec 16 19:28:45 2015 | |
355 | @@ -74,7 +74,7 @@ | |
356 | helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \ | |
357 | dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \ | |
358 | domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \ | |
a6cd8b9b MF |
359 | - poll.o rrfilter.o edns0.o arp.o |
360 | + poll.o rrfilter.o edns0.o arp.o isc.o | |
fbcc3cb7 MF |
361 | |
362 | hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ | |
363 | dns-protocol.h radv-protocol.h ip6addr.h |