dnsmasq: bump to dnsmasq v2.80test3
Refresh patches Upstream commits since last bump: 3b6eb19 Log DNSSEC trust anchors at startup. f3e5787 Trivial comment change. c851c69 Log failure to confirm an address in DHCPv6. a3bd7e7 Fix missing fatal errors when parsing some command-line/config options. ab5ceaf Document the --help option in the french manual 1f2f69d Fix recurrent minor spelling mistake in french manual f361b39 Fix some mistakes in french translation of the manual eb1fe15 When replacing cache entries, preserve CNAMES which target them. Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
This commit is contained in:
parent
2a598bbaa3
commit
1e93ef8498
20 changed files with 6 additions and 1565 deletions
|
@ -8,12 +8,12 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=dnsmasq
|
PKG_NAME:=dnsmasq
|
||||||
PKG_VERSION:=2.80test2
|
PKG_VERSION:=2.80test3
|
||||||
PKG_RELEASE:=5
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||||
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/test-releases
|
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/test-releases
|
||||||
PKG_HASH:=e731666094699afcbad947f89f7f8afbf92e5ddc3c915459d4936159d81116f0
|
PKG_HASH:=af9f6fd13e0d6c5a68059bcf8634c2784c0533017fd48fbaf59cd2955342d301
|
||||||
|
|
||||||
PKG_LICENSE:=GPL-2.0
|
PKG_LICENSE:=GPL-2.0
|
||||||
PKG_LICENSE_FILES:=COPYING
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
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))
|
|
|
@ -1,184 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,587 +0,0 @@
|
||||||
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);
|
|
|
@ -1,22 +0,0 @@
|
||||||
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. */
|
|
|
@ -1,87 +0,0 @@
|
||||||
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 */
|
|
|
@ -1,100 +0,0 @@
|
||||||
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;
|
|
|
@ -1,41 +0,0 @@
|
||||||
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
|
|
|
@ -1,44 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
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 */
|
|
|
@ -1,55 +0,0 @@
|
||||||
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);
|
|
|
@ -1,47 +0,0 @@
|
||||||
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
|
|
|
@ -1,64 +0,0 @@
|
||||||
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))))
|
|
|
@ -1,23 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
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
|
|
|
@ -1,87 +0,0 @@
|
||||||
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;
|
|
|
@ -74,7 +74,7 @@
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
int bind_fallback = 0;
|
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();
|
set_dbus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->relay4)
|
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();
|
check_dbus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@
|
||||||
mostly_clean :
|
mostly_clean :
|
||||||
--- a/src/dnsmasq.h
|
--- a/src/dnsmasq.h
|
||||||
+++ b/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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue