From 3bef96ef18a6fb20401313dfa6e88057d56b16ad Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Thu, 2 Feb 2017 16:07:03 +0000 Subject: [PATCH] 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 Signed-off-by: Kevin Darbyshire-Bryant --- package/network/services/dnsmasq/Makefile | 8 +- ...ise-queries-apply-to-interface-names.patch | 99 ++++++++++++ .../100-fix-dhcp-no-address-warning.patch | 47 ------ .../110-ipset-remove-old-kernel-support.patch | 69 ++------ ...20-dnsmasq-compile-time-option-NO_ID.patch | 149 ------------------ .../patches/220-try-all-servers-on-fail.patch | 30 ++++ 6 files changed, 145 insertions(+), 257 deletions(-) create mode 100644 package/network/services/dnsmasq/patches/010-localise-queries-apply-to-interface-names.patch delete mode 100644 package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch delete mode 100644 package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch create mode 100644 package/network/services/dnsmasq/patches/220-try-all-servers-on-fail.patch diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index a6689d1b9f..17643a8786 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -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 diff --git a/package/network/services/dnsmasq/patches/010-localise-queries-apply-to-interface-names.patch b/package/network/services/dnsmasq/patches/010-localise-queries-apply-to-interface-names.patch new file mode 100644 index 0000000000..2a77727a24 --- /dev/null +++ b/package/network/services/dnsmasq/patches/010-localise-queries-apply-to-interface-names.patch @@ -0,0 +1,99 @@ +From d42d4706bbcce3b5a40ad778a5a356a997db6b34 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +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=,[/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=,
[,] + 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; diff --git a/package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch b/package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch deleted file mode 100644 index 5fc62ffab3..0000000000 --- a/package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch +++ /dev/null @@ -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; - diff --git a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch b/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch index 61b09d5b2c..88e334b0fc 100644 --- a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch +++ b/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch @@ -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)); diff --git a/package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch b/package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch deleted file mode 100644 index 152d1a7fa9..0000000000 --- a/package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch +++ /dev/null @@ -1,149 +0,0 @@ -From f6bea86c78ba9efbd01da3dd2fb18764ec806290 Mon Sep 17 00:00:00 2001 -From: Kevin Darbyshire-Bryant -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 ---- - 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, ""); -+#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)) diff --git a/package/network/services/dnsmasq/patches/220-try-all-servers-on-fail.patch b/package/network/services/dnsmasq/patches/220-try-all-servers-on-fail.patch new file mode 100644 index 0000000000..501eefebb5 --- /dev/null +++ b/package/network/services/dnsmasq/patches/220-try-all-servers-on-fail.patch @@ -0,0 +1,30 @@ +From 94a8815892f538b334d640012eebcafc2c7fa284 Mon Sep 17 00:00:00 2001 +From: Martin Wetterwald +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; +