dnsmasq: update to dnsmasq 2.77test1

Bump to dnsmasq 2.77test1 - this includes a number of fixes since 2.76
and allows dropping of 2 LEDE carried patches.

Notable fix in rrfilter code when talking to Nominum's DNS servers
especially with DNSSEC.

A patch to switch dnsmasq back to 'soft fail' for SERVFAIL responses
from dns servers is also included.  This mean dnsmasq tries all
configured servers before giving up.

A 'localise queries' enhancement has also been backported (it will
appear in test2/rc'n') this is especially important if using the
recently imported to LEDE 'use dnsmasq standalone' feature 9525743c

I have been following dnsmasq HEAD ever since 2.76 release.
Compile & Run tested: ar71xx, Archer C7 v2

Tested-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>

Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
This commit is contained in:
Kevin Darbyshire-Bryant 2017-02-02 16:07:03 +00:00 committed by Jo-Philipp Wich
parent f9f6a21c81
commit 3bef96ef18
6 changed files with 145 additions and 257 deletions

View file

@ -8,12 +8,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dnsmasq
PKG_VERSION:=2.76
PKG_RELEASE:=8
PKG_VERSION:=2.77test1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq
PKG_HASH:=4b92698dee19ca0cb2a8f2e48f1d2dffd01a21eb15d1fbed4cf085630c8c9f96
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/test-releases
PKG_HASH:=be89f1ab7b5b85dc31a982e73f9e9b8a65da6b9dfbdef30eede5284a8f832105
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING

View file

@ -0,0 +1,99 @@
From d42d4706bbcce3b5a40ad778a5a356a997db6b34 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 2 Feb 2017 16:52:06 +0000
Subject: [PATCH] Make --localise-queries apply to names from
--interface-name.
---
CHANGELOG | 7 +++++++
man/dnsmasq.8 | 9 +++++----
src/rfc1035.c | 21 ++++++++++++++++++++-
3 files changed, 32 insertions(+), 5 deletions(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -58,6 +58,13 @@ version 2.77
this is Nominum's. Thanks to Dave Täht for spotting the
bug and assisting in the fix.
+ Fix the manpage which lied that only the primary address
+ of an interface is used by --interface-name.
+
+ Make --localise-queries apply to names from --interface-name.
+ Thanks to Kevin Darbyshire-Bryant and Eric Luehrsen
+ for pushing this.
+
version 2.76
Include 0.0.0.0/8 in DNS rebind checks. This range
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -289,8 +289,8 @@ option requires non-standard networking
under Linux. On other platforms it falls-back to --bind-interfaces mode.
.TP
.B \-y, --localise-queries
-Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was
-received. If a name in /etc/hosts has more than one address associated with
+Return answers to DNS queries from /etc/hosts and --interface-name which depend on the interface over which the query was
+received. If a name has more than one address associated with
it, and at least one of those addresses is on the same subnet as the
interface to which the query was sent, then return only the
address(es) on that subnet. This allows for a server to have multiple
@@ -604,7 +604,7 @@ given by the hex data, which may be of t
012345 or any mixture of these.
.TP
.B --interface-name=<name>,<interface>[/4|/6]
-Return a DNS record associating the name with the primary address on
+Return DNS records associating the name with the address(es) of
the given interface. This flag specifies an A or AAAA record for the given
name in the same way as an /etc/hosts line, except that the address is
not constant, but taken from the given interface. The interface may be
@@ -614,7 +614,8 @@ down, not configured or non-existent, an
matching PTR record is also created, mapping the interface address to
the name. More than one name may be associated with an interface
address by repeating the flag; in that case the first instance is used
-for the reverse address-to-name mapping.
+for the reverse address-to-name mapping. Note that a name used in
+--interface-name may not appear in /etc/hosts.
.TP
.B --synth-domain=<domain>,<address range>[,<prefix>]
Create artificial A/AAAA and PTR records for an address range. The
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1516,9 +1516,24 @@ size_t answer_request(struct dns_header
if (intr)
{
struct addrlist *addrlist;
- int gotit = 0;
+ int gotit = 0, localise = 0;
enumerate_interfaces(0);
+
+ /* See if a putative address is on the network from which we recieved
+ the query, is so we'll filter other answers. */
+ if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && type == T_A)
+ for (intr = daemon->int_names; intr; intr = intr->next)
+ if (hostname_isequal(name, intr->name))
+ for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
+#ifdef HAVE_IPV6
+ if (!(addrlist->flags & ADDRLIST_IPV6))
+#endif
+ if (is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask))
+ {
+ localise = 1;
+ break;
+ }
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
@@ -1528,6 +1543,10 @@ size_t answer_request(struct dns_header
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
#endif
{
+ if (localise &&
+ !is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask))
+ continue;
+
#ifdef HAVE_IPV6
if (addrlist->flags & ADDRLIST_REVONLY)
continue;

View file

@ -1,47 +0,0 @@
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -147,7 +147,7 @@ void dhcp_packet(time_t now, int pxe_fd)
ssize_t sz;
int iface_index = 0, unicast_dest = 0, is_inform = 0;
int rcvd_iface_index;
- struct in_addr iface_addr;
+ struct in_addr iface_addr, *addrp = NULL;
struct iface_param parm;
#ifdef HAVE_LINUX_NETWORK
struct arpreq arp_req;
@@ -277,11 +277,9 @@ void dhcp_packet(time_t now, int pxe_fd)
{
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
- iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
- else
{
- my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
- return;
+ addrp = &iface_addr;
+ iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
@@ -300,7 +298,7 @@ void dhcp_packet(time_t now, int pxe_fd)
parm.relay_local.s_addr = 0;
parm.ind = iface_index;
- if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
+ if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, NULL))
{
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
for a secondary */
@@ -320,6 +318,12 @@ void dhcp_packet(time_t now, int pxe_fd)
complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
}
+ if (!addrp)
+ {
+ my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
+ return;
+ }
+
if (!iface_enumerate(AF_INET, &parm, complete_context))
return;

View file

@ -44,67 +44,22 @@
(buffer = safe_malloc(BUFF_SZ)) &&
(ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 &&
(bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1))
@@ -168,62 +149,16 @@ static int new_add_to_ipset(const char *
}
-static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int remove)
-{
- socklen_t size;
- struct ip_set_req_adt_get {
- unsigned op;
- unsigned version;
- union {
- char name[IPSET_MAXNAMELEN];
- uint16_t index;
- } set;
- char typename[IPSET_MAXNAMELEN];
- } req_adt_get;
- struct ip_set_req_adt {
- unsigned op;
- uint16_t index;
- uint32_t ip;
- } req_adt;
-
- if (strlen(setname) >= sizeof(req_adt_get.set.name))
- {
- errno = ENAMETOOLONG;
- return -1;
- }
-
- req_adt_get.op = 0x10;
- req_adt_get.version = 3;
- strcpy(req_adt_get.set.name, setname);
- size = sizeof(req_adt_get);
- if (getsockopt(ipset_sock, SOL_IP, 83, &req_adt_get, &size) < 0)
- return -1;
- req_adt.op = remove ? 0x102 : 0x101;
- req_adt.index = req_adt_get.set.index;
- req_adt.ip = ntohl(ipaddr->addr.addr4.s_addr);
- if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0)
- return -1;
-
- return 0;
-}
-
-
-
int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove)
{
int af = AF_INET;
#ifdef HAVE_IPV6
@@ -217,17 +198,10 @@ int add_to_ipset(const char *setname, co
if (flags & F_IPV6)
- {
{
af = AF_INET6;
- /* old method only supports IPv4 */
- if (old_kernel)
- return -1;
- }
- {
- errno = EAFNOSUPPORT ;
- ret = -1;
- }
}
#endif
- return old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
+ return new_add_to_ipset(setname, ipaddr, af, remove);
}
- if (ret != -1)
- ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
+ ret = new_add_to_ipset(setname, ipaddr, af, remove);
#endif
if (ret == -1)
my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno));

View file

@ -1,149 +0,0 @@
From f6bea86c78ba9efbd01da3dd2fb18764ec806290 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
Date: Wed, 7 Sep 2016 09:35:07 +0100
Subject: [PATCH] dnsmasq: compile time option NO_ID
Some consider it good practice to obscure software version numbers to
clients. Compiling with -DNO_ID removes the *.bind info structure.
This includes: version, author, copyright, cachesize, cache insertions,
evictions, misses & hits, auth & servers.
Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
---
src/cache.c | 2 ++
src/config.h | 5 +++++
src/dnsmasq.h | 4 ++++
src/option.c | 8 ++++++--
src/rfc1035.c | 3 ++-
5 files changed, 19 insertions(+), 3 deletions(-)
--- a/src/cache.c
+++ b/src/cache.c
@@ -1290,6 +1290,7 @@ void cache_add_dhcp_entry(char *host_nam
}
#endif
+#ifndef NO_ID
int cache_make_stat(struct txt_record *t)
{
static char *buff = NULL;
@@ -1385,6 +1386,7 @@ int cache_make_stat(struct txt_record *t
*buff = len;
return 1;
}
+#endif
/* There can be names in the cache containing control chars, don't
mess up logging or open security holes. */
--- a/src/config.h
+++ b/src/config.h
@@ -120,6 +120,8 @@ HAVE_LOOP
HAVE_INOTIFY
use the Linux inotify facility to efficiently re-read configuration files.
+NO_ID
+ Don't report *.bind CHAOS info to clients.
NO_IPV6
NO_TFTP
NO_DHCP
@@ -434,6 +436,9 @@ static char *compile_opts =
"no-"
#endif
"DNSSEC "
+#ifdef NO_ID
+"no-ID "
+#endif
#ifndef HAVE_LOOP
"no-"
#endif
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -286,6 +286,7 @@ struct naptr {
struct naptr *next;
};
+#ifndef NO_ID
#define TXT_STAT_CACHESIZE 1
#define TXT_STAT_INSERTS 2
#define TXT_STAT_EVICTIONS 3
@@ -293,6 +294,7 @@ struct naptr {
#define TXT_STAT_HITS 5
#define TXT_STAT_AUTH 6
#define TXT_STAT_SERVERS 7
+#endif
struct txt_record {
char *name;
@@ -1078,7 +1080,9 @@ void cache_add_dhcp_entry(char *host_nam
struct in_addr a_record_from_hosts(char *name, time_t now);
void cache_unhash_dhcp(void);
void dump_cache(time_t now);
+#ifndef NO_ID
int cache_make_stat(struct txt_record *t);
+#endif
char *cache_get_name(struct crec *crecp);
char *cache_get_cname_target(struct crec *crecp);
struct crec *cache_enumerate(int init);
--- a/src/option.c
+++ b/src/option.c
@@ -657,7 +657,8 @@ static int atoi_check8(char *a, int *res
return 1;
}
#endif
-
+
+#ifndef NO_ID
static void add_txt(char *name, char *txt, int stat)
{
struct txt_record *r = opt_malloc(sizeof(struct txt_record));
@@ -670,13 +671,14 @@ static void add_txt(char *name, char *tx
*(r->txt) = len;
memcpy((r->txt)+1, txt, len);
}
-
+
r->stat = stat;
r->name = opt_string_alloc(name);
r->next = daemon->txt;
daemon->txt = r;
r->class = C_CHAOS;
}
+#endif
static void do_usage(void)
{
@@ -4515,6 +4517,7 @@ void read_opts(int argc, char **argv, ch
daemon->soa_expiry = SOA_EXPIRY;
daemon->max_port = MAX_PORT;
+#ifndef NO_ID
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
add_txt("authors.bind", "Simon Kelley", 0);
add_txt("copyright.bind", COPYRIGHT, 0);
@@ -4527,6 +4530,7 @@ void read_opts(int argc, char **argv, ch
add_txt("auth.bind", NULL, TXT_STAT_AUTH);
#endif
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
+#endif
while (1)
{
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1264,6 +1264,7 @@ size_t answer_request(struct dns_header
unsigned long ttl = daemon->local_ttl;
int ok = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
+#ifndef NO_ID
/* Dynamically generate stat record */
if (t->stat != 0)
{
@@ -1271,7 +1272,7 @@ size_t answer_request(struct dns_header
if (!cache_make_stat(t))
ok = 0;
}
-
+#endif
if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
ttl, NULL,
T_TXT, t->class, "t", t->len, t->txt))

View file

@ -0,0 +1,30 @@
From 94a8815892f538b334d640012eebcafc2c7fa284 Mon Sep 17 00:00:00 2001
From: Martin Wetterwald <martin.wetterwald@corp.ovh.com>
Date: Thu, 27 Oct 2016 12:17:03 +0200
Subject: [PATCH] Consider SERVFAIL as a non-successful response
Treat Servfail as a recoverable error instead of a hard error.
A misconfigured dns forwarder upstream can return a Servfail faster than
a correctly configured one.
In the case of a dnssec misbehaving, it will misbehave on all correctly
configured upstreams. In the case of a normal DNS query, the original
behavior of dnsmasq here was more robust.
---
src/forward.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/src/forward.c
+++ b/src/forward.c
@@ -853,7 +853,8 @@ void reply_query(int fd, int family, tim
we get a good reply from another server. Kill it when we've
had replies from all to avoid filling the forwarding table when
everything is broken */
- if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
+ if (forward->forwardall == 0 || --forward->forwardall == 1
+ || (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
{
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;