]> git.ipfire.org Git - ipfire-2.x.git/blame - 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
CommitLineData
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