dnsmasq: Update to 2.75

Message ID 1438458997-6193-1-git-send-email-fischerm42@t-online.de
State Not Applicable
Delegated to: Michael Tremer
Headers

Message

Matthias Fischer Aug. 2, 2015, 5:56 a.m. UTC
  From: Matthias Fischer <fischerm42@t-online.de>

Signed-off-by: Matthias Fischer <fischerm42@t-online.de>
---
 lfs/dnsmasq                                        |   6 +-
 ...5-Add-support-to-read-ISC-DHCP-lease-file.patch | 349 ++++++++++++++++++++
 ...q-Add-support-to-read-ISC-DHCP-lease-file.patch | 365 ---------------------
 3 files changed, 352 insertions(+), 368 deletions(-)
 create mode 100644 src/patches/dnsmasq-2.75-Add-support-to-read-ISC-DHCP-lease-file.patch
 delete mode 100644 src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
  

Comments

Michael Tremer Aug. 3, 2015, 6:39 a.m. UTC | #1
Hi,

I don't know if you saw this, but I have pushed the same changes just
minutes before you sent this patch yesterday :)

Should we agree that you are the maintainer of dnsmasq in IPFire 2 from
now on so that these clashes do not happen? Does not make sense to do
the work twice.

On the plus side: The changes are exactly the same. You only renamed
the patch file and I didn't. So that is good :)

Best,
-Michael

On Sat, 2015-08-01 at 21:56 +0200, fischerm42@t-online.de wrote:
> From: Matthias Fischer <fischerm42@t-online.de>
> 
> Signed-off-by: Matthias Fischer <fischerm42@t-online.de>
> ---
>  lfs/dnsmasq                                        |   6 +-
>  ...5-Add-support-to-read-ISC-DHCP-lease-file.patch | 349 
> ++++++++++++++++++++
>  ...q-Add-support-to-read-ISC-DHCP-lease-file.patch | 365 -----------
> ----------
>  3 files changed, 352 insertions(+), 368 deletions(-)
>  create mode 100644 src/patches/dnsmasq-2.75-Add-support-to-read-ISC
> -DHCP-lease-file.patch
>  delete mode 100644 src/patches/dnsmasq-Add-support-to-read-ISC-DHCP
> -lease-file.patch
> 
> diff --git a/lfs/dnsmasq b/lfs/dnsmasq
> index e4410cc..24cb92a 100644
> --- a/lfs/dnsmasq
> +++ b/lfs/dnsmasq
> @@ -24,7 +24,7 @@
>  
>  include Config
>  
> -VER        = 2.73
> +VER        = 2.75
>  
>  THISAPP    = dnsmasq-$(VER)
>  DL_FILE    = $(THISAPP).tar.xz
> @@ -43,7 +43,7 @@ objects = $(DL_FILE)
>  
>  $(DL_FILE) = $(DL_FROM)/$(DL_FILE)
>  
> -$(DL_FILE)_MD5 = b8bfe96d22945c8cf4466826ba9b21bd
> +$(DL_FILE)_MD5 = 887236f1ddde6eb57cdb9d01916c9f72
>  
>  install : $(TARGET)
>  
> @@ -73,7 +73,7 @@ $(subst %,%_MD5,$(objects)) :
>  $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
>  	@$(PREBUILD)
>  	@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf 
> $(DIR_DL)/$(DL_FILE)
> -	cd $(DIR_APP) && patch -Np1 -i 
> $(DIR_SRC)/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease
> -file.patch
> +	cd $(DIR_APP) && patch -Np0 -i 
> $(DIR_SRC)/src/patches/dnsmasq-2.75-Add-support-to-read-ISC-DHCP
> -lease-file.patch
>  	cd $(DIR_APP) && sed -i src/config.h \
>  		-e 's|/\* #define HAVE_IDN \*/|#define HAVE_IDN|g' \
>  		-e 's|/\* #define HAVE_DNSSEC \*/|#define 
> HAVE_DNSSEC|g' \
> diff --git a/src/patches/dnsmasq-2.75-Add-support-to-read-ISC-DHCP
> -lease-file.patch b/src/patches/dnsmasq-2.75-Add-support-to-read-ISC
> -DHCP-lease-file.patch
> new file mode 100644
> index 0000000..4810e5d
> --- /dev/null
> +++ b/src/patches/dnsmasq-2.75-Add-support-to-read-ISC-DHCP-lease
> -file.patch
> @@ -0,0 +1,349 @@
> +--- Makefile	Thu Jul 30 21:59:07 2015
> ++++ Makefile	Sat Aug 01 17:44:39 2015
> +@@ -73,7 +73,7 @@
> +        dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
> +        helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
> +        dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
> +-       domain.o dnssec.o blockdata.o tables.o loop.o inotify.o 
> poll.o
> ++       domain.o dnssec.o blockdata.o tables.o loop.o inotify.o 
> poll.o isc.o
> + 
> + hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
> +        dns-protocol.h radv-protocol.h ip6addr.h
> +--- src/cache.c	Thu Jul 30 21:59:07 2015
> ++++ src/cache.c	Sat Aug 01 18:20:04 2015
> +@@ -17,7 +17,7 @@
> + #include "dnsmasq.h"
> + 
> + static struct crec *cache_head = NULL, *cache_tail = NULL, 
> **hash_table = NULL;
> +-#ifdef HAVE_DHCP
> ++#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER)
> + static struct crec *dhcp_spare = NULL;
> + #endif
> + static struct crec *new_chain = NULL;
> +@@ -222,6 +222,9 @@
> +       crecp->flags &= ~F_BIGNAME;
> +     }
> + 
> ++  if (crecp->flags & F_DHCP)
> ++    free(crecp->name.namep);
> ++
> + #ifdef HAVE_DNSSEC
> +   cache_blockdata_free(crecp);
> + #endif
> +@@ -1151,7 +1154,7 @@
> +   
> + } 
> + 
> +-#ifdef HAVE_DHCP
> ++#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER)
> + struct in_addr a_record_from_hosts(char *name, time_t now)
> + {
> +   struct crec *crecp = NULL;
> +@@ -1294,7 +1297,11 @@
> +       else
> + 	crec->ttd = ttd;
> +       crec->addr.addr = *host_address;
> ++#ifdef HAVE_ISC_READER
> ++      crec->name.namep = strdup(host_name);
> ++#else
> +       crec->name.namep = host_name;
> ++#endif
> +       crec->uid = next_uid();
> +       cache_hash(crec);
> + 
> +--- src/dnsmasq.c	Thu Jul 30 21:59:07 2015
> ++++ src/dnsmasq.c	Sat Aug 01 17:51:19 2015
> +@@ -980,8 +980,13 @@
> + 	  /* poll_resolv doesn't need to reload first time through, 
> since 
> + 	     that's queued anyway. */
> + 
> +-	  poll_resolv(0, daemon->last_resolv != 0, now); 	  
> ++	  poll_resolv(0, daemon->last_resolv != 0, now);
> + 	  daemon->last_resolv = now;
> ++
> ++#ifdef HAVE_ISC_READER
> ++	  if (daemon->lease_file && !daemon->dhcp)
> ++	    load_dhcp(now);
> ++#endif
> + 	}
> + #endif
> + 
> +--- src/dnsmasq.h	Thu Jul 30 21:59:07 2015
> ++++ src/dnsmasq.h	Sat Aug 01 17:53:12 2015
> +@@ -1513,6 +1513,11 @@
> + void set_dynamic_inotify(int flag, int total_size, struct crec 
> **rhash, int revhashsz);
> + #endif
> + 
> ++/* isc.c */
> ++#ifdef HAVE_ISC_READER
> ++void load_dhcp(time_t now);
> ++#endif
> ++
> + /* poll.c */
> + void poll_reset(void);
> + int poll_check(int fd, short event);
> +--- src/isc.c	Sat Aug 01 18:07:12 2015
> ++++ src/isc.c	Sat Aug 01 17:54:27 2015
> +@@ -0,0 +1,251 @@
> ++/* dnsmasq is Copyright (c) 2014 John Volpe, Simon Kelley and
> ++     Michael Tremer
> ++
> ++  This program is free software; you can redistribute it and/or 
> modify
> ++  it under the terms of the GNU General Public License as published 
> by
> ++  the Free Software Foundation; version 2 dated June, 1991, or
> ++  (at your option) version 3 dated 29 June, 2007.
> ++
> ++  This program is distributed in the hope that it will be useful,
> ++  but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> ++  GNU General Public License for more details.
> ++  
> ++  You should have received a copy of the GNU General Public License
> ++  along with this program.  If not, see <
> http://www.gnu.org/licenses/>.
> ++
> ++  Code in this file is based on contributions by John Volpe and
> ++  Simon Kelley. Updated for recent versions of dnsmasq by
> ++  Michael Tremer.
> ++*/
> ++
> ++#include "dnsmasq.h"
> ++
> ++#ifdef HAVE_ISC_READER
> ++#define MAXTOK 50
> ++
> ++struct isc_dhcp_lease {
> ++	char* name;
> ++	char* fqdn;
> ++	time_t expires;
> ++	struct in_addr addr;
> ++	struct isc_dhcp_lease* next;
> ++};
> ++
> ++static struct isc_dhcp_lease* dhcp_lease_new(const char* hostname) 
> {
> ++	struct isc_dhcp_lease* lease = 
> whine_malloc(sizeof(*lease));
> ++
> ++	lease->name = strdup(hostname);
> ++	if (daemon->domain_suffix) {
> ++		asprintf(&lease->fqdn, "%s.%s", hostname, daemon
> ->domain_suffix);
> ++	}
> ++	lease->expires = 0;
> ++	lease->next = NULL;
> ++
> ++	return lease;
> ++}
> ++
> ++static void dhcp_lease_free(struct isc_dhcp_lease* lease) {
> ++	if (!lease)
> ++		return;
> ++
> ++	if (lease->name)
> ++		free(lease->name);
> ++	if (lease->fqdn)
> ++		free(lease->fqdn);
> ++	free(lease);
> ++}
> ++
> ++static int next_token(char* token, int buffsize, FILE* fp) {
> ++	int c, count = 0;
> ++	char* cp = token;
> ++
> ++	while ((c = getc(fp)) != EOF) {
> ++		if (c == '#') {
> ++			do {
> ++				c = getc(fp);
> ++			} while (c != '\n' && c != EOF);
> ++		}
> ++
> ++		if (c == ' ' || c == '\t' || c == '\n' || c == ';') 
> {
> ++			if (count)
> ++				break;
> ++		} else if ((c != '"') && (count < buffsize - 1)) {
> ++			*cp++ = c;
> ++			count++;
> ++		}
> ++	}
> ++
> ++	*cp = 0;
> ++	return count ? 1 : 0;
> ++}
> ++
> ++static long get_utc_offset() {
> ++	time_t t = time(NULL);
> ++	struct tm* time_struct = localtime(&t);
> ++
> ++	return time_struct->tm_gmtoff;
> ++}
> ++
> ++static time_t parse_lease_time(const char* token_date, const char* 
> token_time) {
> ++	time_t time = (time_t)(-1);
> ++	struct tm lease_time;
> ++
> ++	if (sscanf(token_date, "%d/%d/%d", &lease_time.tm_year, 
> &lease_time.tm_mon, &lease_time.tm_mday) == 3) {
> ++		lease_time.tm_year -= 1900;
> ++		lease_time.tm_mon -= 1;
> ++
> ++		if (sscanf(token_time, "%d:%d:%d", 
> &lease_time.tm_hour, &lease_time.tm_min, &lease_time.tm_sec) == 3) {
> ++			time = mktime(&lease_time) + 
> get_utc_offset();
> ++		}
> ++	}
> ++
> ++	return time;
> ++}
> ++
> ++static struct isc_dhcp_lease* find_lease(const char* hostname, 
> struct isc_dhcp_lease* leases) {
> ++	struct isc_dhcp_lease* lease = leases;
> ++
> ++	while (lease) {
> ++		if (strcmp(hostname, lease->name) == 0) {
> ++			return lease;
> ++		}
> ++		lease = lease->next;
> ++	}
> ++
> ++	return NULL;
> ++}
> ++
> ++static off_t lease_file_size = (off_t)0;
> ++static ino_t lease_file_inode = (ino_t)0;
> ++
> ++void load_dhcp(time_t now) {
> ++	struct isc_dhcp_lease* leases = NULL;
> ++
> ++	struct stat statbuf;
> ++	if (stat(daemon->lease_file, &statbuf) == -1) {
> ++		return;
> ++	}
> ++
> ++	/* Do nothing if the lease file has not changed. */
> ++	if ((statbuf.st_size <= lease_file_size) && (statbuf.st_ino 
> == lease_file_inode))
> ++		return;
> ++
> ++	lease_file_size = statbuf.st_size;
> ++	lease_file_inode = statbuf.st_ino;
> ++
> ++	FILE* fp = fopen(daemon->lease_file, "r");
> ++	if (!fp) {
> ++		my_syslog(LOG_ERR, _("failed to load %s:%s"), 
> daemon->lease_file, strerror(errno));
> ++		return;
> ++	}
> ++
> ++	my_syslog(LOG_INFO, _("reading %s"), daemon->lease_file);
> ++
> ++	char* hostname = daemon->namebuff;
> ++	struct in_addr host_address;
> ++	time_t time_starts = -1;
> ++	time_t time_ends = -1;
> ++	int nomem;
> ++
> ++	char token[MAXTOK];
> ++	while ((next_token(token, MAXTOK, fp))) {
> ++		if (strcmp(token, "lease") == 0) {
> ++			hostname[0] = '\0';
> ++
> ++			if (next_token(token, MAXTOK, fp) && 
> ((host_address.s_addr = inet_addr(token)) != (in_addr_t)-1)) {
> ++				if (next_token(token, MAXTOK, fp) 
> && *token == '{') {
> ++					while (next_token(token, 
> MAXTOK, fp) && *token != '}') {
> ++						if ((strcmp(token, 
> "client-hostname") == 0) || (strcmp(token, "hostname") == 0)) {
> ++							if 
> (next_token(hostname, MAXDNAME, fp)) {
> ++								if 
> (!canonicalise(hostname, &nomem)) {
> ++									
> *hostname = 0;
> ++									
> my_syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file);
> ++								}
> ++							}
> ++						} else if 
> ((strcmp(token, "starts") == 0) || (strcmp(token, "ends") == 0)) {
> ++							char 
> token_date[MAXTOK];
> ++							char 
> token_time[MAXTOK];
> ++
> ++							int 
> is_starts = strcmp(token, "starts") == 0;
> ++
> ++							// Throw 
> away the weekday and parse the date.
> ++							if 
> (next_token(token, MAXTOK, fp) && next_token(token_date, MAXTOK, fp) 
> && next_token(token_time, MAXTOK, fp)) {
> ++								tim
> e_t time = parse_lease_time(token_date, token_time);
> ++
> ++								if 
> (is_starts)
> ++									
> time_starts = time;
> ++								els
> e
> ++									
> time_ends = time;
> ++							}
> ++						}
> ++					}
> ++
> ++					if (!*hostname)
> ++						continue;
> ++
> ++					if ((time_starts == -1) || 
> (time_ends == -1))
> ++						continue;
> ++
> ++					if (difftime(now, 
> time_ends) > 0)
> ++						continue;
> ++
> ++					char* dot = 
> strchr(hostname, '.');
> ++					if (dot) {
> ++						if (!daemon
> ->domain_suffix || hostname_isequal(dot + 1, daemon->domain_suffix)) 
> {
> ++							my_syslog(L
> OG_WARNING,
> ++								_("
> Ignoring DHCP lease for %s because it has an illegal domain part"),
> ++								hos
> tname);
> ++							continue;
> ++						}
> ++						*dot = 0;
> ++					}
> ++
> ++					// Search for an existing 
> lease in the list
> ++					// with the given host name 
> and update the data
> ++					// if needed.
> ++					struct isc_dhcp_lease* 
> lease = find_lease(hostname, leases);
> ++
> ++					// If no lease already 
> exists, we create a new one
> ++					// and append it to the 
> list.
> ++					if (!lease) {
> ++						lease = 
> dhcp_lease_new(hostname);
> ++
> ++						lease->next = 
> leases;
> ++						leases = lease;
> ++					}
> ++
> ++					// Only update more recent 
> leases.
> ++					if (lease->expires > 
> time_ends)
> ++						continue;
> ++
> ++					lease->addr = host_address;
> ++					lease->expires = time_ends;
> ++				}
> ++			}
> ++		}
> ++	}
> ++
> ++	fclose(fp);
> ++
> ++	// Drop all entries.
> ++	cache_unhash_dhcp();
> ++
> ++	while (leases) {
> ++		struct isc_dhcp_lease *lease = leases;
> ++		leases = lease->next;
> ++
> ++		if (lease->fqdn) {
> ++			cache_add_dhcp_entry(lease->fqdn, AF_INET, 
> (struct all_addr*)&lease->addr.s_addr, lease->expires);
> ++		}
> ++
> ++		if (lease->name) {
> ++			cache_add_dhcp_entry(lease->name, AF_INET, 
> (struct all_addr*)&lease->addr.s_addr, lease->expires);
> ++		}
> ++
> ++		// Cleanup
> ++		dhcp_lease_free(lease);
> ++	}
> ++}
> ++
> ++#endif
> +--- src/option.c	Thu Jul 30 21:59:07 2015
> ++++ src/option.c	Sat Aug 01 17:55:30 2015
> +@@ -1699,7 +1699,7 @@
> + 	ret_err(_("bad MX target"));
> +       break;
> + 
> +-#ifdef HAVE_DHCP      
> ++#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER)
> +     case 'l':  /* --dhcp-leasefile */
> +       daemon->lease_file = opt_string_alloc(arg);
> +       break;
> diff --git a/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease
> -file.patch b/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease
> -file.patch
> deleted file mode 100644
> index 1a89b36..0000000
> --- a/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease
> -file.patch
> +++ /dev/null
> @@ -1,365 +0,0 @@
> -diff --git a/Makefile b/Makefile
> -index 2910320b6452..0a76ce3c5154 100644
> ---- a/Makefile
> -+++ b/Makefile
> -@@ -73,7 +73,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o 
> network.o \
> -        dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
> -        helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
> -        dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
> --       domain.o dnssec.o blockdata.o tables.o loop.o inotify.o
> -+       domain.o dnssec.o blockdata.o tables.o loop.o inotify.o 
> isc.o
> - 
> - hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
> -        dns-protocol.h radv-protocol.h ip6addr.h
> -diff --git a/src/cache.c b/src/cache.c
> -index 117ae279fd4e..6ee7ee362e6c 100644
> ---- a/src/cache.c
> -+++ b/src/cache.c
> -@@ -17,7 +17,7 @@
> - #include "dnsmasq.h"
> - 
> - static struct crec *cache_head = NULL, *cache_tail = NULL, 
> **hash_table = NULL;
> --#ifdef HAVE_DHCP
> -+#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER)
> - static struct crec *dhcp_spare = NULL;
> - #endif
> - static struct crec *new_chain = NULL;
> -@@ -222,6 +222,9 @@ static void cache_free(struct crec *crecp)
> -       crecp->flags &= ~F_BIGNAME;
> -     }
> - 
> -+  if (crecp->flags & F_DHCP)
> -+    free(crecp->name.namep);
> -+
> - #ifdef HAVE_DNSSEC
> -   cache_blockdata_free(crecp);
> - #endif
> -@@ -1151,7 +1154,7 @@ void cache_reload(void)
> -   
> - } 
> - 
> --#ifdef HAVE_DHCP
> -+#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER)
> - struct in_addr a_record_from_hosts(char *name, time_t now)
> - {
> -   struct crec *crecp = NULL;
> -@@ -1229,7 +1232,7 @@ void cache_add_dhcp_entry(char *host_name, int 
> prot,
> -       addrlen = sizeof(struct in6_addr);
> -     }
> - #endif
> --  
> -+
> -   inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
> -   
> -   while ((crec = cache_find_by_name(crec, host_name, 0, flags | 
> F_CNAME)))
> -@@ -1294,7 +1297,11 @@ void cache_add_dhcp_entry(char *host_name, 
> int prot,
> -       else
> - 	crec->ttd = ttd;
> -       crec->addr.addr = *host_address;
> -+#ifdef HAVE_ISC_READER
> -+      crec->name.namep = strdup(host_name);
> -+#else
> -       crec->name.namep = host_name;
> -+#endif
> -       crec->uid = next_uid();
> -       cache_hash(crec);
> - 
> -diff --git a/src/dnsmasq.c b/src/dnsmasq.c
> -index e903a24c8105..eefc7f939933 100644
> ---- a/src/dnsmasq.c
> -+++ b/src/dnsmasq.c
> -@@ -970,6 +970,11 @@ int main (int argc, char **argv)
> - 
> - 	  poll_resolv(0, daemon->last_resolv != 0, now); 	  
> - 	  daemon->last_resolv = now;
> -+
> -+#ifdef HAVE_ISC_READER
> -+	  if (daemon->lease_file && !daemon->dhcp)
> -+	    load_dhcp(now);
> -+#endif
> - 	}
> - #endif
> - 
> -diff --git a/src/dnsmasq.h b/src/dnsmasq.h
> -index 89e758b56a0a..c5edd6fdf7f5 100644
> ---- a/src/dnsmasq.h
> -+++ b/src/dnsmasq.h
> -@@ -1502,3 +1502,8 @@ void inotify_dnsmasq_init();
> - int inotify_check(time_t now);
> - void set_dynamic_inotify(int flag, int total_size, struct crec 
> **rhash, int revhashsz);
> - #endif
> -+
> -+/* isc.c */
> -+#ifdef HAVE_ISC_READER
> -+void load_dhcp(time_t now);
> -+#endif
> -diff --git a/src/isc.c b/src/isc.c
> -new file mode 100644
> -index 000000000000..51064426f17f
> ---- /dev/null
> -+++ b/src/isc.c
> -@@ -0,0 +1,251 @@
> -+/* dnsmasq is Copyright (c) 2014 John Volpe, Simon Kelley and
> -+     Michael Tremer
> -+
> -+  This program is free software; you can redistribute it and/or 
> modify
> -+  it under the terms of the GNU General Public License as published 
> by
> -+  the Free Software Foundation; version 2 dated June, 1991, or
> -+  (at your option) version 3 dated 29 June, 2007.
> -+
> -+  This program is distributed in the hope that it will be useful,
> -+  but WITHOUT ANY WARRANTY; without even the implied warranty of
> -+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> -+  GNU General Public License for more details.
> -+  
> -+  You should have received a copy of the GNU General Public License
> -+  along with this program.  If not, see <
> http://www.gnu.org/licenses/>.
> -+
> -+  Code in this file is based on contributions by John Volpe and
> -+  Simon Kelley. Updated for recent versions of dnsmasq by
> -+  Michael Tremer.
> -+*/
> -+
> -+#include "dnsmasq.h"
> -+
> -+#ifdef HAVE_ISC_READER
> -+#define MAXTOK 50
> -+
> -+struct isc_dhcp_lease {
> -+	char* name;
> -+	char* fqdn;
> -+	time_t expires;
> -+	struct in_addr addr;
> -+	struct isc_dhcp_lease* next;
> -+};
> -+
> -+static struct isc_dhcp_lease* dhcp_lease_new(const char* hostname) 
> {
> -+	struct isc_dhcp_lease* lease = 
> whine_malloc(sizeof(*lease));
> -+
> -+	lease->name = strdup(hostname);
> -+	if (daemon->domain_suffix) {
> -+		asprintf(&lease->fqdn, "%s.%s", hostname, daemon
> ->domain_suffix);
> -+	}
> -+	lease->expires = 0;
> -+	lease->next = NULL;
> -+
> -+	return lease;
> -+}
> -+
> -+static void dhcp_lease_free(struct isc_dhcp_lease* lease) {
> -+	if (!lease)
> -+		return;
> -+
> -+	if (lease->name)
> -+		free(lease->name);
> -+	if (lease->fqdn)
> -+		free(lease->fqdn);
> -+	free(lease);
> -+}
> -+
> -+static int next_token(char* token, int buffsize, FILE* fp) {
> -+	int c, count = 0;
> -+	char* cp = token;
> -+
> -+	while ((c = getc(fp)) != EOF) {
> -+		if (c == '#') {
> -+			do {
> -+				c = getc(fp);
> -+			} while (c != '\n' && c != EOF);
> -+		}
> -+
> -+		if (c == ' ' || c == '\t' || c == '\n' || c == ';') 
> {
> -+			if (count)
> -+				break;
> -+		} else if ((c != '"') && (count < buffsize - 1)) {
> -+			*cp++ = c;
> -+			count++;
> -+		}
> -+	}
> -+
> -+	*cp = 0;
> -+	return count ? 1 : 0;
> -+}
> -+
> -+static long get_utc_offset() {
> -+	time_t t = time(NULL);
> -+	struct tm* time_struct = localtime(&t);
> -+
> -+	return time_struct->tm_gmtoff;
> -+}
> -+
> -+static time_t parse_lease_time(const char* token_date, const char* 
> token_time) {
> -+	time_t time = (time_t)(-1);
> -+	struct tm lease_time;
> -+
> -+	if (sscanf(token_date, "%d/%d/%d", &lease_time.tm_year, 
> &lease_time.tm_mon, &lease_time.tm_mday) == 3) {
> -+		lease_time.tm_year -= 1900;
> -+		lease_time.tm_mon -= 1;
> -+
> -+		if (sscanf(token_time, "%d:%d:%d", 
> &lease_time.tm_hour, &lease_time.tm_min, &lease_time.tm_sec) == 3) {
> -+			time = mktime(&lease_time) + 
> get_utc_offset();
> -+		}
> -+	}
> -+
> -+	return time;
> -+}
> -+
> -+static struct isc_dhcp_lease* find_lease(const char* hostname, 
> struct isc_dhcp_lease* leases) {
> -+	struct isc_dhcp_lease* lease = leases;
> -+
> -+	while (lease) {
> -+		if (strcmp(hostname, lease->name) == 0) {
> -+			return lease;
> -+		}
> -+		lease = lease->next;
> -+	}
> -+
> -+	return NULL;
> -+}
> -+
> -+static off_t lease_file_size = (off_t)0;
> -+static ino_t lease_file_inode = (ino_t)0;
> -+
> -+void load_dhcp(time_t now) {
> -+	struct isc_dhcp_lease* leases = NULL;
> -+
> -+	struct stat statbuf;
> -+	if (stat(daemon->lease_file, &statbuf) == -1) {
> -+		return;
> -+	}
> -+
> -+	/* Do nothing if the lease file has not changed. */
> -+	if ((statbuf.st_size <= lease_file_size) && (statbuf.st_ino 
> == lease_file_inode))
> -+		return;
> -+
> -+	lease_file_size = statbuf.st_size;
> -+	lease_file_inode = statbuf.st_ino;
> -+
> -+	FILE* fp = fopen(daemon->lease_file, "r");
> -+	if (!fp) {
> -+		my_syslog(LOG_ERR, _("failed to load %s:%s"), 
> daemon->lease_file, strerror(errno));
> -+		return;
> -+	}
> -+
> -+	my_syslog(LOG_INFO, _("reading %s"), daemon->lease_file);
> -+
> -+	char* hostname = daemon->namebuff;
> -+	struct in_addr host_address;
> -+	time_t time_starts = -1;
> -+	time_t time_ends = -1;
> -+	int nomem;
> -+
> -+	char token[MAXTOK];
> -+	while ((next_token(token, MAXTOK, fp))) {
> -+		if (strcmp(token, "lease") == 0) {
> -+			hostname[0] = '\0';
> -+
> -+			if (next_token(token, MAXTOK, fp) && 
> ((host_address.s_addr = inet_addr(token)) != (in_addr_t)-1)) {
> -+				if (next_token(token, MAXTOK, fp) 
> && *token == '{') {
> -+					while (next_token(token, 
> MAXTOK, fp) && *token != '}') {
> -+						if ((strcmp(token, 
> "client-hostname") == 0) || (strcmp(token, "hostname") == 0)) {
> -+							if 
> (next_token(hostname, MAXDNAME, fp)) {
> -+								if 
> (!canonicalise(hostname, &nomem)) {
> -+									
> *hostname = 0;
> -+									
> my_syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file);
> -+								}
> -+							}
> -+						} else if 
> ((strcmp(token, "starts") == 0) || (strcmp(token, "ends") == 0)) {
> -+							char 
> token_date[MAXTOK];
> -+							char 
> token_time[MAXTOK];
> -+
> -+							int 
> is_starts = strcmp(token, "starts") == 0;
> -+
> -+							// Throw 
> away the weekday and parse the date.
> -+							if 
> (next_token(token, MAXTOK, fp) && next_token(token_date, MAXTOK, fp) 
> && next_token(token_time, MAXTOK, fp)) {
> -+								tim
> e_t time = parse_lease_time(token_date, token_time);
> -+
> -+								if 
> (is_starts)
> -+									
> time_starts = time;
> -+								els
> e
> -+									
> time_ends = time;
> -+							}
> -+						}
> -+					}
> -+
> -+					if (!*hostname)
> -+						continue;
> -+
> -+					if ((time_starts == -1) || 
> (time_ends == -1))
> -+						continue;
> -+
> -+					if (difftime(now, 
> time_ends) > 0)
> -+						continue;
> -+
> -+					char* dot = 
> strchr(hostname, '.');
> -+					if (dot) {
> -+						if (!daemon
> ->domain_suffix || hostname_isequal(dot + 1, daemon->domain_suffix)) 
> {
> -+							my_syslog(L
> OG_WARNING,
> -+								_("
> Ignoring DHCP lease for %s because it has an illegal domain part"),
> -+								hos
> tname);
> -+							continue;
> -+						}
> -+						*dot = 0;
> -+					}
> -+
> -+					// Search for an existing 
> lease in the list
> -+					// with the given host name 
> and update the data
> -+					// if needed.
> -+					struct isc_dhcp_lease* 
> lease = find_lease(hostname, leases);
> -+
> -+					// If no lease already 
> exists, we create a new one
> -+					// and append it to the 
> list.
> -+					if (!lease) {
> -+						lease = 
> dhcp_lease_new(hostname);
> -+
> -+						lease->next = 
> leases;
> -+						leases = lease;
> -+					}
> -+
> -+					// Only update more recent 
> leases.
> -+					if (lease->expires > 
> time_ends)
> -+						continue;
> -+
> -+					lease->addr = host_address;
> -+					lease->expires = time_ends;
> -+				}
> -+			}
> -+		}
> -+	}
> -+
> -+	fclose(fp);
> -+
> -+	// Drop all entries.
> -+	cache_unhash_dhcp();
> -+
> -+	while (leases) {
> -+		struct isc_dhcp_lease *lease = leases;
> -+		leases = lease->next;
> -+
> -+		if (lease->fqdn) {
> -+			cache_add_dhcp_entry(lease->fqdn, AF_INET, 
> (struct all_addr*)&lease->addr.s_addr, lease->expires);
> -+		}
> -+
> -+		if (lease->name) {
> -+			cache_add_dhcp_entry(lease->name, AF_INET, 
> (struct all_addr*)&lease->addr.s_addr, lease->expires);
> -+		}
> -+
> -+		// Cleanup
> -+		dhcp_lease_free(lease);
> -+	}
> -+}
> -+
> -+#endif
> -diff --git a/src/option.c b/src/option.c
> -index cb4e76ba0aa2..f6420fcbb7ab 100644
> ---- a/src/option.c
> -+++ b/src/option.c
> -@@ -1693,7 +1693,7 @@ static int one_opt(int option, char *arg, char 
> *errstr, char *gen_err, int comma
> - 	ret_err(_("bad MX target"));
> -       break;
> - 
> --#ifdef HAVE_DHCP      
> -+#if (defined HAVE_DHCP) || (defined HAVE_ISC_READER)
> -     case 'l':  /* --dhcp-leasefile */
> -       daemon->lease_file = opt_string_alloc(arg);
> -       break;