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