]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/dnsmasq-2.72rc2-Add-support-to-read-ISC-DHCP-lease-file.patch
slang: Update to 2.3.0
[people/pmueller/ipfire-2.x.git] / src / patches / dnsmasq-2.72rc2-Add-support-to-read-ISC-DHCP-lease-file.patch
1 diff --git a/Makefile b/Makefile
2 index 58a7975..616c6b7 100644
3 --- a/Makefile
4 +++ b/Makefile
5 @@ -69,7 +69,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
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 \
9 - domain.o dnssec.o blockdata.o tables.o loop.o
10 + domain.o dnssec.o blockdata.o tables.o loop.o isc.o
11
12 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
13 dns-protocol.h radv-protocol.h ip6addr.h
14 diff --git a/src/cache.c b/src/cache.c
15 index 2c3a498..77a7046 100644
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
37 @@ -1110,7 +1113,7 @@ void cache_reload(void)
38 total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
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;
46 @@ -1188,7 +1191,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
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)))
55 @@ -1253,7 +1256,11 @@ void cache_add_dhcp_entry(char *host_name, int prot,
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
67 diff --git a/src/dnsmasq.c b/src/dnsmasq.c
68 index f4a89fc..a448ec4 100644
69 --- a/src/dnsmasq.c
70 +++ b/src/dnsmasq.c
71 @@ -940,6 +940,11 @@ int main (int argc, char **argv)
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 }
81
82 if (FD_ISSET(piperead, &rset))
83 diff --git a/src/dnsmasq.h b/src/dnsmasq.h
84 index e74b15a..4a35168 100644
85 --- a/src/dnsmasq.h
86 +++ b/src/dnsmasq.h
87 @@ -1463,9 +1463,13 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
88 void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
89 #endif
90
91 +/* isc.c */
92 +#ifdef HAVE_ISC_READER
93 +void load_dhcp(time_t now);
94 +#endif
95 +
96 /* loop.c */
97 #ifdef HAVE_LOOP
98 void loop_send_probes();
99 int detect_loop(char *query, int type);
100 #endif
101 -
102 diff --git a/src/isc.c b/src/isc.c
103 new file mode 100644
104 index 0000000..5106442
105 --- /dev/null
106 +++ b/src/isc.c
107 @@ -0,0 +1,251 @@
108 +/* dnsmasq is Copyright (c) 2014 John Volpe, Simon Kelley and
109 + Michael Tremer
110 +
111 + This program is free software; you can redistribute it and/or modify
112 + it under the terms of the GNU General Public License as published by
113 + the Free Software Foundation; version 2 dated June, 1991, or
114 + (at your option) version 3 dated 29 June, 2007.
115 +
116 + This program is distributed in the hope that it will be useful,
117 + but WITHOUT ANY WARRANTY; without even the implied warranty of
118 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
119 + GNU General Public License for more details.
120 +
121 + You should have received a copy of the GNU General Public License
122 + along with this program. If not, see <http://www.gnu.org/licenses/>.
123 +
124 + Code in this file is based on contributions by John Volpe and
125 + Simon Kelley. Updated for recent versions of dnsmasq by
126 + Michael Tremer.
127 +*/
128 +
129 +#include "dnsmasq.h"
130 +
131 +#ifdef HAVE_ISC_READER
132 +#define MAXTOK 50
133 +
134 +struct isc_dhcp_lease {
135 + char* name;
136 + char* fqdn;
137 + time_t expires;
138 + struct in_addr addr;
139 + struct isc_dhcp_lease* next;
140 +};
141 +
142 +static struct isc_dhcp_lease* dhcp_lease_new(const char* hostname) {
143 + struct isc_dhcp_lease* lease = whine_malloc(sizeof(*lease));
144 +
145 + lease->name = strdup(hostname);
146 + if (daemon->domain_suffix) {
147 + asprintf(&lease->fqdn, "%s.%s", hostname, daemon->domain_suffix);
148 + }
149 + lease->expires = 0;
150 + lease->next = NULL;
151 +
152 + return lease;
153 +}
154 +
155 +static void dhcp_lease_free(struct isc_dhcp_lease* lease) {
156 + if (!lease)
157 + return;
158 +
159 + if (lease->name)
160 + free(lease->name);
161 + if (lease->fqdn)
162 + free(lease->fqdn);
163 + free(lease);
164 +}
165 +
166 +static int next_token(char* token, int buffsize, FILE* fp) {
167 + int c, count = 0;
168 + char* cp = token;
169 +
170 + while ((c = getc(fp)) != EOF) {
171 + if (c == '#') {
172 + do {
173 + c = getc(fp);
174 + } while (c != '\n' && c != EOF);
175 + }
176 +
177 + if (c == ' ' || c == '\t' || c == '\n' || c == ';') {
178 + if (count)
179 + break;
180 + } else if ((c != '"') && (count < buffsize - 1)) {
181 + *cp++ = c;
182 + count++;
183 + }
184 + }
185 +
186 + *cp = 0;
187 + return count ? 1 : 0;
188 +}
189 +
190 +static long get_utc_offset() {
191 + time_t t = time(NULL);
192 + struct tm* time_struct = localtime(&t);
193 +
194 + return time_struct->tm_gmtoff;
195 +}
196 +
197 +static time_t parse_lease_time(const char* token_date, const char* token_time) {
198 + time_t time = (time_t)(-1);
199 + struct tm lease_time;
200 +
201 + if (sscanf(token_date, "%d/%d/%d", &lease_time.tm_year, &lease_time.tm_mon, &lease_time.tm_mday) == 3) {
202 + lease_time.tm_year -= 1900;
203 + lease_time.tm_mon -= 1;
204 +
205 + if (sscanf(token_time, "%d:%d:%d", &lease_time.tm_hour, &lease_time.tm_min, &lease_time.tm_sec) == 3) {
206 + time = mktime(&lease_time) + get_utc_offset();
207 + }
208 + }
209 +
210 + return time;
211 +}
212 +
213 +static struct isc_dhcp_lease* find_lease(const char* hostname, struct isc_dhcp_lease* leases) {
214 + struct isc_dhcp_lease* lease = leases;
215 +
216 + while (lease) {
217 + if (strcmp(hostname, lease->name) == 0) {
218 + return lease;
219 + }
220 + lease = lease->next;
221 + }
222 +
223 + return NULL;
224 +}
225 +
226 +static off_t lease_file_size = (off_t)0;
227 +static ino_t lease_file_inode = (ino_t)0;
228 +
229 +void load_dhcp(time_t now) {
230 + struct isc_dhcp_lease* leases = NULL;
231 +
232 + struct stat statbuf;
233 + if (stat(daemon->lease_file, &statbuf) == -1) {
234 + return;
235 + }
236 +
237 + /* Do nothing if the lease file has not changed. */
238 + if ((statbuf.st_size <= lease_file_size) && (statbuf.st_ino == lease_file_inode))
239 + return;
240 +
241 + lease_file_size = statbuf.st_size;
242 + lease_file_inode = statbuf.st_ino;
243 +
244 + FILE* fp = fopen(daemon->lease_file, "r");
245 + if (!fp) {
246 + my_syslog(LOG_ERR, _("failed to load %s:%s"), daemon->lease_file, strerror(errno));
247 + return;
248 + }
249 +
250 + my_syslog(LOG_INFO, _("reading %s"), daemon->lease_file);
251 +
252 + char* hostname = daemon->namebuff;
253 + struct in_addr host_address;
254 + time_t time_starts = -1;
255 + time_t time_ends = -1;
256 + int nomem;
257 +
258 + char token[MAXTOK];
259 + while ((next_token(token, MAXTOK, fp))) {
260 + if (strcmp(token, "lease") == 0) {
261 + hostname[0] = '\0';
262 +
263 + if (next_token(token, MAXTOK, fp) && ((host_address.s_addr = inet_addr(token)) != (in_addr_t)-1)) {
264 + if (next_token(token, MAXTOK, fp) && *token == '{') {
265 + while (next_token(token, MAXTOK, fp) && *token != '}') {
266 + if ((strcmp(token, "client-hostname") == 0) || (strcmp(token, "hostname") == 0)) {
267 + if (next_token(hostname, MAXDNAME, fp)) {
268 + if (!canonicalise(hostname, &nomem)) {
269 + *hostname = 0;
270 + my_syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file);
271 + }
272 + }
273 + } else if ((strcmp(token, "starts") == 0) || (strcmp(token, "ends") == 0)) {
274 + char token_date[MAXTOK];
275 + char token_time[MAXTOK];
276 +
277 + int is_starts = strcmp(token, "starts") == 0;
278 +
279 + // Throw away the weekday and parse the date.
280 + if (next_token(token, MAXTOK, fp) && next_token(token_date, MAXTOK, fp) && next_token(token_time, MAXTOK, fp)) {
281 + time_t time = parse_lease_time(token_date, token_time);
282 +
283 + if (is_starts)
284 + time_starts = time;
285 + else
286 + time_ends = time;
287 + }
288 + }
289 + }
290 +
291 + if (!*hostname)
292 + continue;
293 +
294 + if ((time_starts == -1) || (time_ends == -1))
295 + continue;
296 +
297 + if (difftime(now, time_ends) > 0)
298 + continue;
299 +
300 + char* dot = strchr(hostname, '.');
301 + if (dot) {
302 + if (!daemon->domain_suffix || hostname_isequal(dot + 1, daemon->domain_suffix)) {
303 + my_syslog(LOG_WARNING,
304 + _("Ignoring DHCP lease for %s because it has an illegal domain part"),
305 + hostname);
306 + continue;
307 + }
308 + *dot = 0;
309 + }
310 +
311 + // Search for an existing lease in the list
312 + // with the given host name and update the data
313 + // if needed.
314 + struct isc_dhcp_lease* lease = find_lease(hostname, leases);
315 +
316 + // If no lease already exists, we create a new one
317 + // and append it to the list.
318 + if (!lease) {
319 + lease = dhcp_lease_new(hostname);
320 +
321 + lease->next = leases;
322 + leases = lease;
323 + }
324 +
325 + // Only update more recent leases.
326 + if (lease->expires > time_ends)
327 + continue;
328 +
329 + lease->addr = host_address;
330 + lease->expires = time_ends;
331 + }
332 + }
333 + }
334 + }
335 +
336 + fclose(fp);
337 +
338 + // Drop all entries.
339 + cache_unhash_dhcp();
340 +
341 + while (leases) {
342 + struct isc_dhcp_lease *lease = leases;
343 + leases = lease->next;
344 +
345 + if (lease->fqdn) {
346 + cache_add_dhcp_entry(lease->fqdn, AF_INET, (struct all_addr*)&lease->addr.s_addr, lease->expires);
347 + }
348 +
349 + if (lease->name) {
350 + cache_add_dhcp_entry(lease->name, AF_INET, (struct all_addr*)&lease->addr.s_addr, lease->expires);
351 + }
352 +
353 + // Cleanup
354 + dhcp_lease_free(lease);
355 + }
356 +}
357 +
358 +#endif
359 diff --git a/src/option.c b/src/option.c
360 index 45d8875..29c9ee5 100644
361 --- a/src/option.c
362 +++ b/src/option.c
363 @@ -1669,7 +1669,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
364 ret_err(_("bad MX target"));
365 break;
366
367 -#ifdef HAVE_DHCP
368 +#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER)
369 case 'l': /* --dhcp-leasefile */
370 daemon->lease_file = opt_string_alloc(arg);
371 break;