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)) { ++ time_t time = parse_lease_time(token_date, token_time); ++ ++ if (is_starts) ++ time_starts = time; ++ else ++ 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(LOG_WARNING, ++ _("Ignoring DHCP lease for %s because it has an illegal domain part"), ++ hostname); ++ 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)) { -+ time_t time = parse_lease_time(token_date, token_time); -+ -+ if (is_starts) -+ time_starts = time; -+ else -+ 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(LOG_WARNING, -+ _("Ignoring DHCP lease for %s because it has an illegal domain part"), -+ hostname); -+ 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;
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/%3E. ++ ++ 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/%3E. -+ -+ 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;