]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
BUG11177: pppoe password not required anymore
[ipfire-2.x.git] / src / patches / dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
1 --- a/src/cache.c Wed Dec 16 19:24:12 2015
2 +++ b/src/cache.c Wed Dec 16 19:37:37 2015
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;
12 @@ -217,6 +217,9 @@
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
22 @@ -1138,7 +1141,7 @@
23
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;
31 @@ -1281,7 +1284,11 @@
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
43 --- a/src/dnsmasq.c Thu Jul 30 20:59:06 2015
44 +++ b/src/dnsmasq.c Wed Dec 16 19:38:32 2015
45 @@ -1017,6 +1017,11 @@
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 }
55 #endif
56
57 --- a/src/dnsmasq.h Wed Dec 16 19:24:12 2015
58 +++ b/src/dnsmasq.h Wed Dec 16 19:40:11 2015
59 @@ -1516,6 +1516,11 @@
60 void poll_listen(int fd, short event);
61 int do_poll(int timeout);
62
63 +/* isc.c */
64 +#ifdef HAVE_ISC_READER
65 +void load_dhcp(time_t now);
66 +#endif
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
75 @@ -0,0 +1,266 @@
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 +
97 +
98 +#define _GNU_SOURCE
99 +
100 +#include <assert.h>
101 +#include <stdio.h>
102 +
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 +
116 +static struct isc_dhcp_lease* dhcp_lease_new(const char* hostname) {
117 + struct isc_dhcp_lease* lease = whine_malloc(sizeof(*lease));
118 + if (!lease)
119 + return NULL;
120 +
121 + lease->name = strdup(hostname);
122 + if (daemon->domain_suffix) {
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 + }
130 + }
131 + lease->expires = 0;
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 +
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 +
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 +
183 + if (sscanf(token_date, "%d/%d/%d", &lease_time.tm_year, &lease_time.tm_mon, &lease_time.tm_mday) == 3) {
184 + lease_time.tm_year -= 1900;
185 + lease_time.tm_mon -= 1;
186 +
187 + if (sscanf(token_time, "%d:%d:%d", &lease_time.tm_hour, &lease_time.tm_min, &lease_time.tm_sec) == 3) {
188 + time = mktime(&lease_time) + get_utc_offset();
189 + }
190 + }
191 +
192 + return time;
193 +}
194 +
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 +
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 +
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);
297 +
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);
302 + assert(lease);
303 +
304 + lease->next = leases;
305 + leases = lease;
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;
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
342 --- a/src/option.c Wed Dec 16 19:24:12 2015
343 +++ b/src/option.c Wed Dec 16 19:42:48 2015
344 @@ -1771,7 +1771,7 @@
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;
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 \
359 - poll.o rrfilter.o edns0.o arp.o
360 + poll.o rrfilter.o edns0.o arp.o isc.o
361
362 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
363 dns-protocol.h radv-protocol.h ip6addr.h