From 45e65f1dd90ffe06d2e80c0aa3c2e4f82a0cede7 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 28 Apr 2014 18:26:20 +0200 Subject: [PATCH] dnsmasq: Update to 2.70. Adds support for DNSSEC validation, increases the cache size and adds a patch to read ISC dhcpd lease file (for IPv4). --- lfs/dnsmasq | 27 +- src/initscripts/init.d/dnsmasq | 23 +- ...-support-to-read-ISC-DHCP-lease-file.patch | 366 ++++++++++++++++++ 3 files changed, 404 insertions(+), 12 deletions(-) create mode 100644 src/patches/dnsmasq-2.70-Add-support-to-read-ISC-DHCP-lease-file.patch diff --git a/lfs/dnsmasq b/lfs/dnsmasq index 29fb9b38df..8257913498 100644 --- a/lfs/dnsmasq +++ b/lfs/dnsmasq @@ -24,14 +24,16 @@ include Config -VER = 2.45 +VER = 2.70 THISAPP = dnsmasq-$(VER) -DL_FILE = $(THISAPP).tar.gz +DL_FILE = $(THISAPP).tar.xz DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) +COPTS = -DHAVE_ISC_READER + ############################################################################### # Top-level Rules ############################################################################### @@ -40,7 +42,7 @@ objects = $(DL_FILE) $(DL_FILE) = $(DL_FROM)/$(DL_FILE) -$(DL_FILE)_MD5 = b7956e15c9766e05b3eca3ce88fdb616 +$(DL_FILE)_MD5 = 1d654e80888ab5dbba015548fd284d46 install : $(TARGET) @@ -69,13 +71,16 @@ $(subst %,%_MD5,$(objects)) : $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) @$(PREBUILD) - @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE) - cd $(DIR_APP) && sed -i -e 's|/usr/local|/usr|g' Makefile - cd $(DIR_APP)/src && sed -i \ - -e 's|^\/\* #define HAVE_ISC_READER .*$$|#define HAVE_ISC_READER\n#define NO_IPV6|' \ - -e 's|^#define HAVE_TFTP *$$|//#define HAVE_TFTP|' \ - -e 's/^#define CHUSER .*$$/#define CHUSER "dnsmasq"/' config.h - cd $(DIR_APP) && make $(MAKETUNING) - cd $(DIR_APP) && make install + @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq-2.70-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' \ + -e 's|#define HAVE_DHCP|//#define HAVE_DHCP|g' \ + -e 's|#define HAVE_DHCP6|//#define HAVE_DHCP6|g' \ + -e 's|#define HAVE_TFTP|//#define HAVE_TFTP|g' + + cd $(DIR_APP) && make CFLAGS="$(CFLAGS)" COPTS="$(COPTS)" $(MAKETUNING) + cd $(DIR_APP) && make PREFIX=/usr install @rm -rf $(DIR_APP) @$(POSTBUILD) diff --git a/src/initscripts/init.d/dnsmasq b/src/initscripts/init.d/dnsmasq index 34eee0c26e..48b9d19d02 100644 --- a/src/initscripts/init.d/dnsmasq +++ b/src/initscripts/init.d/dnsmasq @@ -20,7 +20,20 @@ if [ -e "/etc/sysconfig/dnsmasq" ]; then . /etc/sysconfig/dnsmasq fi +CACHE_SIZE=2500 +ENABLE_DNSSEC=1 SHOW_SRV=1 +TRUST_ANCHOR=".,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5" + +function dnssec_args() { + local cmdline="--dnssec" + + if [ -n "${TRUST_ANCHOR}" ]; then + cmdline="${cmdline} --trust-anchor=${TRUST_ANCHOR}" + fi + + echo "${cmdline}" +} function dns_forward_args() { local file="${1}" @@ -41,7 +54,6 @@ function dns_forward_args() { echo "${cmdline}" } - case "${1}" in start) # kill already running copy of dnsmasq... @@ -73,6 +85,15 @@ case "${1}" in # Add custom forward dns zones. ARGS="${ARGS} $(dns_forward_args /var/ipfire/dnsforward/config)" + # Enabled DNSSEC validation + if [ "${ENABLE_DNSSEC}" -eq 1 ]; then + ARGS="${ARGS} $(dnssec_args)" + fi + + if [ -n "${CACHE_SIZE}" ]; then + ARGS="${ARGS} --cache-size=${CACHE_SIZE}" + fi + loadproc /usr/sbin/dnsmasq -l /var/state/dhcp/dhcpd.leases $ARGS if [ "${SHOW_SRV}" -eq 1 ] && [ "${DNS1}" != "" -o "${DNS2}" != "" ]; then diff --git a/src/patches/dnsmasq-2.70-Add-support-to-read-ISC-DHCP-lease-file.patch b/src/patches/dnsmasq-2.70-Add-support-to-read-ISC-DHCP-lease-file.patch new file mode 100644 index 0000000000..88eb6a217e --- /dev/null +++ b/src/patches/dnsmasq-2.70-Add-support-to-read-ISC-DHCP-lease-file.patch @@ -0,0 +1,366 @@ +From b3c0d11d8bcf810b8f50f695ea36c8183fa4791a Mon Sep 17 00:00:00 2001 +From: Michael Tremer +Date: Mon, 28 Apr 2014 00:51:13 +0200 +Subject: [PATCH] Add support to read ISC DHCP lease file. + +--- + Makefile | 2 +- + src/cache.c | 13 +++- + src/dnsmasq.c | 5 ++ + src/dnsmasq.h | 5 ++ + src/isc.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/option.c | 2 +- + 6 files changed, 256 insertions(+), 5 deletions(-) + create mode 100644 src/isc.c + +diff --git a/Makefile b/Makefile +index 292c8bd..5e0cdbe 100644 +--- a/Makefile ++++ b/Makefile +@@ -69,7 +69,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 ++ domain.o dnssec.o blockdata.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 5cec918..1f5657f 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 +@@ -1110,7 +1113,7 @@ void cache_reload(void) + total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz); + } + +-#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; +@@ -1188,7 +1191,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))) +@@ -1253,7 +1256,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 1c96a0e..156ac9a 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -934,6 +934,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 + } + + if (FD_ISSET(piperead, &rset)) +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 3032546..a40b2a9 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1447,3 +1447,8 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force); + time_t periodic_slaac(time_t now, struct dhcp_lease *leases); + void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases); + #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 0000000..565e4e2 +--- /dev/null ++++ b/src/isc.c +@@ -0,0 +1,234 @@ ++/* 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 . ++ ++ 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() { ++ struct isc_dhcp_lease* lease = whine_malloc(sizeof(*lease)); ++ ++ lease->name = NULL; ++ lease->fqdn = NULL; ++ 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 time_t parse_lease_time(const char* token_date, const char* token_time) { ++ time_t time = (time_t)(-1); ++ struct tm lease_time; ++ ++ static const int months[11] = {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; ++ ++ if (sscanf(token_date, "%d/%d/%d", &lease_time.tm_year, &lease_time.tm_mon, &lease_time.tm_mday) == 3) { ++ if (sscanf(token_time, "%d:%d:%d", &lease_time.tm_hour, &lease_time.tm_min, &lease_time.tm_sec) == 3) { ++ /* There doesn't seem to be a universally available library function ++ which converts broken-down _GMT_ time to seconds-in-epoch. ++ The following was borrowed from ISC dhcpd sources, where ++ it is noted that it might not be entirely accurate for odd seconds. ++ Since we're trying to get the same answer as dhcpd, that's just ++ fine here. */ ++ time = ((((((365 * (lease_time.tm_year - 1970) + ++ (lease_time.tm_year - 1969) / 4 + ++ (lease_time.tm_mon > 1 ? months[lease_time.tm_mon - 2] : 0) + ++ (lease_time.tm_mon > 2 && !((lease_time.tm_year - 1972) & 3 )) + ++ (lease_time.tm_mday - 1)) * 24) + ++ lease_time.tm_hour) * 60) + ++ lease_time.tm_mon) * 60) + ++ lease_time.tm_sec; ++ } ++ } ++ ++ return time; ++} ++ ++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; ++ } ++ ++ struct isc_dhcp_lease* lease = dhcp_lease_new(); ++ lease->name = strdup(hostname); ++ lease->addr = host_address; ++ lease->expires = time_ends; ++ lease->next = NULL; ++ ++ if (daemon->domain_suffix) { ++ asprintf(&lease->fqdn, "%s.%s", hostname, daemon->domain_suffix); ++ } ++ ++ if (!leases) ++ leases = lease; ++ else ++ leases->next = lease; ++ } ++ } ++ } ++ } ++ ++ 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 daa728f..d16c982 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -1642,7 +1642,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; +-- +1.9.0 + -- 2.39.2