include $(TOPDIR)/rules.mk
PKG_NAME:=dnsmasq
-PKG_VERSION:=2.80test2
-PKG_RELEASE:=5
+PKG_VERSION:=2.80test3
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/test-releases
-PKG_HASH:=e731666094699afcbad947f89f7f8afbf92e5ddc3c915459d4936159d81116f0
+PKG_HASH:=af9f6fd13e0d6c5a68059bcf8634c2784c0533017fd48fbaf59cd2955342d301
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING
+++ /dev/null
-From f84e674d8aa2316fea8d2145a40fcef0441e3856 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 4 May 2018 16:29:57 +0100
-Subject: [PATCH 01/17] Be persistent with broken-upstream-DNSSEC warnings.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/dnssec.c | 7 +------
- 1 file changed, 1 insertion(+), 6 deletions(-)
-
---- a/src/dnssec.c
-+++ b/src/dnssec.c
-@@ -876,12 +876,7 @@ int dnssec_validate_ds(time_t now, struc
-
- if (rc == STAT_INSECURE)
- {
-- static int reported = 0;
-- if (!reported)
-- {
-- reported = 1;
-- my_syslog(LOG_WARNING, _("Insecure DS reply received, do upstream DNS servers support DNSSEC?"));
-- }
-+ my_syslog(LOG_WARNING, _("Insecure DS reply received, do upstream DNS servers support DNSSEC?"));
- rc = STAT_BOGUS;
- }
-
+++ /dev/null
-From 0669ee7a69a004ce34fed41e50aa575f8e04427b Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 4 May 2018 16:46:24 +0100
-Subject: [PATCH 02/17] Fix DHCP broken-ness when --no-ping AND
- --dhcp-sequential-ip are set.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- CHANGELOG | 3 ++-
- src/dhcp.c | 2 +-
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
---- a/CHANGELOG
-+++ b/CHANGELOG
-@@ -14,7 +14,8 @@ version 2.80
- when the upstream namesevers do not support DNSSEC, and in this
- case no DNSSEC validation at all is occuring.
-
--
-+ Fix DHCP broken-ness when --no-ping AND --dhcp-sequential-ip
-+ are set. Thanks to Daniel Miess for help with this.
-
-
- version 2.79
---- a/src/dhcp.c
-+++ b/src/dhcp.c
-@@ -678,7 +678,7 @@ struct ping_result *do_icmp_ping(time_t
- if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
- {
- /* overloaded, or configured not to check, loopback interface, return "not in use" */
-- dummy.hash = 0;
-+ dummy.hash = hash;
- return &dummy;
- }
- else if (icmp_ping(addr))
+++ /dev/null
-From 07ed585c38d8f7c0a18470d2e79cf46ea92ea96a Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 4 May 2018 21:52:22 +0100
-Subject: [PATCH 03/17] Add logging for DNS error returns from upstream and
- local configuration.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/cache.c | 13 +++++++++++++
- src/dnsmasq.h | 7 ++++++-
- src/forward.c | 25 +++++++++++++++++++------
- src/rfc1035.c | 19 ++++++++++++++-----
- 4 files changed, 52 insertions(+), 12 deletions(-)
-
---- a/src/cache.c
-+++ b/src/cache.c
-@@ -1598,6 +1598,19 @@ void log_query(unsigned int flags, char
- {
- if (flags & F_KEYTAG)
- sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
-+ else if (flags & F_RCODE)
-+ {
-+ unsigned int rcode = addr->addr.rcode.rcode;
-+
-+ if (rcode == SERVFAIL)
-+ dest = "SERVFAIL";
-+ else if (rcode == REFUSED)
-+ dest = "REFUSED";
-+ else if (rcode == NOTIMP)
-+ dest = "not implemented";
-+ else
-+ sprintf(daemon->addrbuff, "%u", rcode);
-+ }
- else
- {
- #ifdef HAVE_IPV6
---- a/src/dnsmasq.h
-+++ b/src/dnsmasq.h
-@@ -268,7 +268,11 @@ struct all_addr {
- /* for log_query */
- struct {
- unsigned short keytag, algo, digest;
-- } log;
-+ } log;
-+ /* for log_query */
-+ struct {
-+ unsigned int rcode;
-+ } rcode;
- /* for cache_insert of DNSKEY, DS */
- struct {
- unsigned short class, type;
-@@ -459,6 +463,7 @@ struct crec {
- #define F_IPSET (1u<<26)
- #define F_NOEXTRA (1u<<27)
- #define F_SERVFAIL (1u<<28)
-+#define F_RCODE (1u<<29)
-
- /* Values of uid in crecs with F_CONFIG bit set. */
- #define SRC_INTERFACE 0
---- a/src/forward.c
-+++ b/src/forward.c
-@@ -563,6 +563,7 @@ static size_t process_reply(struct dns_h
- unsigned char *pheader, *sizep;
- char **sets = 0;
- int munged = 0, is_sign;
-+ unsigned int rcode = RCODE(header);
- size_t plen;
-
- (void)ad_reqd;
-@@ -593,6 +594,9 @@ static size_t process_reply(struct dns_h
-
- if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
- {
-+ /* Get extended RCODE. */
-+ rcode |= sizep[2] << 4;
-+
- if (check_subnet && !check_source(header, plen, pheader, query_source))
- {
- my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
-@@ -641,11 +645,20 @@ static size_t process_reply(struct dns_h
- if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
- header->hb4 &= ~HB4_AD;
-
-- if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
-+ if (OPCODE(header) != QUERY)
- return resize_packet(header, n, pheader, plen);
-+
-+ if (rcode != NOERROR && rcode != NXDOMAIN)
-+ {
-+ struct all_addr a;
-+ a.addr.rcode.rcode = rcode;
-+ log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
-+
-+ return resize_packet(header, n, pheader, plen);
-+ }
-
- /* Complain loudly if the upstream server is non-recursive. */
-- if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
-+ if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
- server && !(server->flags & SERV_WARNED_RECURSIVE))
- {
- prettyprint_addr(&server->addr, daemon->namebuff);
-@@ -654,7 +667,7 @@ static size_t process_reply(struct dns_h
- server->flags |= SERV_WARNED_RECURSIVE;
- }
-
-- if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
-+ if (daemon->bogus_addr && rcode != NXDOMAIN &&
- check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
- {
- munged = 1;
-@@ -666,7 +679,7 @@ static size_t process_reply(struct dns_h
- {
- int doctored = 0;
-
-- if (RCODE(header) == NXDOMAIN &&
-+ if (rcode == NXDOMAIN &&
- extract_request(header, n, daemon->namebuff, NULL) &&
- check_for_local_domain(daemon->namebuff, now))
- {
-@@ -1090,7 +1103,7 @@ void reply_query(int fd, int family, tim
- if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
- domain = daemon->namebuff;
-
-- log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
-+ log_query(F_SECSTAT, domain, NULL, result);
- }
-
- if (status == STAT_SECURE)
-@@ -1948,7 +1961,7 @@ unsigned char *tcp_request(int confd, ti
- if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
- domain = daemon->namebuff;
-
-- log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
-+ log_query(F_SECSTAT, domain, NULL, result);
-
- if (status == STAT_BOGUS)
- {
---- a/src/rfc1035.c
-+++ b/src/rfc1035.c
-@@ -926,12 +926,11 @@ unsigned int extract_request(struct dns_
- return F_QUERY;
- }
-
--
- size_t setup_reply(struct dns_header *header, size_t qlen,
- struct all_addr *addrp, unsigned int flags, unsigned long ttl)
- {
- unsigned char *p;
--
-+
- if (!(p = skip_questions(header, qlen)))
- return 0;
-
-@@ -948,7 +947,12 @@ size_t setup_reply(struct dns_header *he
- else if (flags == F_NXDOMAIN)
- SET_RCODE(header, NXDOMAIN);
- else if (flags == F_SERVFAIL)
-- SET_RCODE(header, SERVFAIL);
-+ {
-+ struct all_addr a;
-+ a.addr.rcode.rcode = SERVFAIL;
-+ log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
-+ SET_RCODE(header, SERVFAIL);
-+ }
- else if (flags == F_IPV4)
- { /* we know the address */
- SET_RCODE(header, NOERROR);
-@@ -966,8 +970,13 @@ size_t setup_reply(struct dns_header *he
- }
- #endif
- else /* nowhere to forward to */
-- SET_RCODE(header, REFUSED);
--
-+ {
-+ struct all_addr a;
-+ a.addr.rcode.rcode = REFUSED;
-+ log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
-+ SET_RCODE(header, REFUSED);
-+ }
-+
- return p - (unsigned char *)header;
- }
-
+++ /dev/null
-From 6b17335209639a56f214d011eaed4ebcde8dd276 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Tue, 8 May 2018 18:32:14 +0100
-Subject: [PATCH 04/17] Add packet-dump debugging facility.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- CHANGELOG | 6 ++
- Makefile | 2 +-
- bld/Android.mk | 3 +-
- man/dnsmasq.8 | 7 ++
- src/config.h | 16 ++++-
- src/dnsmasq.c | 16 ++++-
- src/dnsmasq.h | 29 +++++++-
- src/dump.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/forward.c | 37 ++++++++--
- src/option.c | 14 ++++
- 10 files changed, 329 insertions(+), 11 deletions(-)
- create mode 100644 src/dump.c
-
---- a/CHANGELOG
-+++ b/CHANGELOG
-@@ -17,6 +17,12 @@ version 2.80
- Fix DHCP broken-ness when --no-ping AND --dhcp-sequential-ip
- are set. Thanks to Daniel Miess for help with this.
-
-+ Add a facilty to store DNS packets sent/recieved in a
-+ pcap-format file for later debugging. The file location
-+ is given by the --dumpfile option, and a bitmap controlling
-+ which packets should be dumped is given by the --dumpmask
-+ option.
-+
-
- version 2.79
- Fix parsing of CNAME arguments, which are confused by extra spaces.
---- a/Makefile
-+++ b/Makefile
-@@ -76,7 +76,7 @@ objs = cache.o rfc1035.o util.o option.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 rrfilter.o edns0.o arp.o crypto.o
-+ poll.o rrfilter.o edns0.o arp.o crypto.o dump.o
-
- hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
- dns-protocol.h radv-protocol.h ip6addr.h
---- a/bld/Android.mk
-+++ b/bld/Android.mk
-@@ -10,7 +10,8 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c
- dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
- radv.c slaac.c auth.c ipset.c domain.c \
- dnssec.c dnssec-openssl.c blockdata.c tables.c \
-- loop.c inotify.c poll.c rrfilter.c edns0.c arp.c crypto.c
-+ loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
-+ crypto.c dump.c
-
- LOCAL_MODULE := dnsmasq
-
---- a/man/dnsmasq.8
-+++ b/man/dnsmasq.8
-@@ -647,6 +647,13 @@ V4 mapped IPv6 addresses, which have a r
- The address range can be of the form
- <ip address>,<ip address> or <ip address>/<netmask> in both forms of the option.
- .TP
-+.B --dumpfile=<path/to/file>
-+Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end.
-+.TP
-+.B --dumpmask=<mask>
-+Specify which types of packets should be added to the dumpfile. The argument should be the OR of the bitmasks for each type of packet to be dumped: it can be specified in hex by preceding the number with 0x in the normal way. Each time a packet is written to the dumpfile, dnsmasq logs the packet sequence and the mask
-+representing its type. The current types are: 0x0001 - DNS queries from clients 0x0002 DNS replies to clients 0x0004 - DNS queries to upstream 0x0008 - DNS replies from upstream 0x0010 - queries send upstream for DNSSEC validation 0x0020 - replies to queries for DNSSEC validation 0x0040 - replies to client queries which fail DNSSEC validation 0x0080 replies to queries for DNSSEC validation which fail validation.
-+.TP
- .B --add-mac[=base64|text]
- Add the MAC address of the requestor to DNS queries which are
- forwarded upstream. This may be used to DNS filtering by the upstream
---- a/src/config.h
-+++ b/src/config.h
-@@ -117,6 +117,9 @@ HAVE_AUTH
- HAVE_DNSSEC
- include DNSSEC validator.
-
-+HAVE_DUMPFILE
-+ include code to dump packets to a libpcap-format file for debugging.
-+
- HAVE_LOOP
- include functionality to probe for and remove DNS forwarding loops.
-
-@@ -132,6 +135,7 @@ NO_DHCP6
- NO_SCRIPT
- NO_LARGEFILE
- NO_AUTH
-+NO_DUMPFILE
- NO_INOTIFY
- these are available to explicitly disable compile time options which would
- otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
-@@ -164,6 +168,7 @@ RESOLVFILE
- #define HAVE_AUTH
- #define HAVE_IPSET
- #define HAVE_LOOP
-+#define HAVE_DUMPFILE
-
- /* Build options which require external libraries.
-
-@@ -363,6 +368,10 @@ HAVE_SOCKADDR_SA_LEN
- #undef HAVE_LOOP
- #endif
-
-+#ifdef NO_DUMPFILE
-+#undef HAVE_DUMPFILE
-+#endif
-+
- #if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
- #define HAVE_INOTIFY
- #endif
-@@ -451,8 +460,11 @@ static char *compile_opts =
- #ifndef HAVE_INOTIFY
- "no-"
- #endif
--"inotify";
--
-+"inotify "
-+#ifndef HAVE_DUMPFILE
-+"no-"
-+#endif
-+"dumpfile";
-
- #endif
-
---- a/src/dnsmasq.c
-+++ b/src/dnsmasq.c
-@@ -366,7 +366,16 @@ int main (int argc, char **argv)
- else
- daemon->inotifyfd = -1;
- #endif
--
-+
-+ if (daemon->dump_file)
-+#ifdef HAVE_DUMPFILE
-+ dump_init();
-+ else
-+ daemon->dumpfd = -1;
-+#else
-+ die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
-+#endif
-+
- if (option_bool(OPT_DBUS))
- #ifdef HAVE_DBUS
- {
-@@ -1424,6 +1433,11 @@ static void async_event(int pipe, time_t
-
- if (daemon->runfile)
- unlink(daemon->runfile);
-+
-+#ifdef HAVE_DUMPFILE
-+ if (daemon->dumpfd != -1)
-+ close(daemon->dumpfd);
-+#endif
-
- my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
- flush_log();
---- a/src/dnsmasq.h
-+++ b/src/dnsmasq.h
-@@ -119,6 +119,9 @@ typedef unsigned long long u64;
- #include <net/if_arp.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
-+#ifdef HAVE_IPV6
-+#include <netinet/ip6.h>
-+#endif
- #include <netinet/ip_icmp.h>
- #include <sys/uio.h>
- #include <syslog.h>
-@@ -598,6 +601,16 @@ struct hostsfile {
- unsigned int index; /* matches to cache entries for logging */
- };
-
-+/* packet-dump flags */
-+#define DUMP_QUERY 0x0001
-+#define DUMP_REPLY 0x0002
-+#define DUMP_UP_QUERY 0x0004
-+#define DUMP_UP_REPLY 0x0008
-+#define DUMP_SEC_QUERY 0x0010
-+#define DUMP_SEC_REPLY 0x0020
-+#define DUMP_BOGUS 0x0040
-+#define DUMP_SEC_BOGUS 0x0080
-+
-
- /* DNSSEC status values. */
- #define STAT_SECURE 1
-@@ -1020,14 +1033,14 @@ extern struct daemon {
- unsigned int duid_enterprise, duid_config_len;
- unsigned char *duid_config;
- char *dbus_name;
-+ char *dump_file;
-+ int dump_mask;
- unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
- #ifdef OPTION6_PREFIX_CLASS
- struct prefix_class *prefix_classes;
- #endif
- #ifdef HAVE_DNSSEC
- struct ds_config *ds;
-- int dnssec_no_time_check;
-- int back_to_the_future;
- char *timestamp_file;
- #endif
-
-@@ -1040,6 +1053,8 @@ extern struct daemon {
- char *workspacename; /* ditto */
- char *rr_status; /* flags for individual RRs */
- int rr_status_sz;
-+ int dnssec_no_time_check;
-+ int back_to_the_future;
- #endif
- unsigned int local_answer, queries_forwarded, auth_answer;
- struct frec *frec_list;
-@@ -1094,6 +1109,10 @@ extern struct daemon {
- char *addrbuff;
- char *addrbuff2; /* only allocated when OPT_EXTRALOG */
-
-+#ifdef HAVE_DUMPFILE
-+ /* file for packet dumps. */
-+ int dumpfd;
-+#endif
- } *daemon;
-
- /* cache.c */
-@@ -1588,3 +1607,9 @@ int check_source(struct dns_header *head
- /* arp.c */
- int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now);
- int do_arp_script_run(void);
-+
-+/* dump.c */
-+#ifdef HAVE_DUMPFILE
-+void dump_init(void);
-+void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst);
-+#endif
---- /dev/null
-+++ b/src/dump.c
-@@ -0,0 +1,210 @@
-+/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
-+
-+ 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/>.
-+*/
-+
-+#include "dnsmasq.h"
-+
-+#ifdef HAVE_DUMPFILE
-+
-+static u32 packet_count;
-+
-+/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
-+struct pcap_hdr_s {
-+ u32 magic_number; /* magic number */
-+ u16 version_major; /* major version number */
-+ u16 version_minor; /* minor version number */
-+ u32 thiszone; /* GMT to local correction */
-+ u32 sigfigs; /* accuracy of timestamps */
-+ u32 snaplen; /* max length of captured packets, in octets */
-+ u32 network; /* data link type */
-+};
-+
-+struct pcaprec_hdr_s {
-+ u32 ts_sec; /* timestamp seconds */
-+ u32 ts_usec; /* timestamp microseconds */
-+ u32 incl_len; /* number of octets of packet saved in file */
-+ u32 orig_len; /* actual length of packet */
-+};
-+
-+
-+void dump_init(void)
-+{
-+ struct stat buf;
-+ struct pcap_hdr_s header;
-+ struct pcaprec_hdr_s pcap_header;
-+
-+ packet_count = 0;
-+
-+ if (stat(daemon->dump_file, &buf) == -1)
-+ {
-+ /* doesn't exist, create and add header */
-+ header.magic_number = 0xa1b2c3d4;
-+ header.version_major = 2;
-+ header.version_minor = 4;
-+ header.thiszone = 0;
-+ header.sigfigs = 0;
-+ header.snaplen = daemon->edns_pktsz + 200; /* slop for IP/UDP headers */
-+ header.network = 101; /* DLT_RAW http://www.tcpdump.org/linktypes.html */
-+
-+ if (errno != ENOENT ||
-+ (daemon->dumpfd = creat(daemon->dump_file, S_IRUSR | S_IWUSR)) == -1 ||
-+ !read_write(daemon->dumpfd, (void *)&header, sizeof(header), 0))
-+ die(_("cannot create %s: %s"), daemon->dump_file, EC_FILE);
-+ }
-+ else if ((daemon->dumpfd = open(daemon->dump_file, O_APPEND | O_RDWR)) == -1 ||
-+ !read_write(daemon->dumpfd, (void *)&header, sizeof(header), 1) ||
-+ header.magic_number != 0xa1b2c3d4)
-+ die(_("cannot access %s: %s"), daemon->dump_file, EC_FILE);
-+ else
-+ {
-+ /* count existing records */
-+ while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 1))
-+ {
-+ lseek(daemon->dumpfd, pcap_header.incl_len, SEEK_CUR);
-+ packet_count++;
-+ }
-+ }
-+}
-+
-+void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst)
-+{
-+ struct ip ip;
-+#ifdef HAVE_IPV6
-+ struct ip6_hdr ip6;
-+ int family;
-+#endif
-+ struct udphdr {
-+ u16 uh_sport; /* source port */
-+ u16 uh_dport; /* destination port */
-+ u16 uh_ulen; /* udp length */
-+ u16 uh_sum; /* udp checksum */
-+ } udp;
-+ struct pcaprec_hdr_s pcap_header;
-+ struct timeval time;
-+ u32 i, sum;
-+ void *iphdr;
-+ size_t ipsz;
-+ int rc;
-+
-+ if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
-+ return;
-+
-+ /* So wireshark can Id the packet. */
-+ udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT);
-+
-+#ifdef HAVE_IPV6
-+ if (src)
-+ family = src->sa.sa_family;
-+ else
-+ family = dst->sa.sa_family;
-+
-+ if (family == AF_INET6)
-+ {
-+ iphdr = &ip6;
-+ ipsz = sizeof(ip6);
-+ memset(&ip6, 0, sizeof(ip6));
-+
-+ ip6.ip6_vfc = 6 << 4;
-+ ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
-+ ip6.ip6_nxt = IPPROTO_UDP;
-+ ip6.ip6_hops = 64;
-+
-+ if (src)
-+ {
-+ memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ);
-+ udp.uh_sport = src->in6.sin6_port;
-+ }
-+
-+ if (dst)
-+ {
-+ memcpy(&ip6.ip6_dst, &dst->in6.sin6_addr, IN6ADDRSZ);
-+ udp.uh_dport = dst->in6.sin6_port;
-+ }
-+
-+ /* start UDP checksum */
-+ for (sum = 0, i = 0; i < IN6ADDRSZ; i++)
-+ sum += ((u16 *)&ip6.ip6_src)[i];
-+ }
-+ else
-+#endif
-+ {
-+ iphdr = &ip;
-+ ipsz = sizeof(ip);
-+ memset(&ip, 0, sizeof(ip));
-+
-+ ip.ip_v = IPVERSION;
-+ ip.ip_hl = sizeof(struct ip) / 4;
-+ ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
-+ ip.ip_ttl = IPDEFTTL;
-+ ip.ip_p = IPPROTO_UDP;
-+
-+ if (src)
-+ {
-+ ip.ip_src = src->in.sin_addr;
-+ udp.uh_sport = src->in.sin_port;
-+ }
-+
-+ if (dst)
-+ {
-+ ip.ip_dst = dst->in.sin_addr;
-+ udp.uh_dport = dst->in.sin_port;
-+ }
-+
-+ ip.ip_sum = 0;
-+ for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
-+ sum += ((u16 *)&ip)[i];
-+ while (sum >> 16)
-+ sum = (sum & 0xffff) + (sum >> 16);
-+ ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
-+
-+ /* start UDP checksum */
-+ sum = ip.ip_src.s_addr & 0xffff;
-+ sum += (ip.ip_src.s_addr >> 16) & 0xffff;
-+ sum += ip.ip_dst.s_addr & 0xffff;
-+ sum += (ip.ip_dst.s_addr >> 16) & 0xffff;
-+ }
-+
-+ if (len & 1)
-+ ((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */
-+
-+ udp.uh_sum = 0;
-+ udp.uh_ulen = htons(sizeof(struct udphdr) + len);
-+ sum += htons(IPPROTO_UDP);
-+ sum += htons(sizeof(struct udphdr) + len);
-+ for (i = 0; i < sizeof(struct udphdr)/2; i++)
-+ sum += ((u16 *)&udp)[i];
-+ for (i = 0; i < (len + 1) / 2; i++)
-+ sum += ((u16 *)packet)[i];
-+ while (sum >> 16)
-+ sum = (sum & 0xffff) + (sum >> 16);
-+ udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
-+
-+ rc = gettimeofday(&time, NULL);
-+ pcap_header.ts_sec = time.tv_sec;
-+ pcap_header.ts_usec = time.tv_usec;
-+ pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
-+
-+ if (rc == -1 ||
-+ !read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
-+ !read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
-+ !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0) ||
-+ !read_write(daemon->dumpfd, (void *)packet, len, 0))
-+ my_syslog(LOG_ERR, _("failed to write packet dump"));
-+ else
-+ my_syslog(LOG_INFO, _("dumping UDP packet %u mask 0x%04x"), ++packet_count, mask);
-+
-+}
-+
-+#endif
---- a/src/forward.c
-+++ b/src/forward.c
-@@ -508,6 +508,10 @@ static int forward_query(int udpfd, unio
-
- if (errno == 0)
- {
-+#ifdef HAVE_DUMPFILE
-+ dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &start->addr);
-+#endif
-+
- /* Keep info in case we want to re-send this packet */
- daemon->srv_save = start;
- daemon->packet_len = plen;
-@@ -769,7 +773,7 @@ void reply_query(int fd, int family, tim
- #endif
-
- header = (struct dns_header *)daemon->packet;
--
-+
- if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
- return;
-
-@@ -796,6 +800,12 @@ void reply_query(int fd, int family, tim
- if (!(forward = lookup_frec(ntohs(header->id), hash)))
- return;
-
-+#ifdef HAVE_DUMPFILE
-+ dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
-+ (void *)header, n, &serveraddr, NULL);
-+#endif
-+
-+
- /* log_query gets called indirectly all over the place, so
- pass these in global variables - sorry. */
- daemon->log_display_id = forward->log_id;
-@@ -934,6 +944,11 @@ void reply_query(int fd, int family, tim
- status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
- !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
- NULL, NULL);
-+#ifdef HAVE_DUMPFILE
-+ if (status == STAT_BOGUS)
-+ dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
-+ header, (size_t)n, &serveraddr, NULL);
-+#endif
- }
-
- /* Can't validate, as we're missing key data. Put this
-@@ -1060,6 +1075,11 @@ void reply_query(int fd, int family, tim
- setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
- }
- #endif
-+
-+#ifdef HAVE_DUMPFILE
-+ dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
-+#endif
-+
- while (retry_send(sendto(fd, (char *)header, nn, 0,
- &server->addr.sa,
- sa_len(&server->addr))));
-@@ -1114,8 +1134,8 @@ void reply_query(int fd, int family, tim
- bogusanswer = 1;
- }
- }
--#endif
--
-+#endif
-+
- /* restore CD bit to the value in the query */
- if (forward->flags & FREC_CHECKING_DISABLED)
- header->hb4 |= HB4_CD;
-@@ -1141,6 +1161,11 @@ void reply_query(int fd, int family, tim
- nn = resize_packet(header, nn, NULL, 0);
- }
- #endif
-+
-+#ifdef HAVE_DUMPFILE
-+ dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &forward->source);
-+#endif
-+
- send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
- &forward->source, &forward->dest, forward->iface);
- }
-@@ -1394,7 +1419,11 @@ void receive_query(struct listener *list
- pass these in global variables - sorry. */
- daemon->log_display_id = ++daemon->log_id;
- daemon->log_source_addr = &source_addr;
--
-+
-+#ifdef HAVE_DUMPFILE
-+ dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
-+#endif
-+
- if (extract_request(header, (size_t)n, daemon->namebuff, &type))
- {
- #ifdef HAVE_AUTH
---- a/src/option.c
-+++ b/src/option.c
-@@ -161,6 +161,8 @@ struct myoption {
- #define LOPT_TFTP_MTU 349
- #define LOPT_REPLY_DELAY 350
- #define LOPT_RAPID_COMMIT 351
-+#define LOPT_DUMPFILE 352
-+#define LOPT_DUMPMASK 353
-
- #ifdef HAVE_GETOPT_LONG
- static const struct option opts[] =
-@@ -327,6 +329,8 @@ static const struct myoption opts[] =
- { "dhcp-ttl", 1, 0 , LOPT_DHCPTTL },
- { "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY },
- { "dhcp-rapid-commit", 0, 0, LOPT_RAPID_COMMIT },
-+ { "dumpfile", 1, 0, LOPT_DUMPFILE },
-+ { "dumpmask", 1, 0, LOPT_DUMPMASK },
- { NULL, 0, 0, 0 }
- };
-
-@@ -500,6 +504,8 @@ static struct {
- { LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL },
- { LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL },
- { LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapid Commit option."), NULL },
-+ { LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump file"), NULL },
-+ { LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
- { 0, 0, NULL, NULL, NULL }
- };
-
-@@ -1811,6 +1817,14 @@ static int one_opt(int option, char *arg
- ret_err(_("bad MX target"));
- break;
-
-+ case LOPT_DUMPFILE: /* --dumpfile */
-+ daemon->dump_file = opt_string_alloc(arg);
-+ break;
-+
-+ case LOPT_DUMPMASK: /* --dumpmask */
-+ daemon->dump_mask = strtol(arg, NULL, 0);
-+ break;
-+
- #ifdef HAVE_DHCP
- case 'l': /* --dhcp-leasefile */
- daemon->lease_file = opt_string_alloc(arg);
+++ /dev/null
-From 34e26e14c5e0fb2d5f05f67858319c9db2058333 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Thu, 10 May 2018 20:54:57 +0100
-Subject: [PATCH 05/17] Retry query to other servers on receipt of SERVFAIL
- rcode.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/forward.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/src/forward.c
-+++ b/src/forward.c
-@@ -817,7 +817,7 @@ void reply_query(int fd, int family, tim
-
- /* Note: if we send extra options in the EDNS0 header, we can't recreate
- the query from the reply. */
-- if (RCODE(header) == REFUSED &&
-+ if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
- forward->forwardall == 0 &&
- !(forward->flags & FREC_HAS_EXTRADATA))
- /* for broken servers, attempt to send to another one. */
+++ /dev/null
-From a0088e83640d7d1544127dd668660462e9f78e52 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Thu, 10 May 2018 21:43:14 +0100
-Subject: [PATCH 06/17] Handle query retry on REFUSED or SERVFAIL for
- DNSSEC-generated queries.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/forward.c | 46 ++++++++++++++++++++++++++++++++++++++++------
- 1 file changed, 40 insertions(+), 6 deletions(-)
-
---- a/src/forward.c
-+++ b/src/forward.c
-@@ -298,9 +298,9 @@ static int forward_query(int udpfd, unio
- fd = forward->rfd4->fd;
- }
-
-- while (retry_send( sendto(fd, (char *)header, plen, 0,
-- &forward->sentto->addr.sa,
-- sa_len(&forward->sentto->addr))));
-+ while (retry_send(sendto(fd, (char *)header, plen, 0,
-+ &forward->sentto->addr.sa,
-+ sa_len(&forward->sentto->addr))));
-
- return 1;
- }
-@@ -804,8 +804,7 @@ void reply_query(int fd, int family, tim
- dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
- (void *)header, n, &serveraddr, NULL);
- #endif
--
--
-+
- /* log_query gets called indirectly all over the place, so
- pass these in global variables - sorry. */
- daemon->log_display_id = forward->log_id;
-@@ -826,6 +825,40 @@ void reply_query(int fd, int family, tim
- size_t plen;
- int is_sign;
-
-+ /* For DNSSEC originated queries, just retry the query to the same server. */
-+ if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
-+ {
-+ blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
-+ plen = forward->stash_len;
-+
-+ forward->forwardall = 2; /* only retry once */
-+
-+ if (forward->sentto->addr.sa.sa_family == AF_INET)
-+ log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
-+#ifdef HAVE_IPV6
-+ else
-+ log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
-+#endif
-+
-+ if (forward->sentto->sfd)
-+ fd = forward->sentto->sfd->fd;
-+ else
-+ {
-+#ifdef HAVE_IPV6
-+ if (forward->sentto->addr.sa.sa_family == AF_INET6)
-+ fd = forward->rfd6->fd;
-+ else
-+#endif
-+ fd = forward->rfd4->fd;
-+ }
-+
-+ while (retry_send(sendto(fd, (char *)header, plen, 0,
-+ &forward->sentto->addr.sa,
-+ sa_len(&forward->sentto->addr))));
-+
-+ return;
-+ }
-+
- /* In strict order mode, there must be a server later in the chain
- left to send to, otherwise without the forwardall mechanism,
- code further on will cycle around the list forwever if they
-@@ -1017,7 +1050,8 @@ void reply_query(int fd, int family, tim
- #ifdef HAVE_IPV6
- new->rfd6 = NULL;
- #endif
-- new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
-+ new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
-+ new->forwardall = 0;
-
- new->dependent = forward; /* to find query awaiting new one. */
- forward->blocking_query = new; /* for garbage cleaning */
+++ /dev/null
-From 1f60a18ea1c64beb8b6cffa0650a2bfad95ac352 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 11 May 2018 16:44:16 +0100
-Subject: [PATCH 07/17] Retry SERVFAIL DNSSEC queries to a different server, if
- possible.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/forward.c | 53 ++++++++++++++++++++++++++++++++++++++++++-----------
- 1 file changed, 42 insertions(+), 11 deletions(-)
-
---- a/src/forward.c
-+++ b/src/forward.c
-@@ -825,9 +825,12 @@ void reply_query(int fd, int family, tim
- size_t plen;
- int is_sign;
-
-+#ifdef HAVE_DNSSEC
- /* For DNSSEC originated queries, just retry the query to the same server. */
- if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
- {
-+ struct server *start;
-+
- blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
- plen = forward->stash_len;
-
-@@ -839,26 +842,54 @@ void reply_query(int fd, int family, tim
- else
- log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
- #endif
--
-- if (forward->sentto->sfd)
-- fd = forward->sentto->sfd->fd;
-+
-+ start = forward->sentto;
-+
-+ /* for non-domain specific servers, see if we can find another to try. */
-+ if ((forward->sentto->flags & SERV_TYPE) == 0)
-+ while (1)
-+ {
-+ if (!(start = start->next))
-+ start = daemon->servers;
-+ if (start == forward->sentto)
-+ break;
-+
-+ if ((start->flags & SERV_TYPE) == 0 &&
-+ (start->flags & SERV_DO_DNSSEC))
-+ break;
-+ }
-+
-+
-+ if (start->sfd)
-+ fd = start->sfd->fd;
- else
- {
- #ifdef HAVE_IPV6
-- if (forward->sentto->addr.sa.sa_family == AF_INET6)
-- fd = forward->rfd6->fd;
-+ if (start->addr.sa.sa_family == AF_INET6)
-+ {
-+ /* may have changed family */
-+ if (!forward->rfd6)
-+ forward->rfd6 = allocate_rfd(AF_INET6);
-+ fd = forward->rfd6->fd;
-+ }
- else
- #endif
-- fd = forward->rfd4->fd;
-+ {
-+ /* may have changed family */
-+ if (!forward->rfd4)
-+ forward->rfd4 = allocate_rfd(AF_INET);
-+ fd = forward->rfd4->fd;
-+ }
- }
--
-+
- while (retry_send(sendto(fd, (char *)header, plen, 0,
-- &forward->sentto->addr.sa,
-- sa_len(&forward->sentto->addr))));
-+ &start->addr.sa,
-+ sa_len(&start->addr))));
-
- return;
- }
--
-+#endif
-+
- /* In strict order mode, there must be a server later in the chain
- left to send to, otherwise without the forwardall mechanism,
- code further on will cycle around the list forwever if they
-@@ -1024,7 +1055,7 @@ void reply_query(int fd, int family, tim
- while (1)
- {
- if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
-- (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
-+ ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
- !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
- {
- new_server = start;
+++ /dev/null
-From e27825b0ef1e79ab05b1752c8c838cb43ad39d79 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 11 May 2018 17:20:47 +0100
-Subject: [PATCH 08/17] Fix logging in previous.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/forward.c | 15 +++++++--------
- 1 file changed, 7 insertions(+), 8 deletions(-)
-
---- a/src/forward.c
-+++ b/src/forward.c
-@@ -835,14 +835,6 @@ void reply_query(int fd, int family, tim
- plen = forward->stash_len;
-
- forward->forwardall = 2; /* only retry once */
--
-- if (forward->sentto->addr.sa.sa_family == AF_INET)
-- log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
--#ifdef HAVE_IPV6
-- else
-- log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
--#endif
--
- start = forward->sentto;
-
- /* for non-domain specific servers, see if we can find another to try. */
-@@ -886,6 +878,13 @@ void reply_query(int fd, int family, tim
- &start->addr.sa,
- sa_len(&start->addr))));
-
-+ if (start->addr.sa.sa_family == AF_INET)
-+ log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&start->addr.in.sin_addr, "dnssec");
-+#ifdef HAVE_IPV6
-+ else
-+ log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&start->addr.in6.sin6_addr, "dnssec");
-+#endif
-+
- return;
- }
- #endif
+++ /dev/null
-From 0a496f059c1e9d75c33cce4c1211d58422ba4f62 Mon Sep 17 00:00:00 2001
-From: Maarten de Vries <maarten+dnsmasq@m.de-vri.es>
-Date: Fri, 11 May 2018 23:20:58 +0100
-Subject: [PATCH 09/17] Do unsolicited RAs for interfaces which appear after
- dnsmasq startup.
-
-I noticed that dnsmasq often wasn't sending any unsolicited RAs for me.
-
-This turned out to happen when the interface (a bridge interface) wasn't
-created yet at the time dnsmasq started. When dnsmasq is started after
-the interface is created, it sends RAs as expected. I assume this also
-extends to other types of virtual interfaces that are created after
-dnsmasq starts.
-
-Digging into the source, it seems to be caused by a missing call to
-ra_start_unsolicited for non-template contexts in construct_worker from
-src/dhcp6.c. The attached patch adds that call, but only if the
-interface index or address changed to prevent doing fast RAs for no reason.
-
-I tested it on my own server and it appears to work as expected. When
-the interface is created and configured, dnsmasq does fast RAs for a
-while and then settles into slow RAs.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/dhcp6.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/src/dhcp6.c
-+++ b/src/dhcp6.c
-@@ -647,6 +647,13 @@ static int construct_worker(struct in6_a
- is_same_net6(local, &template->start6, template->prefix) &&
- is_same_net6(local, &template->end6, template->prefix))
- {
-+ /* First time found, do fast RA. */
-+ if (template->if_index != if_index || !IN6_ARE_ADDR_EQUAL(&template->local6, local))
-+ {
-+ ra_start_unsolicited(param->now, template);
-+ param->newone = 1;
-+ }
-+
- template->if_index = if_index;
- template->local6 = *local;
- }
+++ /dev/null
-From 1f1873aadd092a0fab505dd278a484d887ba0ec3 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 11 May 2018 23:38:23 +0100
-Subject: [PATCH 10/17] Log warning on very large cachesize config, instead of
- truncating it.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/dnsmasq.c | 6 +++++-
- src/option.c | 2 --
- 2 files changed, 5 insertions(+), 3 deletions(-)
-
---- a/src/dnsmasq.c
-+++ b/src/dnsmasq.c
-@@ -740,7 +740,11 @@ int main (int argc, char **argv)
- else
- {
- if (daemon->cachesize != 0)
-- my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
-+ {
-+ my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
-+ if (daemon->cachesize > 10000)
-+ my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
-+ }
- else
- my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
-
---- a/src/option.c
-+++ b/src/option.c
-@@ -2603,8 +2603,6 @@ static int one_opt(int option, char *arg
-
- if (size < 0)
- size = 0;
-- else if (size > 10000)
-- size = 10000;
-
- daemon->cachesize = size;
- }
+++ /dev/null
-From c488b68e75ee5304007eef37203c4fc10193d191 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Sat, 2 Jun 2018 13:06:00 +0100
-Subject: [PATCH 11/17] Handle standard and contructed dhcp-ranges on the same
- interface.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- CHANGELOG | 6 ++++++
- src/dhcp6.c | 29 +++++++++++++++++------------
- 2 files changed, 23 insertions(+), 12 deletions(-)
-
---- a/CHANGELOG
-+++ b/CHANGELOG
-@@ -23,6 +23,12 @@ version 2.80
- which packets should be dumped is given by the --dumpmask
- option.
-
-+ Handle the case of both standard and constructed dhcp-ranges on the
-+ same interface better. We don't now contruct a dhcp-range if there's
-+ already one specified. This allows the specified interface to
-+ have different parameters and avoids advertising the same
-+ prefix twice. Thanks to Luis Marsano for spotting this case.
-+
-
- version 2.79
- Fix parsing of CNAME arguments, which are confused by extra spaces.
---- a/src/dhcp6.c
-+++ b/src/dhcp6.c
-@@ -667,23 +667,28 @@ static int construct_worker(struct in6_a
- end6 = *local;
- setaddr6part(&end6, addr6part(&template->end6));
-
-+ /* If there's an absolute address context covering this address
-+ then don't contruct one as well. */
- for (context = daemon->dhcp6; context; context = context->next)
-- if ((context->flags & CONTEXT_CONSTRUCTED) &&
-+ if (!(context->flags & CONTEXT_TEMPLATE) &&
- IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
- IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
- {
-- int flags = context->flags;
-- context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
-- if (flags & CONTEXT_OLD)
-+ if (context->flags & CONTEXT_CONSTRUCTED)
- {
-- /* address went, now it's back */
-- log_context(AF_INET6, context);
-- /* fast RAs for a while */
-- ra_start_unsolicited(param->now, context);
-- param->newone = 1;
-- /* Add address to name again */
-- if (context->flags & CONTEXT_RA_NAME)
-- param->newname = 1;
-+ int cflags = context->flags;
-+ context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
-+ if (cflags & CONTEXT_OLD)
-+ {
-+ /* address went, now it's back */
-+ log_context(AF_INET6, context);
-+ /* fast RAs for a while */
-+ ra_start_unsolicited(param->now, context);
-+ param->newone = 1;
-+ /* Add address to name again */
-+ if (context->flags & CONTEXT_RA_NAME)
-+ param->newname = 1;
-+ }
- }
- break;
- }
+++ /dev/null
-From cc5cc8f1e0b4deaaea4cbefe677989b186c84837 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Sat, 2 Jun 2018 14:45:17 +0100
-Subject: [PATCH 12/17] Sane error message when pcap file header is wrong.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/dump.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/src/dump.c
-+++ b/src/dump.c
-@@ -64,9 +64,10 @@ void dump_init(void)
- die(_("cannot create %s: %s"), daemon->dump_file, EC_FILE);
- }
- else if ((daemon->dumpfd = open(daemon->dump_file, O_APPEND | O_RDWR)) == -1 ||
-- !read_write(daemon->dumpfd, (void *)&header, sizeof(header), 1) ||
-- header.magic_number != 0xa1b2c3d4)
-+ !read_write(daemon->dumpfd, (void *)&header, sizeof(header), 1))
- die(_("cannot access %s: %s"), daemon->dump_file, EC_FILE);
-+ else if (header.magic_number != 0xa1b2c3d4)
-+ die(_("bad header in %s"), daemon->dump_file, EC_FILE);
- else
- {
- /* count existing records */
+++ /dev/null
-From 090856c7e6d483bc4d7ec41f55208a9842769c45 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Sat, 2 Jun 2018 18:37:07 +0100
-Subject: [PATCH 13/17] Allow zone transfer in authoritative mode whenever
- auth-peer is specified.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- CHANGELOG | 4 ++++
- man/dnsmasq.8 | 6 +++++-
- src/auth.c | 5 +++--
- 3 files changed, 12 insertions(+), 3 deletions(-)
-
---- a/CHANGELOG
-+++ b/CHANGELOG
-@@ -29,6 +29,10 @@ version 2.80
- have different parameters and avoids advertising the same
- prefix twice. Thanks to Luis Marsano for spotting this case.
-
-+ Allow zone transfer in authoritative mode if auth-peer is specified,
-+ even if auth-sec-servers is not. Thanks to Raphaël Halimi for
-+ the suggestion.
-+
-
- version 2.79
- Fix parsing of CNAME arguments, which are confused by extra spaces.
---- a/man/dnsmasq.8
-+++ b/man/dnsmasq.8
-@@ -817,7 +817,11 @@ authoritative zones as dnsmasq.
- Specify the addresses of secondary servers which are allowed to
- initiate zone transfer (AXFR) requests for zones for which dnsmasq is
- authoritative. If this option is not given, then AXFR requests will be
--accepted from any secondary.
-+accepted from any secondary. Specifying
-+.B auth-peer
-+without
-+.B auth-sec-servers
-+enables zone transfer but does not advertise the secondary in NS records returned by dnsmasq.
- .TP
- .B --conntrack
- Read the Linux connection track mark associated with incoming DNS
---- a/src/auth.c
-+++ b/src/auth.c
-@@ -436,8 +436,9 @@ size_t answer_auth(struct dns_header *he
- if (sockaddr_isequal(peer_addr, &peers->addr))
- break;
-
-- /* Refuse all AXFR unless --auth-sec-servers is set */
-- if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)
-+ /* Refuse all AXFR unless --auth-sec-servers or auth-peers is set */
-+ if ((!daemon->secondary_forward_server && !daemon->auth_peers) ||
-+ (daemon->auth_peers && !peers))
- {
- if (peer_addr->sa.sa_family == AF_INET)
- inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
+++ /dev/null
-From 7dcca6c62211e60905e2252a185bede909391877 Mon Sep 17 00:00:00 2001
-From: Geert Stappers <stappers@stappers.nl>
-Date: Sat, 2 Jun 2018 18:54:04 +0100
-Subject: [PATCH 14/17] Warn about the impact of cache-size on performance.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- man/dnsmasq.8 | 2 +-
- man/es/dnsmasq.8 | 3 ++-
- man/fr/dnsmasq.8 | 3 ++-
- 3 files changed, 5 insertions(+), 3 deletions(-)
-
---- a/man/dnsmasq.8
-+++ b/man/dnsmasq.8
-@@ -692,7 +692,7 @@ will add 1.2.3.0/24 for both IPv4 and IP
-
- .TP
- .B \-c, --cache-size=<cachesize>
--Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
-+Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching. Note: huge cache size impacts performance.
- .TP
- .B \-N, --no-negcache
- Disable negative caching. Negative caching allows dnsmasq to remember
---- a/man/es/dnsmasq.8
-+++ b/man/es/dnsmasq.8
-@@ -478,7 +478,8 @@ la traza reversa dirección-a-nombre.
- .TP
- .B \-c, --cache-size=<tamaño de caché>
- Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres.
--Fijar el tamaño a cero deshabilita el caché.
-+Fijar el tamaño a cero deshabilita el caché. Nota: el gran tamaño de
-+caché afecta el rendimiento.
- .TP
- .B \-N, --no-negcache
- Deshabilitar caché negativo. El caché negativo le permite a dnsmasq
---- a/man/fr/dnsmasq.8
-+++ b/man/fr/dnsmasq.8
-@@ -666,7 +666,8 @@ différentes pourraient-être rencontré
- .TP
- .B \-c, --cache-size=<taille>
- Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms.
--Définir une valeur de zéro désactive le cache.
-+Définir une valeur de zéro désactive le cache. Remarque: la taille importante
-+du cache a un impact sur les performances.
- .TP
- .B \-N, --no-negcache
- Désactive le "cache négatif". Le "cache négatif" permet à Dnsmasq de se souvenir
+++ /dev/null
-From db0f488ea8f5ded7c57400c9108ec3c9367d75c5 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Thu, 7 Jun 2018 21:37:02 +0100
-Subject: [PATCH 15/17] Handle some corner cases in RA contructed interfaces
- with addresses changing interface.
-
-Thanks to Vladislav Grishenko for work on this.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/dhcp6.c | 16 ++++++++++------
- 1 file changed, 10 insertions(+), 6 deletions(-)
-
---- a/src/dhcp6.c
-+++ b/src/dhcp6.c
-@@ -640,7 +640,7 @@ static int construct_worker(struct in6_a
- return 0;
-
- for (template = daemon->dhcp6; template; template = template->next)
-- if (!(template->flags & CONTEXT_TEMPLATE))
-+ if (!(template->flags & (CONTEXT_TEMPLATE | CONTEXT_CONSTRUCTED)))
- {
- /* non-template entries, just fill in interface and local addresses */
- if (prefix <= template->prefix &&
-@@ -667,20 +667,23 @@ static int construct_worker(struct in6_a
- end6 = *local;
- setaddr6part(&end6, addr6part(&template->end6));
-
-- /* If there's an absolute address context covering this address
-- then don't contruct one as well. */
- for (context = daemon->dhcp6; context; context = context->next)
- if (!(context->flags & CONTEXT_TEMPLATE) &&
- IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
- IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
- {
-- if (context->flags & CONTEXT_CONSTRUCTED)
-+ /* If there's an absolute address context covering this address
-+ then don't construct one as well. */
-+ if (!(context->flags & CONTEXT_CONSTRUCTED))
-+ break;
-+
-+ if (context->if_index == if_index)
- {
- int cflags = context->flags;
- context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
- if (cflags & CONTEXT_OLD)
- {
-- /* address went, now it's back */
-+ /* address went, now it's back, and on the same interface */
- log_context(AF_INET6, context);
- /* fast RAs for a while */
- ra_start_unsolicited(param->now, context);
-@@ -688,9 +691,10 @@ static int construct_worker(struct in6_a
- /* Add address to name again */
- if (context->flags & CONTEXT_RA_NAME)
- param->newname = 1;
-+
-+ break;
- }
- }
-- break;
- }
-
- if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
+++ /dev/null
-From 05ff659a3c0d95be6d41fae755243988a1bb3387 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Tue, 12 Jun 2018 16:03:09 +0100
-Subject: [PATCH 16/17] Fix stupid infinite loop introduced by preceding
- commit.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/dhcp6.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/src/dhcp6.c
-+++ b/src/dhcp6.c
-@@ -692,8 +692,8 @@ static int construct_worker(struct in6_a
- if (context->flags & CONTEXT_RA_NAME)
- param->newname = 1;
-
-- break;
- }
-+ break;
- }
- }
-
+++ /dev/null
-From 51e4eeeb04b8dd8510ed267d580751525e77cb77 Mon Sep 17 00:00:00 2001
-From: Paul Maddock <Paul@whitefall.co.uk>
-Date: Tue, 12 Jun 2018 16:37:40 +0100
-Subject: [PATCH 17/17] Fix address-dependent domains for IPv6.
-
-Thanks to Paul Maddock for spotting this.
-It seems to have been broken forever.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- src/lease.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/src/lease.c
-+++ b/src/lease.c
-@@ -87,7 +87,7 @@ static int read_leases(time_t now, FILE
- if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
- {
- lease_set_iaid(lease, strtoul(s, NULL, 10));
-- domain = get_domain6((struct in6_addr *)lease->hwaddr);
-+ domain = get_domain6(&lease->addr6);
- }
- }
- #endif
+++ /dev/null
-From a997ca0da044719a0ce8a232d14da8b30022592b Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 29 Jun 2018 14:39:41 +0100
-Subject: [PATCH 18/18] Fix sometimes missing DNSSEC RRs when DNSSEC validation
- not enabled.
-
-Dnsmasq does pass on the do-bit, and return DNSSEC RRs, irrespective
-of of having DNSSEC validation compiled in or enabled.
-
-The thing to understand here is that the cache does not store all the
-DNSSEC RRs, and dnsmasq doesn't have the (very complex) logic required
-to determine the set of DNSSEC RRs required in an answer. Therefore if
-the client wants the DNSSEC RRs, the query can not be answered from
-the cache. When DNSSEC validation is enabled, any query with the
-do-bit set is never answered from the cache, unless the domain is
-known not to be signed: the query is always forwarded. This ensures
-that the DNSEC RRs are included.
-
-The same thing should be true when DNSSEC validation is not enabled,
-but there's a bug in the logic.
-
-line 1666 of src/rfc1035.c looks like this
-
- if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
-
-{ ...answer from cache ... }
-
-So local stuff (hosts, DHCP, ) get answered. If the do_bit is not set
-then the query is answered, and if the domain is known not to be
-signed, the query is answered.
-
-Unfortunately, if DNSSEC validation is not turned on then the
-F_DNSSECOK bit is not valid, and it's always zero, so the question
-always gets answered from the cache, even when the do-bit is set.
-
-This code should look like that at line 1468, dealing with PTR queries
-
- if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
- !do_bit ||
- (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
-
-where the F_DNSSECOK bit is only used when validation is enabled.
-
-Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
----
- CHANGELOG | 7 ++++++-
- src/rfc1035.c | 6 ++++--
- 2 files changed, 10 insertions(+), 3 deletions(-)
-
---- a/CHANGELOG
-+++ b/CHANGELOG
-@@ -33,7 +33,12 @@ version 2.80
- even if auth-sec-servers is not. Thanks to Raphaël Halimi for
- the suggestion.
-
--
-+ Fix bug which sometimes caused dnsmasq to wrongly return answers
-+ without DNSSEC RRs to queries with the do-bit set, but only when
-+ DNSSEC validation was not enabled.
-+ Thanks to Petr Menšík for spotting this.
-+
-+
- version 2.79
- Fix parsing of CNAME arguments, which are confused by extra spaces.
- Thanks to Diego Aguirre for spotting the bug.
---- a/src/rfc1035.c
-+++ b/src/rfc1035.c
-@@ -1663,7 +1663,9 @@ size_t answer_request(struct dns_header
- }
-
- /* If the client asked for DNSSEC don't use cached data. */
-- if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
-+ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
-+ !do_bit ||
-+ (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
- do
- {
- /* don't answer wildcard queries with data not from /etc/hosts
-@@ -1747,7 +1749,7 @@ size_t answer_request(struct dns_header
- {
- if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
- (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
-- ((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
-+ ((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
- {
- if (!(crecp->flags & F_DNSSECOK))
- sec_data = 0;
int main (int argc, char **argv)
{
int bind_fallback = 0;
-@@ -944,6 +1004,7 @@ int main (int argc, char **argv)
+@@ -949,6 +1009,7 @@ int main (int argc, char **argv)
set_dbus_listeners();
#endif
#ifdef HAVE_DHCP
if (daemon->dhcp || daemon->relay4)
{
-@@ -1074,6 +1135,8 @@ int main (int argc, char **argv)
+@@ -1079,6 +1140,8 @@ int main (int argc, char **argv)
check_dbus_listeners();
#endif
mostly_clean :
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
-@@ -1440,6 +1440,8 @@ void emit_dbus_signal(int action, struct
+@@ -1445,6 +1445,8 @@ void emit_dbus_signal(int action, struct
# endif
#endif