From: Michael Tremer Date: Thu, 9 Jul 2015 10:31:32 +0000 (+0200) Subject: Remove dnsmasq patches X-Git-Tag: v2.17-core93~36 X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=commitdiff_plain;h=0f5f0fc10c2878f367049ba3eb038d30405fe29a Remove dnsmasq patches These are not applied any more because dnsmasq was updated to the latest release version. Signed-off-by: Michael Tremer --- diff --git a/src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch b/src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch deleted file mode 100644 index 3c67b64170..0000000000 --- a/src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch +++ /dev/null @@ -1,23 +0,0 @@ -From f2658275b25ebfe691cdcb9fede85a3088cca168 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Thu, 25 Sep 2014 21:51:25 +0100 -Subject: [PATCH 001/113] Add newline at the end of example config file. - ---- - dnsmasq.conf.example | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example -index 83924fc4a9b4..6b00bd34fbb5 100644 ---- a/dnsmasq.conf.example -+++ b/dnsmasq.conf.example -@@ -645,4 +645,4 @@ - #conf-dir=/etc/dnsmasq.d,.bak - - # Include all files in a directory which end in .conf --#conf-dir=/etc/dnsmasq.d/*.conf -\ No newline at end of file -+#conf-dir=/etc/dnsmasq.d/*.conf --- -2.1.0 - diff --git a/src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch b/src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch deleted file mode 100644 index 090892dd12..0000000000 --- a/src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 00cd9d551998307225312fd21f761cfa8868bd2c Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Thu, 2 Oct 2014 21:44:21 +0100 -Subject: [PATCH 002/113] crash at startup when an empty suffix is supplied to - --conf-dir - ---- - CHANGELOG | 6 ++++++ - src/option.c | 38 +++++++++++++++++++++++--------------- - 2 files changed, 29 insertions(+), 15 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 768e2aaca42a..13ab41c05fc3 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -1,3 +1,9 @@ -+version 2.73 -+ Fix crash at startup when an empty suffix is supplied to -+ --conf-dir, also trivial memory leak. Thanks to -+ Tomas Hozza for spotting this. -+ -+ - version 2.72 - Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. - -diff --git a/src/option.c b/src/option.c -index 45d8875fb7f9..b08e98e16f84 100644 ---- a/src/option.c -+++ b/src/option.c -@@ -1474,22 +1474,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma - for (arg = comma; arg; arg = comma) - { - comma = split(arg); -- li = opt_malloc(sizeof(struct list)); -- if (*arg == '*') -+ if (strlen(arg) != 0) - { -- li->next = match_suffix; -- match_suffix = li; -- /* Have to copy: buffer is overwritten */ -- li->suffix = opt_string_alloc(arg+1); -- } -- else -- { -- li->next = ignore_suffix; -- ignore_suffix = li; -- /* Have to copy: buffer is overwritten */ -- li->suffix = opt_string_alloc(arg); -+ li = opt_malloc(sizeof(struct list)); -+ if (*arg == '*') -+ { -+ li->next = match_suffix; -+ match_suffix = li; -+ /* Have to copy: buffer is overwritten */ -+ li->suffix = opt_string_alloc(arg+1); -+ } -+ else -+ { -+ li->next = ignore_suffix; -+ ignore_suffix = li; -+ /* Have to copy: buffer is overwritten */ -+ li->suffix = opt_string_alloc(arg); -+ } - } -- }; -+ } - - if (!(dir_stream = opendir(directory))) - die(_("cannot access directory %s: %s"), directory, EC_FILE); -@@ -1555,7 +1558,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma - free(ignore_suffix->suffix); - free(ignore_suffix); - } -- -+ for(; match_suffix; match_suffix = li) -+ { -+ li = match_suffix->next; -+ free(match_suffix->suffix); -+ free(match_suffix); -+ } - break; - } - --- -2.1.0 - diff --git a/src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch b/src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch deleted file mode 100644 index 1fcb04122e..0000000000 --- a/src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 6ac3bc0452a74e16e3d620a0757b0f8caab182ec Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Fri, 3 Oct 2014 08:48:11 +0100 -Subject: [PATCH 003/113] Debian build fixes for kFreeBSD - ---- - src/tables.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/tables.c b/src/tables.c -index 834f11944cd0..dcdef794c4d2 100644 ---- a/src/tables.c -+++ b/src/tables.c -@@ -20,6 +20,10 @@ - - #if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK) - -+#ifndef __FreeBSD__ -+#include -+#endif -+ - #include - #include - -@@ -136,7 +140,7 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, - return -1; - } - -- if (rc = pfr_add_tables(&table, 1, &n, 0)) -+ if ((rc = pfr_add_tables(&table, 1, &n, 0))) - { - my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"), - pfr_strerror(errno),rc); --- -2.1.0 - diff --git a/src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch b/src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch deleted file mode 100644 index f734fbc85a..0000000000 --- a/src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch +++ /dev/null @@ -1,68 +0,0 @@ -From e9828b6f66b22ce8873f8d30a773137d1aef1b92 Mon Sep 17 00:00:00 2001 -From: Karl Vogel -Date: Fri, 3 Oct 2014 21:45:15 +0100 -Subject: [PATCH 004/113] Set conntrack mark before connect() call. - -SO_MARK has to be done before issuing the connect() call on the -TCP socket. ---- - src/forward.c | 36 ++++++++++++++++++------------------ - 1 file changed, 18 insertions(+), 18 deletions(-) - -diff --git a/src/forward.c b/src/forward.c -index 4895efeba89a..2cf29eba6e26 100644 ---- a/src/forward.c -+++ b/src/forward.c -@@ -1796,6 +1796,24 @@ unsigned char *tcp_request(int confd, time_t now, - if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1) - continue; - -+#ifdef HAVE_CONNTRACK -+ /* Copy connection mark of incoming query to outgoing connection. */ -+ if (option_bool(OPT_CONNTRACK)) -+ { -+ unsigned int mark; -+ struct all_addr local; -+#ifdef HAVE_IPV6 -+ if (local_addr->sa.sa_family == AF_INET6) -+ local.addr.addr6 = local_addr->in6.sin6_addr; -+ else -+#endif -+ local.addr.addr4 = local_addr->in.sin_addr; -+ -+ if (get_incoming_mark(&peer_addr, &local, 1, &mark)) -+ setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int)); -+ } -+#endif -+ - if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) || - connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)) - { -@@ -1820,24 +1838,6 @@ unsigned char *tcp_request(int confd, time_t now, - size = new_size; - } - #endif -- --#ifdef HAVE_CONNTRACK -- /* Copy connection mark of incoming query to outgoing connection. */ -- if (option_bool(OPT_CONNTRACK)) -- { -- unsigned int mark; -- struct all_addr local; --#ifdef HAVE_IPV6 -- if (local_addr->sa.sa_family == AF_INET6) -- local.addr.addr6 = local_addr->in6.sin6_addr; -- else --#endif -- local.addr.addr4 = local_addr->in.sin_addr; -- -- if (get_incoming_mark(&peer_addr, &local, 1, &mark)) -- setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int)); -- } --#endif - } - - *length = htons(size); --- -2.1.0 - diff --git a/src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch b/src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch deleted file mode 100644 index ef70ae3f25..0000000000 --- a/src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 17b475912f6a4e72797a543dad59d4d5dde6bb1b Mon Sep 17 00:00:00 2001 -From: Daniel Collins -Date: Fri, 3 Oct 2014 21:58:43 +0100 -Subject: [PATCH 005/113] Fix typo in new Dbus code. - -Simon's fault. ---- - src/dbus.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/dbus.c b/src/dbus.c -index 15fed906bd90..a2a94dc85dac 100644 ---- a/src/dbus.c -+++ b/src/dbus.c -@@ -426,7 +426,7 @@ static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name) - } - else - { -- my_syslog(LOG_INFO, "Disabling --$s option from D-Bus", name); -+ my_syslog(LOG_INFO, "Disabling --%s option from D-Bus", name); - reset_option_bool(flag); - } - --- -2.1.0 - diff --git a/src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch b/src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch deleted file mode 100644 index c6dc31e610..0000000000 --- a/src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 3d9d2dd0018603a2ae4b9cd65ac6ff959f4fd8c7 Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Mon, 6 Oct 2014 10:46:48 +0100 -Subject: [PATCH 006/113] Fit example conf file typo. - ---- - dnsmasq.conf.example | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example -index 6b00bd34fbb5..1bd305dbdbad 100644 ---- a/dnsmasq.conf.example -+++ b/dnsmasq.conf.example -@@ -645,4 +645,4 @@ - #conf-dir=/etc/dnsmasq.d,.bak - - # Include all files in a directory which end in .conf --#conf-dir=/etc/dnsmasq.d/*.conf -+#conf-dir=/etc/dnsmasq.d/,*.conf --- -2.1.0 - diff --git a/src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch b/src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch deleted file mode 100644 index bc24281381..0000000000 --- a/src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch +++ /dev/null @@ -1,107 +0,0 @@ -From b9ff5c8f435173cfa616e3c398bdc089ef690a07 Mon Sep 17 00:00:00 2001 -From: Vladislav Grishenko -Date: Mon, 6 Oct 2014 14:34:24 +0100 -Subject: [PATCH 007/113] Improve RFC-compliance when unable to supply - addresses in DHCPv6 - -While testing https://github.com/sbyx/odhcp6c client I have noticed it -permanently crashes after startup. - -The reason was it (odhcp6c) doesn't expect empty IA options in ADVERTISE -message without any suboptions. - -Despite this validation bug of odhcp6c, dnsmasq should not generate -ADVERTISE messages with IA if there's nothing to advert per RFC 3315 -17.2.2: - - If the server will not assign any addresses to any IAs in a - - subsequent Request from the client, the server MUST send an Advertise - - message to the client that includes only a Status Code option with - - code NoAddrsAvail and a status message for the user, a Server - - Identifier option with the server's DUID, and a Client Identifier - - option with the client's DUID. - -Meanwhile it's need to add status code for every IA in REPLY message per -RFC3315 18.2.1: - - If the server cannot assign any addresses to an IA in the message - from the client, the server MUST include the IA in the Reply message - with no addresses in the IA and a Status Code option in the IA - containing status code NoAddrsAvail. - -So, I've changed the logic to skip IA completely from ADVERTISE messages and -to add NoAddrsAvail subcode into IA of REPLY messages. - -As for overhead, yes, I believe it's ok to return NoAddrsAvail twice in IA -and in global section for compatibility with all old and new clients. ---- - src/rfc3315.c | 27 +++++++++++++++++++++++++-- - 1 file changed, 25 insertions(+), 2 deletions(-) - -diff --git a/src/rfc3315.c b/src/rfc3315.c -index 5ebf09d50ac1..ddb390bf1136 100644 ---- a/src/rfc3315.c -+++ b/src/rfc3315.c -@@ -691,6 +691,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - #endif - - o = build_ia(state, &t1cntr); -+ if (address_assigned) -+ address_assigned = 2; - - for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) - { -@@ -781,6 +783,27 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - address_assigned = 1; - } - -+ if (address_assigned != 1) -+ { -+ /* If the server will not assign any addresses to any IAs in a -+ subsequent Request from the client, the server MUST send an Advertise -+ message to the client that doesn't include any IA options. */ -+ if (!state->lease_allocate) -+ { -+ save_counter(o); -+ continue; -+ } -+ -+ /* If the server cannot assign any addresses to an IA in the message -+ from the client, the server MUST include the IA in the Reply message -+ with no addresses in the IA and a Status Code option in the IA -+ containing status code NoAddrsAvail. */ -+ o1 = new_opt6(OPTION6_STATUS_CODE); -+ put_opt6_short(DHCP6NOADDRS); -+ put_opt6_string(_("address unavailable")); -+ end_opt6(o1); -+ } -+ - end_ia(t1cntr, min_time, 0); - end_opt6(o); - } -@@ -806,7 +829,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - put_opt6_short(DHCP6NOADDRS); - put_opt6_string(_("no addresses available")); - end_opt6(o1); -- log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available")); -+ log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available")); - } - - break; -@@ -862,7 +885,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - { - /* Static range, not configured. */ - o1 = new_opt6(OPTION6_STATUS_CODE); -- put_opt6_short(DHCP6UNSPEC); -+ put_opt6_short(DHCP6NOADDRS); - put_opt6_string(_("address unavailable")); - end_opt6(o1); - } --- -2.1.0 - diff --git a/src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch b/src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch deleted file mode 100644 index 47f0ea6f58..0000000000 --- a/src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 98906275a02ae260fe3f82133bd79054f8315f06 Mon Sep 17 00:00:00 2001 -From: Hans Dedecker -Date: Tue, 9 Dec 2014 22:22:53 +0000 -Subject: [PATCH 008/113] Fix conntrack with --bind-interfaces - -Make sure dst_addr is assigned the correct address in receive_query when OPTNOWILD is -enabled so the assigned mark can be correctly retrieved and set in forward_query when -conntrack is enabled. - -Signed-off-by: Hans Dedecker ---- - src/forward.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/forward.c b/src/forward.c -index 2cf29eba6e26..408a179a20f4 100644 ---- a/src/forward.c -+++ b/src/forward.c -@@ -1048,7 +1048,7 @@ void receive_query(struct listener *listen, time_t now) - /* packet buffer overwritten */ - daemon->srv_save = NULL; - -- dst_addr_4.s_addr = 0; -+ dst_addr_4.s_addr = dst_addr.addr.addr4.s_addr = 0; - netmask.s_addr = 0; - - if (option_bool(OPT_NOWILD) && listen->iface) -@@ -1057,7 +1057,7 @@ void receive_query(struct listener *listen, time_t now) - - if (listen->family == AF_INET) - { -- dst_addr_4 = listen->iface->addr.in.sin_addr; -+ dst_addr_4 = dst_addr.addr.addr4 = listen->iface->addr.in.sin_addr; - netmask = listen->iface->netmask; - } - } --- -2.1.0 - diff --git a/src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch b/src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch deleted file mode 100644 index 3cefd02fca..0000000000 --- a/src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch +++ /dev/null @@ -1,257 +0,0 @@ -From 193de4abf59e49c6b70d54cfe9720fcb95ca2f71 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Wed, 10 Dec 2014 17:32:16 +0000 -Subject: [PATCH 009/113] Use inotify instead of polling on Linux. - -This should solve problems people are seeing when a file changes -twice within a second and thus is missed for polling. ---- - Makefile | 2 +- - bld/Android.mk | 2 +- - src/dnsmasq.c | 25 ++++++++++++-- - src/dnsmasq.h | 11 ++++++- - src/inotify.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 137 insertions(+), 5 deletions(-) - create mode 100644 src/inotify.c - -diff --git a/Makefile b/Makefile -index 58a7975f60b5..c340f1c7b59a 100644 ---- a/Makefile -+++ b/Makefile -@@ -69,7 +69,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \ - dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ - helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \ - dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \ -- domain.o dnssec.o blockdata.o tables.o loop.o -+ domain.o dnssec.o blockdata.o tables.o loop.o inotify.o - - hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ - dns-protocol.h radv-protocol.h ip6addr.h -diff --git a/bld/Android.mk b/bld/Android.mk -index d855094eb264..d627796e8edc 100644 ---- a/bld/Android.mk -+++ b/bld/Android.mk -@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.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 -+ loop.c inotify.c - - LOCAL_MODULE := dnsmasq - -diff --git a/src/dnsmasq.c b/src/dnsmasq.c -index f4a89fc38183..bf2e25a55780 100644 ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -315,9 +315,15 @@ int main (int argc, char **argv) - if (daemon->port != 0) - { - cache_init(); -+ - #ifdef HAVE_DNSSEC - blockdata_init(); - #endif -+ -+#ifdef HAVE_LINUX_NETWORK -+ if (!option_bool(OPT_NO_POLL)) -+ inotify_dnsmasq_init(); -+#endif - } - - if (option_bool(OPT_DBUS)) -@@ -793,6 +799,11 @@ int main (int argc, char **argv) - - pid = getpid(); - -+#ifdef HAVE_LINUX_NETWORK -+ /* Using inotify, have to select a resolv file at startup */ -+ poll_resolv(1, 0, now); -+#endif -+ - while (1) - { - int maxfd = -1; -@@ -862,11 +873,16 @@ int main (int argc, char **argv) - #if defined(HAVE_LINUX_NETWORK) - FD_SET(daemon->netlinkfd, &rset); - bump_maxfd(daemon->netlinkfd, &maxfd); -+ if (daemon->port != 0 && !option_bool(OPT_NO_POLL)) -+ { -+ FD_SET(daemon->inotifyfd, &rset); -+ bump_maxfd(daemon->inotifyfd, &maxfd); -+ } - #elif defined(HAVE_BSD_NETWORK) - FD_SET(daemon->routefd, &rset); - bump_maxfd(daemon->routefd, &maxfd); - #endif -- -+ - FD_SET(piperead, &rset); - bump_maxfd(piperead, &maxfd); - -@@ -929,6 +945,10 @@ int main (int argc, char **argv) - route_sock(); - #endif - -+#ifdef HAVE_LINUX_NETWORK -+ if (daemon->port != 0 && !option_bool(OPT_NO_POLL) && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check()) -+ poll_resolv(1, 1, now); -+#else - /* Check for changes to resolv files once per second max. */ - /* Don't go silent for long periods if the clock goes backwards. */ - if (daemon->last_resolv == 0 || -@@ -941,7 +961,8 @@ int main (int argc, char **argv) - poll_resolv(0, daemon->last_resolv != 0, now); - daemon->last_resolv = now; - } -- -+#endif -+ - if (FD_ISSET(piperead, &rset)) - async_event(piperead, now); - -diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index e74b15a5459a..ebb6b957812f 100644 ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -541,6 +541,10 @@ struct resolvc { - int is_default, logged; - time_t mtime; - char *name; -+#ifdef HAVE_LINUX_NETWORK -+ int wd; /* inotify watch descriptor */ -+ char *file; /* pointer to file part if path */ -+#endif - }; - - /* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */ -@@ -998,7 +1002,7 @@ extern struct daemon { - /* DHCP state */ - int dhcpfd, helperfd, pxefd; - #if defined(HAVE_LINUX_NETWORK) -- int netlinkfd; -+ int netlinkfd, inotifyfd; - #elif defined(HAVE_BSD_NETWORK) - int dhcp_raw_fd, dhcp_icmp_fd, routefd; - #endif -@@ -1469,3 +1473,8 @@ void loop_send_probes(); - int detect_loop(char *query, int type); - #endif - -+/* inotify.c */ -+#ifdef HAVE_LINUX_NETWORK -+void inotify_dnsmasq_init(); -+int inotify_check(void); -+#endif -diff --git a/src/inotify.c b/src/inotify.c -new file mode 100644 -index 000000000000..a0223443d6b6 ---- /dev/null -+++ b/src/inotify.c -@@ -0,0 +1,102 @@ -+/* dnsmasq is Copyright (c) 2000-2014 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 . -+*/ -+ -+#include "dnsmasq.h" -+#include -+ -+#ifdef HAVE_LINUX_NETWORK -+ -+/* the strategy is to set a inotify on the directories containing -+ resolv files, for any files in the directory which are close-write -+ or moved into the directory. -+ -+ When either of those happen, we look to see if the file involved -+ is actually a resolv-file, and if so, call poll-resolv with -+ the "force" argument, to ensure it's read. -+ -+ This adds one new error condition: the directories containing -+ all specified resolv-files must exist at start-up, even if the actual -+ files don't. -+*/ -+ -+static char *inotify_buffer; -+#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1) -+ -+void inotify_dnsmasq_init() -+{ -+ struct resolvc *res; -+ -+ inotify_buffer = safe_malloc(INOTIFY_SZ); -+ -+ daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); -+ -+ if (daemon->inotifyfd == -1) -+ die(_("failed to create inotify: %s"), NULL, EC_MISC); -+ -+ for (res = daemon->resolv_files; res; res = res->next) -+ { -+ char *d = strrchr(res->name, '/'); -+ -+ if (!d) -+ die(_("resolv-file %s not an absolute path"), res->name, EC_MISC); -+ -+ *d = 0; /* make ->name just directory */ -+ res->wd = inotify_add_watch(daemon->inotifyfd, res->name, IN_CLOSE_WRITE | IN_MOVED_TO); -+ res->file = d+1; /* pointer to filename */ -+ -+ if (res->wd == -1 && errno == ENOENT) -+ die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); -+ -+ *d = '/'; /* restore name */ -+ -+ if (res->wd == -1) -+ die(_("failed to create inotify for %s: %s"), res->name, EC_MISC); -+ } -+} -+ -+int inotify_check(void) -+{ -+ int hit = 0; -+ -+ while (1) -+ { -+ int rc; -+ char *p; -+ struct resolvc *res; -+ struct inotify_event *in; -+ -+ while ((rc = read(daemon->inotifyfd, inotify_buffer, INOTIFY_SZ)) == -1 && errno == EINTR); -+ -+ if (rc <= 0) -+ break; -+ -+ for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len) -+ { -+ in = (struct inotify_event*)p; -+ -+ for (res = daemon->resolv_files; res; res = res->next) -+ if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0) -+ hit = 1; -+ } -+ } -+ -+ return hit; -+} -+ -+#endif -+ -+ -+ --- -2.1.0 - diff --git a/src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch b/src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch deleted file mode 100644 index 35c405b767..0000000000 --- a/src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 857973e6f7e0a3d03535a9df7f9373fd7a0b65cc Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Mon, 15 Dec 2014 15:58:13 +0000 -Subject: [PATCH 010/113] Teach the new inotify code about symlinks. - ---- - src/inotify.c | 43 +++++++++++++++++++++++++++---------------- - 1 file changed, 27 insertions(+), 16 deletions(-) - -diff --git a/src/inotify.c b/src/inotify.c -index a0223443d6b6..960bf5efb41f 100644 ---- a/src/inotify.c -+++ b/src/inotify.c -@@ -41,29 +41,40 @@ void inotify_dnsmasq_init() - - inotify_buffer = safe_malloc(INOTIFY_SZ); - -- daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); - -+ daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); -+ - if (daemon->inotifyfd == -1) - die(_("failed to create inotify: %s"), NULL, EC_MISC); -- -+ - for (res = daemon->resolv_files; res; res = res->next) - { -- char *d = strrchr(res->name, '/'); -- -- if (!d) -- die(_("resolv-file %s not an absolute path"), res->name, EC_MISC); -- -- *d = 0; /* make ->name just directory */ -- res->wd = inotify_add_watch(daemon->inotifyfd, res->name, IN_CLOSE_WRITE | IN_MOVED_TO); -- res->file = d+1; /* pointer to filename */ -- -- if (res->wd == -1 && errno == ENOENT) -- die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); -+ char *d = NULL, *path; - -- *d = '/'; /* restore name */ -+ if (!(path = realpath(res->name, NULL))) -+ { -+ /* realpath will fail if the file doesn't exist, but -+ dnsmasq copes with missing files, so fall back -+ and assume that symlinks are not in use in that case. */ -+ if (errno == ENOENT) -+ path = res->name; -+ else -+ die(_("cannot cannonicalise resolv-file %s: %s"), res->name, EC_MISC); -+ } - -- if (res->wd == -1) -- die(_("failed to create inotify for %s: %s"), res->name, EC_MISC); -+ if ((d = strrchr(path, '/'))) -+ { -+ *d = 0; /* make path just directory */ -+ res->wd = inotify_add_watch(daemon->inotifyfd, path, IN_CLOSE_WRITE | IN_MOVED_TO); -+ res->file = d+1; /* pointer to filename */ -+ *d = '/'; -+ -+ if (res->wd == -1 && errno == ENOENT) -+ die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); -+ -+ if (res->wd == -1) -+ die(_("failed to create inotify for %s: %s"), res->name, EC_MISC); -+ } - } - } - --- -2.1.0 - diff --git a/src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch b/src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch deleted file mode 100644 index d1766f58d3..0000000000 --- a/src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 800c5cc1e7438818fd80f08c2d472df249a6942d Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Mon, 15 Dec 2014 17:50:15 +0000 -Subject: [PATCH 011/113] Remove floor on EDNS0 packet size with DNSSEC. - ---- - CHANGELOG | 6 +++++- - src/dnsmasq.c | 5 ----- - 2 files changed, 5 insertions(+), 6 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 13ab41c05fc3..68252924e743 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -2,7 +2,11 @@ version 2.73 - Fix crash at startup when an empty suffix is supplied to - --conf-dir, also trivial memory leak. Thanks to - Tomas Hozza for spotting this. -- -+ -+ Remove floor of 4096 on advertised EDNS0 packet size when -+ DNSSEC in use, the original rationale for this has long gone. -+ Thanks to Anders Kaseorg for spotting this. -+ - - version 2.72 - Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. -diff --git a/src/dnsmasq.c b/src/dnsmasq.c -index bf2e25a55780..5c7750d365fa 100644 ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -87,11 +87,6 @@ int main (int argc, char **argv) - - if (daemon->edns_pktsz < PACKETSZ) - daemon->edns_pktsz = PACKETSZ; --#ifdef HAVE_DNSSEC -- /* Enforce min packet big enough for DNSSEC */ -- if (option_bool(OPT_DNSSEC_VALID) && daemon->edns_pktsz < EDNS_PKTSZ) -- daemon->edns_pktsz = EDNS_PKTSZ; --#endif - - daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ? - daemon->edns_pktsz : DNSMASQ_PACKETSZ; --- -2.1.0 - diff --git a/src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch b/src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch deleted file mode 100644 index 5fe1dfb597..0000000000 --- a/src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch +++ /dev/null @@ -1,27 +0,0 @@ -From ad946d555dce44eb690c7699933b6ff40ab85bb6 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Mon, 15 Dec 2014 17:52:22 +0000 -Subject: [PATCH 012/113] CHANGELOG re. inotify. - ---- - CHANGELOG | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/CHANGELOG b/CHANGELOG -index 68252924e743..9174b0bd75dc 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -7,6 +7,10 @@ version 2.73 - DNSSEC in use, the original rationale for this has long gone. - Thanks to Anders Kaseorg for spotting this. - -+ Use inotify for checking on updates to /etc/resolv.conf and -+ friends under Linux. This fixes race conditions when the files are -+ updated rapidly and saves CPU by noy polling. -+ - - version 2.72 - Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. --- -2.1.0 - diff --git a/src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch b/src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch deleted file mode 100644 index 284b5cc4f0..0000000000 --- a/src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 3ad3f3bbd4ee716a7d2fb1e115cf89bd1b1a5de9 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 16 Dec 2014 18:25:17 +0000 -Subject: [PATCH 013/113] Fix breakage of --domain=,,local - ---- - CHANGELOG | 4 ++++ - src/option.c | 18 ++++++++++++++++-- - 2 files changed, 20 insertions(+), 2 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 9174b0bd75dc..9e6c7aa4fd68 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -10,6 +10,10 @@ version 2.73 - Use inotify for checking on updates to /etc/resolv.conf and - friends under Linux. This fixes race conditions when the files are - updated rapidly and saves CPU by noy polling. -+ -+ Fix breakage of --domain=,,local - only reverse -+ queries were intercepted. THis appears to have been broken -+ since 2.69. Thanks to Josh Stone for finding the bug. - - - version 2.72 -diff --git a/src/option.c b/src/option.c -index b08e98e16f84..209fa6976609 100644 ---- a/src/option.c -+++ b/src/option.c -@@ -1941,10 +1941,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma - else - { - /* generate the equivalent of -- local=// - local=/xxx.yyy.zzz.in-addr.arpa/ */ - struct server *serv = add_rev4(new->start, msize); - serv->flags |= SERV_NO_ADDR; -+ -+ /* local=// */ -+ serv = opt_malloc(sizeof(struct server)); -+ memset(serv, 0, sizeof(struct server)); -+ serv->domain = d; -+ serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; -+ serv->next = daemon->servers; -+ daemon->servers = serv; - } - } - } -@@ -1978,10 +1985,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma - else - { - /* generate the equivalent of -- local=// - local=/xxx.yyy.zzz.ip6.arpa/ */ - struct server *serv = add_rev6(&new->start6, msize); - serv->flags |= SERV_NO_ADDR; -+ -+ /* local=// */ -+ serv = opt_malloc(sizeof(struct server)); -+ memset(serv, 0, sizeof(struct server)); -+ serv->domain = d; -+ serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; -+ serv->next = daemon->servers; -+ daemon->servers = serv; - } - } - } --- -2.1.0 - diff --git a/src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch b/src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch deleted file mode 100644 index 65030e9e4c..0000000000 --- a/src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch +++ /dev/null @@ -1,27 +0,0 @@ -From bd9520b7ade7098ee423acc38965376aa57feb07 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 16 Dec 2014 20:41:29 +0000 -Subject: [PATCH 014/113] Remove redundant IN6_IS_ADDR_ULA(a) macro defn. - ---- - src/network.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/src/network.c b/src/network.c -index 5067007c5cbc..99419f57951e 100644 ---- a/src/network.c -+++ b/src/network.c -@@ -16,10 +16,6 @@ - - #include "dnsmasq.h" - --#ifndef IN6_IS_ADDR_ULA --#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000)) --#endif -- - #ifdef HAVE_LINUX_NETWORK - - int indextoname(int fd, int index, char *name) --- -2.1.0 - diff --git a/src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch b/src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch deleted file mode 100644 index 8aca09feff..0000000000 --- a/src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 476693678e778886b64d0b56e27eb7695cbcca99 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Wed, 17 Dec 2014 12:41:56 +0000 -Subject: [PATCH 015/113] Eliminate IPv6 privacy addresses from - --interface-name answers. - ---- - CHANGELOG | 5 +++++ - src/auth.c | 4 ++++ - src/dnsmasq.h | 1 + - src/network.c | 12 ++++++++---- - src/rfc1035.c | 17 ++++++++++------- - 5 files changed, 28 insertions(+), 11 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 9e6c7aa4fd68..01f5208ec006 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -14,6 +14,11 @@ version 2.73 - Fix breakage of --domain=,,local - only reverse - queries were intercepted. THis appears to have been broken - since 2.69. Thanks to Josh Stone for finding the bug. -+ -+ Eliminate IPv6 privacy addresses and deprecated addresses from -+ the answers given by --interface-name. Note that reverse queries -+ (ie looking for names, given addresses) are not affected. -+ Thanks to Michael Gorbach for the suggestion. - - - version 2.72 -diff --git a/src/auth.c b/src/auth.c -index dd46566ec2cc..a327f16d8c0b 100644 ---- a/src/auth.c -+++ b/src/auth.c -@@ -363,6 +363,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n - if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype && - (local_query || filter_zone(zone, flag, &addrlist->addr))) - { -+#ifdef HAVE_IPV6 -+ if (addrlist->flags & ADDRLIST_REVONLY) -+ continue; -+#endif - found = 1; - log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL); - if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, -diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index ebb6b957812f..1dd61c5edba3 100644 ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -318,6 +318,7 @@ struct ds_config { - - #define ADDRLIST_LITERAL 1 - #define ADDRLIST_IPV6 2 -+#define ADDRLIST_REVONLY 4 - - struct addrlist { - struct all_addr addr; -diff --git a/src/network.c b/src/network.c -index 99419f57951e..14d2af2ce313 100644 ---- a/src/network.c -+++ b/src/network.c -@@ -236,7 +236,7 @@ struct iface_param { - }; - - static int iface_allowed(struct iface_param *param, int if_index, char *label, -- union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad) -+ union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags) - { - struct irec *iface; - int mtu = 0, loopback; -@@ -388,6 +388,10 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, - { - al->addr.addr.addr6 = addr->in6.sin6_addr; - al->flags = ADDRLIST_IPV6; -+ /* Privacy addresses and addresses still undergoing DAD and deprecated addresses -+ don't appear in forward queries, but will in reverse ones. */ -+ if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE))) -+ al->flags |= ADDRLIST_REVONLY; - } - #endif - } -@@ -399,7 +403,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, - for (iface = daemon->interfaces; iface; iface = iface->next) - if (sockaddr_isequal(&iface->addr, addr)) - { -- iface->dad = dad; -+ iface->dad = !!(iface_flags & IFACE_TENTATIVE); - iface->found = 1; /* for garbage collection */ - return 1; - } -@@ -474,7 +478,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, - iface->dhcp_ok = dhcp_ok; - iface->dns_auth = auth_dns; - iface->mtu = mtu; -- iface->dad = dad; -+ iface->dad = !!(iface_flags & IFACE_TENTATIVE); - iface->found = 1; - iface->done = iface->multicast_done = iface->warned = 0; - iface->index = if_index; -@@ -519,7 +523,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix, - else - addr.in6.sin6_scope_id = 0; - -- return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE)); -+ return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags); - } - #endif - -diff --git a/src/rfc1035.c b/src/rfc1035.c -index 8a7d2608dac5..bdeb3fb10e68 100644 ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1923,14 +1923,17 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, - for (intr = daemon->int_names; intr; intr = intr->next) - if (hostname_isequal(name, intr->name)) - { -- ans = 1; -- if (!dryrun) -- { -- -- for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) -+ for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) - #ifdef HAVE_IPV6 -- if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type) -+ if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type) - #endif -+ { -+#ifdef HAVE_IPV6 -+ if (addrlist->flags & ADDRLIST_REVONLY) -+ continue; -+#endif -+ ans = 1; -+ if (!dryrun) - { - gotit = 1; - log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL); -@@ -1939,7 +1942,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, - type == T_A ? "4" : "6", &addrlist->addr)) - anscount++; - } -- } -+ } - } - - if (!dryrun && !gotit) --- -2.1.0 - diff --git a/src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch b/src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch deleted file mode 100644 index df1268fcdc..0000000000 --- a/src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 3267804598047bd1781cab91508d1bc516e5ddbb Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Wed, 17 Dec 2014 20:38:20 +0000 -Subject: [PATCH 016/113] Tweak field width in cache dump to avoid truncating - IPv6 addresses. - ---- - src/cache.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/cache.c b/src/cache.c -index 2c3a49887053..f9e1d31e8c99 100644 ---- a/src/cache.c -+++ b/src/cache.c -@@ -1411,7 +1411,7 @@ void dump_cache(time_t now) - *a = 0; - if (strlen(n) == 0 && !(cache->flags & F_REVERSE)) - n = ""; -- p += sprintf(p, "%-40.40s ", n); -+ p += sprintf(p, "%-30.30s ", n); - if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache)) - a = cache_get_cname_target(cache); - #ifdef HAVE_DNSSEC -@@ -1454,7 +1454,7 @@ void dump_cache(time_t now) - else if (cache->flags & F_DNSKEY) - t = "K"; - #endif -- p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s ", a, t, -+ p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t, - cache->flags & F_FORWARD ? "F" : " ", - cache->flags & F_REVERSE ? "R" : " ", - cache->flags & F_IMMORTAL ? "I" : " ", --- -2.1.0 - diff --git a/src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch b/src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch deleted file mode 100644 index 81a39be305..0000000000 --- a/src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 094b5c3d904bae9aeb3206d9f3b8348926b84975 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Sun, 21 Dec 2014 16:11:52 +0000 -Subject: [PATCH 017/113] Fix crash in DNSSEC code when attempting to verify - large RRs. - ---- - CHANGELOG | 3 +++ - src/dnssec.c | 27 +++++++++++++++++++-------- - 2 files changed, 22 insertions(+), 8 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 01f5208ec006..956b71a151db 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -19,6 +19,9 @@ version 2.73 - the answers given by --interface-name. Note that reverse queries - (ie looking for names, given addresses) are not affected. - Thanks to Michael Gorbach for the suggestion. -+ -+ Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids -+ for the bug report. - - - version 2.72 -diff --git a/src/dnssec.c b/src/dnssec.c -index 69bfc29e355f..3208ac701149 100644 ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -456,16 +456,27 @@ static u16 *get_desc(int type) - - /* Return bytes of canonicalised rdata, when the return value is zero, the remaining - data, pointed to by *p, should be used raw. */ --static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, -+static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen, - unsigned char **p, u16 **desc) - { - int d = **desc; - -- (*desc)++; -- - /* No more data needs mangling */ - if (d == (u16)-1) -- return 0; -+ { -+ /* If there's more data than we have space for, just return what fits, -+ we'll get called again for more chunks */ -+ if (end - *p > bufflen) -+ { -+ memcpy(buff, *p, bufflen); -+ *p += bufflen; -+ return bufflen; -+ } -+ -+ return 0; -+ } -+ -+ (*desc)++; - - if (d == 0 && extract_name(header, plen, p, buff, 1, 0)) - /* domain-name, canonicalise */ -@@ -560,7 +571,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int - if (left1 != 0) - memmove(buff1, buff1 + len1 - left1, left1); - -- if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0) -+ if ((len1 = get_rdata(header, plen, end1, buff1 + left1, MAXDNAME - left1, &p1, &dp1)) == 0) - { - quit = 1; - len1 = end1 - p1; -@@ -571,7 +582,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int - if (left2 != 0) - memmove(buff2, buff2 + len2 - left2, left2); - -- if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0) -+ if ((len2 = get_rdata(header, plen, end2, buff2 + left2, MAXDNAME - left2, &p2, &dp2)) == 0) - { - quit = 1; - len2 = end2 - p2; -@@ -808,7 +819,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in - /* canonicalise rdata and calculate length of same, use name buffer as workspace */ - cp = p; - dp = rr_desc; -- for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg); -+ for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg); - len += end - cp; - len = htons(len); - hash->update(ctx, 2, (unsigned char *)&len); -@@ -816,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in - /* Now canonicalise again and digest. */ - cp = p; - dp = rr_desc; -- while ((seg = get_rdata(header, plen, end, name, &cp, &dp))) -+ while ((seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp))) - hash->update(ctx, seg, (unsigned char *)name); - if (cp != end) - hash->update(ctx, end - cp, cp); --- -2.1.0 - diff --git a/src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch b/src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch deleted file mode 100644 index 6f41cf2e70..0000000000 --- a/src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch +++ /dev/null @@ -1,99 +0,0 @@ -From cbc652423403e3cef00e00240f6beef713142246 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Sun, 21 Dec 2014 21:21:53 +0000 -Subject: [PATCH 018/113] Make caching work for CNAMEs pointing to A/AAAA - records shadowed in /etc/hosts - -If the answer to an upstream query is a CNAME which points to an -A/AAAA record which also exists in /etc/hosts and friends, then -caching is suppressed, to avoid inconsistent answers. This is -now modified to allow caching when the upstream and local A/AAAA -records have the same value. ---- - src/cache.c | 34 +++++++++++++++++++++++++--------- - 1 file changed, 25 insertions(+), 9 deletions(-) - -diff --git a/src/cache.c b/src/cache.c -index f9e1d31e8c99..ff1ca6f1c352 100644 ---- a/src/cache.c -+++ b/src/cache.c -@@ -322,7 +322,7 @@ static int is_expired(time_t now, struct crec *crecp) - return 1; - } - --static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) -+static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) - { - /* Scan and remove old entries. - If (flags & F_FORWARD) then remove any forward entries for name and any expired -@@ -331,8 +331,8 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign - entries in the whole cache. - If (flags == 0) remove any expired entries in the whole cache. - -- In the flags & F_FORWARD case, the return code is valid, and returns zero if the -- name exists in the cache as a HOSTS or DHCP entry (these are never deleted) -+ In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer -+ to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted) - - We take advantage of the fact that hash chains have stuff in the order ,, - so that when we hit an entry which isn't reverse and is immortal, we're done. */ -@@ -361,7 +361,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign - (((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS)))) - { - if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) -- return 0; -+ return crecp; - *up = crecp->hash_next; - cache_unlink(crecp); - cache_free(crecp); -@@ -378,7 +378,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign - crecp->addr.sig.type_covered == addr->addr.dnssec.type)) - { - if (crecp->flags & F_CONFIG) -- return 0; -+ return crecp; - *up = crecp->hash_next; - cache_unlink(crecp); - cache_free(crecp); -@@ -423,7 +423,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign - up = &crecp->hash_next; - } - -- return 1; -+ return NULL; - } - - /* Note: The normal calling sequence is -@@ -471,10 +471,26 @@ struct crec *cache_insert(char *name, struct all_addr *addr, - return NULL; - - /* First remove any expired entries and entries for the name/address we -- are currently inserting. Fail if we attempt to delete a name from -- /etc/hosts or DHCP. */ -- if (!cache_scan_free(name, addr, now, flags)) -+ are currently inserting. */ -+ if ((new = cache_scan_free(name, addr, now, flags))) - { -+ /* We're trying to insert a record over one from -+ /etc/hosts or DHCP, or other config. If the -+ existing record is for an A or AAAA and -+ the record we're trying to insert is the same, -+ just drop the insert, but don't error the whole process. */ -+ if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD)) -+ { -+ if ((flags & F_IPV4) && (new->flags & F_IPV4) && -+ new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr) -+ return new; -+#ifdef HAVE_IPV6 -+ else if ((flags & F_IPV6) && (new->flags & F_IPV6) && -+ IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6)) -+ return new; -+#endif -+ } -+ - insert_error = 1; - return NULL; - } --- -2.1.0 - diff --git a/src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch b/src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch deleted file mode 100644 index 1755c3a55d..0000000000 --- a/src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch +++ /dev/null @@ -1,365 +0,0 @@ -From fbc5205702c7f6f431d9f1043c553d7fb62ddfdb Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 23 Dec 2014 15:46:08 +0000 -Subject: [PATCH 019/113] Fix problems validating NSEC3 and wildcards. - ---- - src/dnssec.c | 253 ++++++++++++++++++++++++++++++----------------------------- - 1 file changed, 128 insertions(+), 125 deletions(-) - -diff --git a/src/dnssec.c b/src/dnssec.c -index 3208ac701149..9350d3e8c963 100644 ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -615,6 +615,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int - Return code: - STAT_SECURE if it validates. - STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion. -+ (In this case *wildcard_out points to the "body" of the wildcard within name.) - STAT_NO_SIG no RRsigs found. - STAT_INSECURE RRset empty. - STAT_BOGUS signature is wrong, bad packet. -@@ -625,8 +626,8 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int - - name is unchanged on exit. keyname is used as workspace and trashed. - */ --static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, -- int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in) -+static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, -+ char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in) - { - static unsigned char **rrset = NULL, **sigs = NULL; - static int rrset_sz = 0, sig_sz = 0; -@@ -798,8 +799,16 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in - { - int k; - for (k = name_labels - labels; k != 0; k--) -- while (*name_start != '.' && *name_start != 0) -- name_start++; -+ { -+ while (*name_start != '.' && *name_start != 0) -+ name_start++; -+ if (k != 1) -+ name_start++; -+ } -+ -+ if (wildcard_out) -+ *wildcard_out = name_start+1; -+ - name_start--; - *name_start = '*'; - } -@@ -974,7 +983,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch - if (recp1->addr.ds.keylen == (int)hash->digest_size && - (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) && - memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 && -- validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag) == STAT_SECURE) -+ validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, NULL, key, rdlen - 4, algo, keytag) == STAT_SECURE) - { - valid = 1; - break; -@@ -1443,11 +1452,88 @@ static int base32_decode(char *in, unsigned char *out) - return p - out; - } - -+static int check_nsec3_coverage(struct dns_header *header, size_t plen, int digest_len, unsigned char *digest, int type, -+ char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count) -+{ -+ int i, hash_len, salt_len, base32_len, rdlen; -+ unsigned char *p, *psave; -+ -+ for (i = 0; i < nsec_count; i++) -+ if ((p = nsecs[i])) -+ { -+ if (!extract_name(header, plen, &p, workspace1, 1, 0) || -+ !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) -+ return 0; -+ -+ p += 8; /* class, type, TTL */ -+ GETSHORT(rdlen, p); -+ psave = p; -+ p += 4; /* algo, flags, iterations */ -+ salt_len = *p++; /* salt_len */ -+ p += salt_len; /* salt */ -+ hash_len = *p++; /* p now points to next hashed name */ -+ -+ if (!CHECK_LEN(header, p, plen, hash_len)) -+ return 0; -+ -+ if (digest_len == base32_len && hash_len == base32_len) -+ { -+ int rc = memcmp(workspace2, digest, digest_len); -+ -+ if (rc == 0) -+ { -+ /* We found an NSEC3 whose hashed name exactly matches the query, so -+ we just need to check the type map. p points to the RR data for the record. */ -+ -+ int offset = (type & 0xff) >> 3; -+ int mask = 0x80 >> (type & 0x07); -+ -+ p += hash_len; /* skip next-domain hash */ -+ rdlen -= p - psave; -+ -+ if (!CHECK_LEN(header, p, plen, rdlen)) -+ return 0; -+ -+ while (rdlen >= 2) -+ { -+ if (p[0] == type >> 8) -+ { -+ /* Does the NSEC3 say our type exists? */ -+ if (offset < p[1] && (p[offset+2] & mask) != 0) -+ return STAT_BOGUS; -+ -+ break; /* finshed checking */ -+ } -+ -+ rdlen -= p[1]; -+ p += p[1]; -+ } -+ -+ return 1; -+ } -+ else if (rc <= 0) -+ { -+ /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash, -+ wrap around case, name-hash falls between NSEC3 name-hash and end */ -+ if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0) -+ return 1; -+ } -+ else -+ { -+ /* wrap around case, name falls between start and next domain name */ -+ if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0) -+ return 1; -+ } -+ } -+ } -+ return 0; -+} -+ - static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, -- char *workspace1, char *workspace2, char *name, int type) -+ char *workspace1, char *workspace2, char *name, int type, char *wildname) - { - unsigned char *salt, *p, *digest; -- int digest_len, i, iterations, salt_len, hash_len, base32_len, algo = 0; -+ int digest_len, i, iterations, salt_len, base32_len, algo = 0; - struct nettle_hash const *hash; - char *closest_encloser, *next_closest, *wildcard; - -@@ -1520,7 +1606,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns - if (!(hash = hash_find("sha1"))) - return STAT_BOGUS; - -- /* Now, we need the "closest encloser NSEC3" */ -+ if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0) -+ return STAT_BOGUS; -+ -+ if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) -+ return STAT_SECURE; -+ -+ /* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3" -+ or an answer inferred from a wildcard record. */ - closest_encloser = name; - next_closest = NULL; - -@@ -1529,6 +1622,9 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns - if (*closest_encloser == '.') - closest_encloser++; - -+ if (wildname && hostname_isequal(closest_encloser, wildname)) -+ break; -+ - if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0) - return STAT_BOGUS; - -@@ -1551,127 +1647,33 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns - } - while ((closest_encloser = strchr(closest_encloser, '.'))); - -- /* No usable NSEC3s */ -- if (i == nsec_count) -+ if (!closest_encloser) - return STAT_BOGUS; - -- if (!next_closest) -- { -- /* We found an NSEC3 whose hashed name exactly matches the query, so -- Now we just need to check the type map. p points to the RR data for the record. */ -- int rdlen; -- unsigned char *psave; -- int offset = (type & 0xff) >> 3; -- int mask = 0x80 >> (type & 0x07); -- -- p += 8; /* class, type, TTL */ -- GETSHORT(rdlen, p); -- psave = p; -- p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */ -- hash_len = *p++; -- if (!CHECK_LEN(header, p, plen, hash_len)) -- return STAT_BOGUS; /* bad packet */ -- p += hash_len; -- rdlen -= p - psave; -- -- while (rdlen >= 2) -- { -- if (!CHECK_LEN(header, p, plen, rdlen)) -- return STAT_BOGUS; -- -- if (p[0] == type >> 8) -- { -- /* Does the NSEC3 say our type exists? */ -- if (offset < p[1] && (p[offset+2] & mask) != 0) -- return STAT_BOGUS; -- -- break; /* finshed checking */ -- } -- -- rdlen -= p[1]; -- p += p[1]; -- } -- -- return STAT_SECURE; -- } -- - /* Look for NSEC3 that proves the non-existence of the next-closest encloser */ - if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0) - return STAT_BOGUS; - -- for (i = 0; i < nsec_count; i++) -- if ((p = nsecs[i])) -- { -- if (!extract_name(header, plen, &p, workspace1, 1, 0) || -- !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) -- return STAT_BOGUS; -- -- p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */ -- hash_len = *p++; /* p now points to next hashed name */ -- -- if (!CHECK_LEN(header, p, plen, hash_len)) -- return STAT_BOGUS; -- -- if (digest_len == base32_len && hash_len == base32_len) -- { -- if (memcmp(workspace2, digest, digest_len) <= 0) -- { -- /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash, -- wrap around case, name-hash falls between NSEC3 name-hash and end */ -- if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0) -- return STAT_SECURE; -- } -- else -- { -- /* wrap around case, name falls between start and next domain name */ -- if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0) -- return STAT_SECURE; -- } -- } -- } -- -- /* Finally, check that there's no seat of wildcard synthesis */ -- if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest) -- return STAT_BOGUS; -- -- wildcard--; -- *wildcard = '*'; -- -- if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) -+ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) - return STAT_BOGUS; - -- for (i = 0; i < nsec_count; i++) -- if ((p = nsecs[i])) -- { -- if (!extract_name(header, plen, &p, workspace1, 1, 0) || -- !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) -- return STAT_BOGUS; -- -- p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */ -- hash_len = *p++; /* p now points to next hashed name */ -- -- if (!CHECK_LEN(header, p, plen, hash_len)) -- return STAT_BOGUS; -- -- if (digest_len == base32_len && hash_len == base32_len) -- { -- if (memcmp(workspace2, digest, digest_len) <= 0) -- { -- /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash, -- wrap around case, name-hash falls between NSEC3 name-hash and end */ -- if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0) -- return STAT_SECURE; -- } -- else -- { -- /* wrap around case, name falls between start and next domain name */ -- if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0) -- return STAT_SECURE; -- } -- } -- } -+ /* Finally, check that there's no seat of wildcard synthesis */ -+ if (!wildname) -+ { -+ if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest) -+ return STAT_BOGUS; -+ -+ wildcard--; -+ *wildcard = '*'; -+ -+ if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) -+ return STAT_BOGUS; -+ -+ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) -+ return STAT_BOGUS; -+ } - -- return STAT_BOGUS; -+ return STAT_SECURE; - } - - /* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */ -@@ -1792,8 +1794,9 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch - struct all_addr a; - struct blockdata *key; - struct crec *crecp; -- -- rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0); -+ char *wildname; -+ -+ rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0); - - if (rc == STAT_SECURE_WILDCARD) - { -@@ -1807,7 +1810,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch - if (nsec_type == T_NSEC) - rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1); - else -- rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1); -+ rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, wildname); - - if (rc != STAT_SECURE) - return rc; -@@ -1933,7 +1936,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch - if (nsec_type == T_NSEC) - return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype); - else -- return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype); -+ return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL); - } - - /* Chase the CNAME chain in the packet until the first record which _doesn't validate. -@@ -1980,7 +1983,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char - return STAT_INSECURE; - - /* validate CNAME chain, return if insecure or need more data */ -- rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, 0, 0, 0); -+ rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, NULL, 0, 0, 0); - if (rc != STAT_SECURE) - { - if (rc == STAT_NO_SIG) --- -2.1.0 - diff --git a/src/patches/dnsmasq/0020-Initialise-return-value.patch b/src/patches/dnsmasq/0020-Initialise-return-value.patch deleted file mode 100644 index 2dd2f26589..0000000000 --- a/src/patches/dnsmasq/0020-Initialise-return-value.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 83d2ed09fc0216b567d7fb2197e4ff3eae150b0d Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 23 Dec 2014 18:42:38 +0000 -Subject: [PATCH 020/113] Initialise return value. - ---- - src/dnssec.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/src/dnssec.c b/src/dnssec.c -index 9350d3e8c963..ed8cf893bad2 100644 ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -637,10 +637,13 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in - struct crec *crecp = NULL; - int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag; - u16 *rr_desc = get_desc(type); -- -+ -+ if (wildcard_out) -+ *wildcard_out = NULL; -+ - if (!(p = skip_questions(header, plen))) - return STAT_BOGUS; -- -+ - name_labels = count_labels(name); /* For 4035 5.3.2 check */ - - /* look for RRSIGs for this RRset and get pointers to each RR in the set. */ --- -2.1.0 - diff --git a/src/patches/dnsmasq/0021-Add-ignore-address-option.patch b/src/patches/dnsmasq/0021-Add-ignore-address-option.patch deleted file mode 100644 index 7ff57afd7e..0000000000 --- a/src/patches/dnsmasq/0021-Add-ignore-address-option.patch +++ /dev/null @@ -1,192 +0,0 @@ -From 32fc6dbe03569d70dd394420ceb73532cf303c33 Mon Sep 17 00:00:00 2001 -From: Glen Huang -Date: Sat, 27 Dec 2014 15:28:12 +0000 -Subject: [PATCH 021/113] Add --ignore-address option. - ---- - CHANGELOG | 8 ++++++++ - man/dnsmasq.8 | 6 ++++++ - src/dnsmasq.h | 3 ++- - src/forward.c | 4 ++++ - src/option.c | 18 +++++++++++++++--- - src/rfc1035.c | 37 +++++++++++++++++++++++++++++++++++++ - 6 files changed, 72 insertions(+), 4 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 956b71a151db..2b6356bcfb02 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -22,6 +22,14 @@ version 2.73 - - Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids - for the bug report. -+ -+ Add --ignore-address option. Ignore replies to A-record -+ queries which include the specified address. No error is -+ generated, dnsmasq simply continues to listen for another -+ reply. This is useful to defeat blocking strategies which -+ rely on quickly supplying a forged answer to a DNS -+ request for certain domains, before the correct answer can -+ arrive. Thanks to Glen Huang for the patch. - - - version 2.72 -diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 -index 0b8e04f0a897..4236ba307df3 100644 ---- a/man/dnsmasq.8 -+++ b/man/dnsmasq.8 -@@ -293,6 +293,12 @@ an advertising web page in response to queries for unregistered names, - instead of the correct NXDOMAIN response. This option tells dnsmasq to - fake the correct response when it sees this behaviour. As at Sept 2003 - the IP address being returned by Verisign is 64.94.110.11 -+.TP -+.B \-B, --ignore-address= -+Ignore replies to A-record queries which include the specified address. -+No error is generated, dnsmasq simply continues to listen for another reply. -+This is useful to defeat blocking strategies which rely on quickly supplying a -+forged answer to a DNS request for certain domain, before the correct answer can arrive. - .TP - .B \-f, --filterwin2k - Later versions of windows make periodic DNS requests which don't get sensible answers from -diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index 1dd61c5edba3..7bc982ddf73c 100644 ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -930,7 +930,7 @@ extern struct daemon { - char *runfile; - char *lease_change_command; - struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces; -- struct bogus_addr *bogus_addr; -+ struct bogus_addr *bogus_addr, *ignore_addr; - struct server *servers; - struct ipsets *ipsets; - int log_fac; /* log facility */ -@@ -1093,6 +1093,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, - time_t now, int *ad_reqd, int *do_bit); - int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, - struct bogus_addr *addr, time_t now); -+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr); - unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, - size_t *len, unsigned char **p, int *is_sign); - int check_for_local_domain(char *name, time_t now); -diff --git a/src/forward.c b/src/forward.c -index 408a179a20f4..f28c7d51f708 100644 ---- a/src/forward.c -+++ b/src/forward.c -@@ -724,6 +724,10 @@ void reply_query(int fd, int family, time_t now) - if (!(forward = lookup_frec(ntohs(header->id), hash))) - return; - -+ if (daemon->ignore_addr && RCODE(header) == NOERROR && -+ check_for_ignored_address(header, n, daemon->ignore_addr)) -+ return; -+ - if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) && - !option_bool(OPT_ORDER) && - forward->forwardall == 0) -diff --git a/src/option.c b/src/option.c -index 209fa6976609..907d0cf88de9 100644 ---- a/src/option.c -+++ b/src/option.c -@@ -147,6 +147,7 @@ struct myoption { - #define LOPT_LOCAL_SERVICE 335 - #define LOPT_DNSSEC_TIME 336 - #define LOPT_LOOP_DETECT 337 -+#define LOPT_IGNORE_ADDR 338 - - #ifdef HAVE_GETOPT_LONG - static const struct option opts[] = -@@ -181,6 +182,7 @@ static const struct myoption opts[] = - { "local-service", 0, 0, LOPT_LOCAL_SERVICE }, - { "bogus-priv", 0, 0, 'b' }, - { "bogus-nxdomain", 1, 0, 'B' }, -+ { "ignore-address", 1, 0, LOPT_IGNORE_ADDR }, - { "selfmx", 0, 0, 'e' }, - { "filterwin2k", 0, 0, 'f' }, - { "pid-file", 2, 0, 'x' }, -@@ -457,6 +459,7 @@ static struct { - { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL }, - { LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks"), NULL }, - { LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops"), NULL }, -+ { LOPT_IGNORE_ADDR, ARG_DUP, "", gettext_noop("Ignore DNS responses containing ipaddr."), NULL }, - { 0, 0, NULL, NULL, NULL } - }; - -@@ -2119,14 +2122,23 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma - break; - - case 'B': /* --bogus-nxdomain */ -- { -+ case LOPT_IGNORE_ADDR: /* --ignore-address */ -+ { - struct in_addr addr; - unhide_metas(arg); - if (arg && (inet_pton(AF_INET, arg, &addr) > 0)) - { - struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr)); -- baddr->next = daemon->bogus_addr; -- daemon->bogus_addr = baddr; -+ if (option == 'B') -+ { -+ baddr->next = daemon->bogus_addr; -+ daemon->bogus_addr = baddr; -+ } -+ else -+ { -+ baddr->next = daemon->ignore_addr; -+ daemon->ignore_addr = baddr; -+ } - baddr->addr = addr; - } - else -diff --git a/src/rfc1035.c b/src/rfc1035.c -index bdeb3fb10e68..75c4266b47dd 100644 ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1328,6 +1328,43 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, - return 0; - } - -+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr) -+{ -+ unsigned char *p; -+ int i, qtype, qclass, rdlen; -+ struct bogus_addr *baddrp; -+ -+ /* skip over questions */ -+ if (!(p = skip_questions(header, qlen))) -+ return 0; /* bad packet */ -+ -+ for (i = ntohs(header->ancount); i != 0; i--) -+ { -+ if (!(p = skip_name(p, header, qlen, 10))) -+ return 0; /* bad packet */ -+ -+ GETSHORT(qtype, p); -+ GETSHORT(qclass, p); -+ p += 4; /* TTL */ -+ GETSHORT(rdlen, p); -+ -+ if (qclass == C_IN && qtype == T_A) -+ { -+ if (!CHECK_LEN(header, p, qlen, INADDRSZ)) -+ return 0; -+ -+ for (baddrp = baddr; baddrp; baddrp = baddrp->next) -+ if (memcmp(&baddrp->addr, p, INADDRSZ) == 0) -+ return 1; -+ } -+ -+ if (!ADD_RDLEN(header, p, qlen, rdlen)) -+ return 0; -+ } -+ -+ return 0; -+} -+ - int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp, - unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...) - { --- -2.1.0 - diff --git a/src/patches/dnsmasq/0022-Bad-packet-protection.patch b/src/patches/dnsmasq/0022-Bad-packet-protection.patch deleted file mode 100644 index 96c4696bab..0000000000 --- a/src/patches/dnsmasq/0022-Bad-packet-protection.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0b1008d367d44e77352134a4c5178f896f0db3e7 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Sat, 27 Dec 2014 15:33:32 +0000 -Subject: [PATCH 022/113] Bad packet protection. - ---- - src/dnssec.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/dnssec.c b/src/dnssec.c -index ed8cf893bad2..026794b077e5 100644 ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -805,7 +805,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in - { - while (*name_start != '.' && *name_start != 0) - name_start++; -- if (k != 1) -+ if (k != 1 && *name_start == '.') - name_start++; - } - --- -2.1.0 - diff --git a/src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch b/src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch deleted file mode 100644 index f5dfad8aca..0000000000 --- a/src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch +++ /dev/null @@ -1,29 +0,0 @@ -From d310ab7ecbffce79d3d90debba621e0222f9bced Mon Sep 17 00:00:00 2001 -From: Matthias Andree -Date: Sat, 27 Dec 2014 15:36:38 +0000 -Subject: [PATCH 023/113] Fix build failure in new inotify code on BSD. - ---- - src/inotify.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/inotify.c b/src/inotify.c -index 960bf5efb41f..83730008c11b 100644 ---- a/src/inotify.c -+++ b/src/inotify.c -@@ -15,10 +15,10 @@ - */ - - #include "dnsmasq.h" --#include -- - #ifdef HAVE_LINUX_NETWORK - -+#include -+ - /* the strategy is to set a inotify on the directories containing - resolv files, for any files in the directory which are close-write - or moved into the directory. --- -2.1.0 - diff --git a/src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch b/src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch deleted file mode 100644 index 6f29876c31..0000000000 --- a/src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 81c538efcebfce2ce4a1d3a420b6c885b8f08df9 Mon Sep 17 00:00:00 2001 -From: Yousong Zhou -Date: Sat, 3 Jan 2015 16:36:14 +0000 -Subject: [PATCH 024/113] Implement makefile dependencies on COPTS variable. - ---- - .gitignore | 2 +- - Makefile | 10 ++++++---- - 2 files changed, 7 insertions(+), 5 deletions(-) - -diff --git a/.gitignore b/.gitignore -index fcdbcbd135ae..23f11488ab4c 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -3,7 +3,7 @@ src/*.mo - src/dnsmasq.pot - src/dnsmasq - src/dnsmasq_baseline --src/.configured -+src/.copts_* - contrib/wrt/dhcp_lease_time - contrib/wrt/dhcp_release - debian/base/ -diff --git a/Makefile b/Makefile -index c340f1c7b59a..5675f60c2036 100644 ---- a/Makefile -+++ b/Makefile -@@ -64,6 +64,8 @@ nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG - gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp` - sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi` - version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"' -+copts_conf = .copts_$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | \ -+ ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ') - - objs = cache.o rfc1035.o util.o option.o forward.o network.o \ - dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ -@@ -83,7 +85,7 @@ all : $(BUILDDIR) - - mostly_clean : - rm -f $(BUILDDIR)/*.mo $(BUILDDIR)/*.pot -- rm -f $(BUILDDIR)/.configured $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq -+ rm -f $(BUILDDIR)/.copts_* $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq - - clean : mostly_clean - rm -f $(BUILDDIR)/dnsmasq_baseline -@@ -139,8 +141,8 @@ bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all - - # rules below are targets in recusive makes with cwd=$(BUILDDIR) - --.configured: $(hdrs) -- @rm -f *.o -+$(copts_conf): $(hdrs) -+ @rm -f *.o .copts_* - @touch $@ - - $(objs:.o=.c) $(hdrs): -@@ -149,7 +151,7 @@ $(objs:.o=.c) $(hdrs): - .c.o: - $(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $< - --dnsmasq : .configured $(hdrs) $(objs) -+dnsmasq : $(copts_conf) $(hdrs) $(objs) - $(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS) - - dnsmasq.pot : $(objs:.o=.c) $(hdrs) --- -2.1.0 - diff --git a/src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch b/src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch deleted file mode 100644 index 84245f88d7..0000000000 --- a/src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch +++ /dev/null @@ -1,30 +0,0 @@ -From d8dbd903d024f84a149dac2f8a674a68dfed47a3 Mon Sep 17 00:00:00 2001 -From: Yousong Zhou -Date: Mon, 5 Jan 2015 17:03:35 +0000 -Subject: [PATCH 025/113] Fix race condition issue in makefile. - ---- - Makefile | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/Makefile b/Makefile -index 5675f60c2036..bcbd5571671d 100644 ---- a/Makefile -+++ b/Makefile -@@ -148,10 +148,12 @@ $(copts_conf): $(hdrs) - $(objs:.o=.c) $(hdrs): - ln -s $(top)/$(SRC)/$@ . - -+$(objs): $(copts_conf) $(hdrs) -+ - .c.o: - $(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $< - --dnsmasq : $(copts_conf) $(hdrs) $(objs) -+dnsmasq : $(objs) - $(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS) - - dnsmasq.pot : $(objs:.o=.c) $(hdrs) --- -2.1.0 - diff --git a/src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch b/src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch deleted file mode 100644 index e715c50ae7..0000000000 --- a/src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch +++ /dev/null @@ -1,792 +0,0 @@ -From 97e618a0e3f29465acc689d87288596b006f197e Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Wed, 7 Jan 2015 21:55:43 +0000 -Subject: [PATCH 026/113] DNSSEC: do top-down search for limit of secure - delegation. - ---- - CHANGELOG | 9 ++ - src/dnsmasq.h | 11 +- - src/dnssec.c | 91 +++++++++------- - src/forward.c | 327 +++++++++++++++++++++++++++++++++------------------------- - 4 files changed, 260 insertions(+), 178 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 2b6356bcfb02..e8bf80f81baa 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -31,7 +31,16 @@ version 2.73 - request for certain domains, before the correct answer can - arrive. Thanks to Glen Huang for the patch. - -+ Revisit the part of DNSSEC validation which determines if an -+ unsigned answer is legit, or is in some part of the DNS -+ tree which should be signed. Dnsmasq now works from the -+ DNS root downward looking for the limit of signed -+ delegations, rather than working bottom up. This is -+ both more correct, and less likely to trip over broken -+ nameservers in the unsigned parts of the DNS tree -+ which don't respond well to DNSSEC queries. - -+ - version 2.72 - Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. - -diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index 7bc982ddf73c..2f4597294a56 100644 ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -569,8 +569,9 @@ struct hostsfile { - #define STAT_SECURE_WILDCARD 7 - #define STAT_NO_SIG 8 - #define STAT_NO_DS 9 --#define STAT_NEED_DS_NEG 10 --#define STAT_CHASE_CNAME 11 -+#define STAT_NO_NS 10 -+#define STAT_NEED_DS_NEG 11 -+#define STAT_CHASE_CNAME 12 - - #define FREC_NOREBIND 1 - #define FREC_CHECKING_DISABLED 2 -@@ -604,7 +605,9 @@ struct frec { - #ifdef HAVE_DNSSEC - int class, work_counter; - struct blockdata *stash; /* Saved reply, whilst we validate */ -- size_t stash_len; -+ struct blockdata *orig_domain; /* domain of original query, whilst -+ we're seeing is if in unsigned domain */ -+ size_t stash_len, name_start, name_len; - struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */ - struct frec *blocking_query; /* Query which is blocking us. */ - #endif -@@ -1126,7 +1129,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut); - size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr); - int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class); - int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class); --int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer); -+int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer, int *nons); - int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname); - int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen); - size_t filter_rrsigs(struct dns_header *header, size_t plen); -diff --git a/src/dnssec.c b/src/dnssec.c -index 026794b077e5..8f27677628b2 100644 ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -875,8 +875,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in - /* The DNS packet is expected to contain the answer to a DNSKEY query. - Put all DNSKEYs in the answer which are valid into the cache. - return codes: -- STAT_INSECURE No DNSKEYs in reply. -- STAT_SECURE At least one valid DNSKEY found and in cache. -+ STAT_SECURE At least one valid DNSKEY found and in cache. - STAT_BOGUS No DNSKEYs found, which can be validated with DS, - or self-sign for DNSKEY RRset is not valid, bad packet. - STAT_NEED_DS DS records to validate a key not found, name in keyname -@@ -896,11 +895,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch - GETSHORT(qtype, p); - GETSHORT(qclass, p); - -- if (qtype != T_DNSKEY || qclass != class) -+ if (qtype != T_DNSKEY || qclass != class || ntohs(header->ancount) == 0) - return STAT_BOGUS; -- -- if (ntohs(header->ancount) == 0) -- return STAT_INSECURE; - - /* See if we have cached a DS record which validates this key */ - if (!(crecp = cache_find_by_name(NULL, name, now, F_DS))) -@@ -1103,17 +1099,17 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch - /* The DNS packet is expected to contain the answer to a DS query - Put all DSs in the answer which are valid into the cache. - return codes: -- STAT_INSECURE no DS in reply or not signed. - STAT_SECURE At least one valid DS found and in cache. - STAT_NO_DS It's proved there's no DS here. -- STAT_BOGUS At least one DS found, which fails validation, bad packet. -+ STAT_NO_NS It's proved there's no DS _or_ NS here. -+ STAT_BOGUS no DS in reply or not signed, fails validation, bad packet. - STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname - */ - - int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) - { - unsigned char *p = (unsigned char *)(header+1); -- int qtype, qclass, val, i, neganswer; -+ int qtype, qclass, val, i, neganswer, nons; - - if (ntohs(header->qdcount) != 1 || - !(p = skip_name(p, header, plen, 4))) -@@ -1125,32 +1121,39 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char - if (qtype != T_DS || qclass != class) - val = STAT_BOGUS; - else -- val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer); -- -- if (val == STAT_NO_SIG) -- val = STAT_INSECURE; -+ val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer, &nons); -+ /* Note dnssec_validate_reply() will have cached positive answers */ -+ -+ if (val == STAT_NO_SIG || val == STAT_INSECURE) -+ val = STAT_BOGUS; - - p = (unsigned char *)(header+1); - extract_name(header, plen, &p, name, 1, 4); - p += 4; /* qtype, qclass */ - - if (!(p = skip_section(p, ntohs(header->ancount), header, plen))) -- return STAT_BOGUS; -+ val = STAT_BOGUS; - - if (val == STAT_BOGUS) -- log_query(F_UPSTREAM, name, NULL, "BOGUS DS"); -- -- if ((val == STAT_SECURE || val == STAT_INSECURE) && neganswer) - { -- int rdlen, flags = F_FORWARD | F_DS | F_NEG; -+ log_query(F_UPSTREAM, name, NULL, "BOGUS DS"); -+ return STAT_BOGUS; -+ } -+ -+ /* By here, the answer is proved secure, and a positive answer has been cached. */ -+ if (val == STAT_SECURE && neganswer) -+ { -+ int rdlen, flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK; - unsigned long ttl, minttl = ULONG_MAX; - struct all_addr a; - - if (RCODE(header) == NXDOMAIN) - flags |= F_NXDOMAIN; - -- if (val == STAT_SECURE) -- flags |= F_DNSSECOK; -+ /* We only cache validated DS records, DNSSECOK flag hijacked -+ to store presence/absence of NS. */ -+ if (nons) -+ flags &= ~F_DNSSECOK; - - for (i = ntohs(header->nscount); i != 0; i--) - { -@@ -1196,10 +1199,12 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char - a.addr.dnssec.class = class; - cache_insert(name, &a, now, ttl, flags); - -- cache_end_insert(); -+ cache_end_insert(); -+ -+ log_query(F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS"); - } - -- return (val == STAT_SECURE) ? STAT_NO_DS : STAT_INSECURE; -+ return nons ? STAT_NO_NS : STAT_NO_DS; - } - - return val; -@@ -1323,12 +1328,15 @@ static int find_nsec_records(struct dns_header *header, size_t plen, unsigned ch - } - - static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, -- char *workspace1, char *workspace2, char *name, int type) -+ char *workspace1, char *workspace2, char *name, int type, int *nons) - { - int i, rc, rdlen; - unsigned char *p, *psave; - int offset = (type & 0xff) >> 3; - int mask = 0x80 >> (type & 0x07); -+ -+ if (nons) -+ *nons = 0; - - /* Find NSEC record that proves name doesn't exist */ - for (i = 0; i < nsec_count; i++) -@@ -1355,6 +1363,10 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi - rdlen -= p - psave; - /* rdlen is now length of type map, and p points to it */ - -+ /* If we can prove that there's no NS record, return that information. */ -+ if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) == 0) -+ *nons = 1; -+ - while (rdlen >= 2) - { - if (!CHECK_LEN(header, p, plen, rdlen)) -@@ -1456,7 +1468,7 @@ static int base32_decode(char *in, unsigned char *out) - } - - static int check_nsec3_coverage(struct dns_header *header, size_t plen, int digest_len, unsigned char *digest, int type, -- char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count) -+ char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count, int *nons) - { - int i, hash_len, salt_len, base32_len, rdlen; - unsigned char *p, *psave; -@@ -1497,6 +1509,10 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige - if (!CHECK_LEN(header, p, plen, rdlen)) - return 0; - -+ /* If we can prove that there's no NS record, return that information. */ -+ if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) == 0) -+ *nons = 1; -+ - while (rdlen >= 2) - { - if (p[0] == type >> 8) -@@ -1533,13 +1549,16 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige - } - - static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, -- char *workspace1, char *workspace2, char *name, int type, char *wildname) -+ char *workspace1, char *workspace2, char *name, int type, char *wildname, int *nons) - { - unsigned char *salt, *p, *digest; - int digest_len, i, iterations, salt_len, base32_len, algo = 0; - struct nettle_hash const *hash; - char *closest_encloser, *next_closest, *wildcard; -- -+ -+ if (nons) -+ *nons = 0; -+ - /* Look though the NSEC3 records to find the first one with - an algorithm we support (currently only algo == 1). - -@@ -1612,7 +1631,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns - if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0) - return STAT_BOGUS; - -- if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) -+ if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, nons)) - return STAT_SECURE; - - /* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3" -@@ -1657,7 +1676,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns - if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0) - return STAT_BOGUS; - -- if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) -+ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL)) - return STAT_BOGUS; - - /* Finally, check that there's no seat of wildcard synthesis */ -@@ -1672,7 +1691,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns - if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) - return STAT_BOGUS; - -- if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) -+ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL)) - return STAT_BOGUS; - } - -@@ -1681,7 +1700,8 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns - - /* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */ - /* Returns are the same as validate_rrset, plus the class if the missing key is in *class */ --int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer) -+int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, -+ int *class, int *neganswer, int *nons) - { - unsigned char *ans_start, *qname, *p1, *p2, **nsecs; - int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype; -@@ -1811,10 +1831,11 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch - return STAT_BOGUS; /* No NSECs or bad packet */ - - if (nsec_type == T_NSEC) -- rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1); -+ rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, NULL); - else -- rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, wildname); -- -+ rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, -+ keyname, name, type1, wildname, NULL); -+ - if (rc != STAT_SECURE) - return rc; - } -@@ -1937,9 +1958,9 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch - return STAT_BOGUS; - - if (nsec_type == T_NSEC) -- return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype); -+ return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, nons); - else -- return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL); -+ return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons); - } - - /* Chase the CNAME chain in the packet until the first record which _doesn't validate. -diff --git a/src/forward.c b/src/forward.c -index f28c7d51f708..ee8d7b52d5e5 100644 ---- a/src/forward.c -+++ b/src/forward.c -@@ -26,8 +26,9 @@ static void free_frec(struct frec *f); - #ifdef HAVE_DNSSEC - static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n, - int class, char *name, char *keyname, struct server *server, int *keycount); --static int do_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class); --static int send_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname); -+static int do_check_sign(struct frec *forward, int status, time_t now, char *name, char *keyname); -+static int send_check_sign(struct frec *forward, time_t now, struct dns_header *header, size_t plen, -+ char *name, char *keyname); - #endif - - -@@ -815,18 +816,22 @@ void reply_query(int fd, int family, time_t now) - else if (forward->flags & FREC_DS_QUERY) - { - status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); -- if (status == STAT_NO_DS) -- status = STAT_INSECURE; -+ if (status == STAT_NO_DS || status == STAT_NO_NS) -+ status = STAT_BOGUS; - } - else if (forward->flags & FREC_CHECK_NOSIGN) -- status = do_check_sign(now, header, n, daemon->namebuff, daemon->keyname, forward->class); -+ { -+ status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); -+ if (status != STAT_NEED_KEY) -+ status = do_check_sign(forward, status, now, daemon->namebuff, daemon->keyname); -+ } - else - { -- status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL); -+ status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL); - if (status == STAT_NO_SIG) - { - if (option_bool(OPT_DNSSEC_NO_SIGN)) -- status = send_check_sign(now, header, n, daemon->namebuff, daemon->keyname); -+ status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname); - else - status = STAT_INSECURE; - } -@@ -861,6 +866,7 @@ void reply_query(int fd, int family, time_t now) - new->blocking_query = NULL; - new->sentto = server; - new->rfd4 = NULL; -+ new->orig_domain = NULL; - #ifdef HAVE_IPV6 - new->rfd6 = NULL; - #endif -@@ -889,7 +895,9 @@ void reply_query(int fd, int family, time_t now) - new->new_id = get_id(); - header->id = htons(new->new_id); - /* Save query for retransmission */ -- new->stash = blockdata_alloc((char *)header, nn); -+ if (!(new->stash = blockdata_alloc((char *)header, nn))) -+ return; -+ - new->stash_len = nn; - - /* Don't resend this. */ -@@ -946,18 +954,22 @@ void reply_query(int fd, int family, time_t now) - else if (forward->flags & FREC_DS_QUERY) - { - status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); -- if (status == STAT_NO_DS) -- status = STAT_INSECURE; -+ if (status == STAT_NO_DS || status == STAT_NO_NS) -+ status = STAT_BOGUS; - } - else if (forward->flags & FREC_CHECK_NOSIGN) -- status = do_check_sign(now, header, n, daemon->namebuff, daemon->keyname, forward->class); -+ { -+ status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); -+ if (status != STAT_NEED_KEY) -+ status = do_check_sign(forward, status, now, daemon->namebuff, daemon->keyname); -+ } - else - { -- status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL); -+ status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL); - if (status == STAT_NO_SIG) - { - if (option_bool(OPT_DNSSEC_NO_SIGN)) -- status = send_check_sign(now, header, n, daemon->namebuff, daemon->keyname); -+ status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname); - else - status = STAT_INSECURE; - } -@@ -1319,70 +1331,80 @@ void receive_query(struct listener *listen, time_t now) - /* UDP: we've got an unsigned answer, return STAT_INSECURE if we can prove there's no DS - and therefore the answer shouldn't be signed, or STAT_BOGUS if it should be, or - STAT_NEED_DS_NEG and keyname if we need to do the query. */ --static int send_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname) -+static int send_check_sign(struct frec *forward, time_t now, struct dns_header *header, size_t plen, -+ char *name, char *keyname) - { -- struct crec *crecp; -- char *name_start = name; - int status = dnssec_chase_cname(now, header, plen, name, keyname); - - if (status != STAT_INSECURE) - return status; - -+ /* Store the domain we're trying to check. */ -+ forward->name_start = strlen(name); -+ forward->name_len = forward->name_start + 1; -+ if (!(forward->orig_domain = blockdata_alloc(name, forward->name_len))) -+ return STAT_BOGUS; -+ -+ return do_check_sign(forward, 0, now, name, keyname); -+} -+ -+/* We either have a a reply (header non-NULL, or we need to start by looking in the cache */ -+static int do_check_sign(struct frec *forward, int status, time_t now, char *name, char *keyname) -+{ -+ /* get domain we're checking back from blockdata store, it's stored on the original query. */ -+ while (forward->dependent) -+ forward = forward->dependent; -+ -+ blockdata_retrieve(forward->orig_domain, forward->name_len, name); -+ - while (1) - { -- crecp = cache_find_by_name(NULL, name_start, now, F_DS); -- -- if (crecp && (crecp->flags & F_DNSSECOK)) -- return (crecp->flags & F_NEG) ? STAT_INSECURE : STAT_BOGUS; -- -- if (crecp && (crecp->flags & F_NEG) && (name_start = strchr(name_start, '.'))) -+ char *p; -+ -+ if (status == 0) - { -- name_start++; /* chop a label off and try again */ -- continue; -+ struct crec *crecp; -+ -+ /* Haven't received answer, see if in cache */ -+ if (!(crecp = cache_find_by_name(NULL, &name[forward->name_start], now, F_DS))) -+ { -+ /* put name of DS record we're missing into keyname */ -+ strcpy(keyname, &name[forward->name_start]); -+ /* and wait for reply to arrive */ -+ return STAT_NEED_DS_NEG; -+ } -+ -+ /* F_DNSSECOK misused in DS cache records to non-existance of NS record */ -+ if (!(crecp->flags & F_NEG)) -+ status = STAT_SECURE; -+ else if (crecp->flags & F_DNSSECOK) -+ status = STAT_NO_DS; -+ else -+ status = STAT_NO_NS; - } -+ -+ /* Have entered non-signed part of DNS tree. */ -+ if (status == STAT_NO_DS) -+ return STAT_INSECURE; - -- /* Reached the root */ -- if (!name_start) -+ if (status == STAT_BOGUS) - return STAT_BOGUS; - -- strcpy(keyname, name_start); -- return STAT_NEED_DS_NEG; -- } --} -- --/* Got answer to DS query from send_check_sign, check for proven non-existence, or make the next DS query to try. */ --static int do_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) -- --{ -- char *name_start; -- unsigned char *p; -- int status; -+ /* There's a proven DS record, or we're within a zone, where there doesn't need -+ to be a DS record. Add a name and try again. -+ If we've already tried the whole name, then fail */ - -- /* In this case only, a SERVFAIL reply allows us to continue up the tree, looking for a -- suitable NSEC reply to DS queries. */ -- if (RCODE(header) != SERVFAIL) -- { -- status = dnssec_validate_ds(now, header, plen, name, keyname, class); -+ if (forward->name_start == 0) -+ return STAT_BOGUS; - -- if (status != STAT_INSECURE) -- { -- if (status == STAT_NO_DS) -- status = STAT_INSECURE; -- return status; -- } -- } -- -- p = (unsigned char *)(header+1); -- -- if (extract_name(header, plen, &p, name, 1, 4) && -- (name_start = strchr(name, '.'))) -- { -- name_start++; /* chop a label off and try again */ -- strcpy(keyname, name_start); -- return STAT_NEED_DS_NEG; -+ for (p = &name[forward->name_start-2]; (*p != '.') && (p != name); p--); -+ -+ if (p != name) -+ p++; -+ -+ forward->name_start = p - name; -+ status = 0; /* force to cache when we iterate. */ - } -- -- return STAT_BOGUS; - } - - /* Move toward the root, until we find a signed non-existance of a DS, in which case -@@ -1395,8 +1417,10 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s - unsigned char *packet, *payload; - u16 *length; - unsigned char *p = (unsigned char *)(header+1); -- int status; -- char *name_start = name; -+ int status, name_len; -+ struct blockdata *block; -+ -+ char *name_start; - - /* Get first insecure entry in CNAME chain */ - status = tcp_key_recurse(now, STAT_CHASE_CNAME, header, plen, class, name, keyname, server, keycount); -@@ -1409,95 +1433,113 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s - payload = &packet[2]; - header = (struct dns_header *)payload; - length = (u16 *)packet; -+ -+ /* Stash the name away, since the buffer will be trashed when we recurse */ -+ name_len = strlen(name) + 1; -+ name_start = name + name_len - 1; - -+ if (!(block = blockdata_alloc(name, name_len))) -+ { -+ free(packet); -+ return STAT_BOGUS; -+ } -+ - while (1) - { -- unsigned char *newhash, hash[HASH_SIZE]; - unsigned char c1, c2; -- struct crec *crecp = cache_find_by_name(NULL, name_start, now, F_DS); -- -+ struct crec *crecp; -+ - if (--(*keycount) == 0) - { - free(packet); -+ blockdata_free(block); - return STAT_BOGUS; - } -- -- if (crecp && (crecp->flags & F_DNSSECOK)) -- { -- free(packet); -- return (crecp->flags & F_NEG) ? STAT_INSECURE : STAT_BOGUS; -- } - -- /* If we have cached insecurely that a DS doesn't exist, -- ise that is a hit for where to start looking for the secure one */ -- if (crecp && (crecp->flags & F_NEG) && (name_start = strchr(name_start, '.'))) -- { -- name_start++; /* chop a label off and try again */ -- continue; -- } -- -- /* reached the root */ -- if (!name_start) -- { -- free(packet); -- return STAT_BOGUS; -+ while (crecp = cache_find_by_name(NULL, name_start, now, F_DS)) -+ { -+ if ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)) -+ { -+ /* Found a secure denial of DS - delegation is indeed insecure */ -+ free(packet); -+ blockdata_free(block); -+ return STAT_INSECURE; -+ } -+ -+ /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation. -+ Add another label and continue. */ -+ -+ if (name_start == name) -+ { -+ free(packet); -+ blockdata_free(block); -+ return STAT_BOGUS; /* run out of labels */ -+ } -+ -+ name_start -= 2; -+ while (*name_start != '.' && name_start != name) -+ name_start--; -+ if (name_start != name) -+ name_start++; - } -+ -+ /* Can't find it in the cache, have to send a query */ - - m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr); - -- /* We rely on the question section coming back unchanged, ensure it is with the hash. */ -- if ((newhash = hash_questions(header, (unsigned int)m, name))) -- { -- memcpy(hash, newhash, HASH_SIZE); -+ *length = htons(m); - -- *length = htons(m); -+ if (read_write(server->tcpfd, packet, m + sizeof(u16), 0) && -+ read_write(server->tcpfd, &c1, 1, 1) && -+ read_write(server->tcpfd, &c2, 1, 1) && -+ read_write(server->tcpfd, payload, (c1 << 8) | c2, 1)) -+ { -+ m = (c1 << 8) | c2; -+ -+ /* Note this trashes all three name workspaces */ -+ status = tcp_key_recurse(now, STAT_NEED_DS_NEG, header, m, class, name, keyname, server, keycount); - -- if (read_write(server->tcpfd, packet, m + sizeof(u16), 0) && -- read_write(server->tcpfd, &c1, 1, 1) && -- read_write(server->tcpfd, &c2, 1, 1) && -- read_write(server->tcpfd, payload, (c1 << 8) | c2, 1)) -+ if (status == STAT_NO_DS) - { -- m = (c1 << 8) | c2; -- -- newhash = hash_questions(header, (unsigned int)m, name); -- if (newhash && memcmp(hash, newhash, HASH_SIZE) == 0) -- { -- /* In this case only, a SERVFAIL reply allows us to continue up the tree, looking for a -- suitable NSEC reply to DS queries. */ -- if (RCODE(header) == SERVFAIL) -- status = STAT_INSECURE; -- else -- /* Note this trashes all three name workspaces */ -- status = tcp_key_recurse(now, STAT_NEED_DS_NEG, header, m, class, name, keyname, server, keycount); -- -- /* We've found a DS which proves the bit of the DNS where the -- original query is, is unsigned, so the answer is OK, -- if unvalidated. */ -- if (status == STAT_NO_DS) -- { -- free(packet); -- return STAT_INSECURE; -- } -- -- /* No DS, not got to DNSSEC-land yet, go up. */ -- if (status == STAT_INSECURE) -- { -- p = (unsigned char *)(header+1); -- -- if (extract_name(header, plen, &p, name, 1, 4) && -- (name_start = strchr(name, '.'))) -- { -- name_start++; /* chop a label off and try again */ -- continue; -- } -- } -- } -+ /* Found a secure denial of DS - delegation is indeed insecure */ -+ free(packet); -+ blockdata_free(block); -+ return STAT_INSECURE; -+ } -+ -+ if (status == STAT_BOGUS) -+ { -+ free(packet); -+ blockdata_free(block); -+ return STAT_BOGUS; -+ } -+ -+ /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation. -+ Add another label and continue. */ -+ -+ /* Get name we're checking back. */ -+ blockdata_retrieve(block, name_len, name); -+ -+ if (name_start == name) -+ { -+ free(packet); -+ blockdata_free(block); -+ return STAT_BOGUS; /* run out of labels */ - } -+ -+ name_start -= 2; -+ while (*name_start != '.' && name_start != name) -+ name_start--; -+ if (name_start != name) -+ name_start++; -+ } -+ else -+ { -+ /* IO failure */ -+ free(packet); -+ blockdata_free(block); -+ return STAT_BOGUS; /* run out of labels */ - } -- -- free(packet); -- -- return STAT_BOGUS; - } - } - -@@ -1516,14 +1558,14 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si - else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG) - { - new_status = dnssec_validate_ds(now, header, n, name, keyname, class); -- if (status == STAT_NEED_DS && new_status == STAT_NO_DS) -- new_status = STAT_INSECURE; -+ if (status == STAT_NEED_DS && (new_status == STAT_NO_DS || new_status == STAT_NO_NS)) -+ new_status = STAT_BOGUS; - } - else if (status == STAT_CHASE_CNAME) - new_status = dnssec_chase_cname(now, header, n, name, keyname); - else - { -- new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL); -+ new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL); - - if (new_status == STAT_NO_SIG) - { -@@ -1576,14 +1618,14 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si - else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG) - { - new_status = dnssec_validate_ds(now, header, n, name, keyname, class); -- if (status == STAT_NEED_DS && new_status == STAT_NO_DS) -- new_status = STAT_INSECURE; /* Validated no DS */ -+ if (status == STAT_NEED_DS && (new_status == STAT_NO_DS || new_status == STAT_NO_NS)) -+ new_status = STAT_BOGUS; /* Validated no DS */ - } - else if (status == STAT_CHASE_CNAME) - new_status = dnssec_chase_cname(now, header, n, name, keyname); - else - { -- new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL); -+ new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL); - - if (new_status == STAT_NO_SIG) - { -@@ -1961,6 +2003,7 @@ static struct frec *allocate_frec(time_t now) - f->dependent = NULL; - f->blocking_query = NULL; - f->stash = NULL; -+ f->orig_domain = NULL; - #endif - daemon->frec_list = f; - } -@@ -2029,6 +2072,12 @@ static void free_frec(struct frec *f) - f->stash = NULL; - } - -+ if (f->orig_domain) -+ { -+ blockdata_free(f->orig_domain); -+ f->orig_domain = NULL; -+ } -+ - /* Anything we're waiting on is pointless now, too */ - if (f->blocking_query) - free_frec(f->blocking_query); --- -2.1.0 - diff --git a/src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch b/src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch deleted file mode 100644 index f643527142..0000000000 --- a/src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch +++ /dev/null @@ -1,346 +0,0 @@ -From 25cf5e373eb41c088d4ee5e625209c4cf6a5659e Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Fri, 9 Jan 2015 15:53:03 +0000 -Subject: [PATCH 027/113] Add --log-queries=extra option for more complete - logging. - ---- - CHANGELOG | 3 +++ - man/dnsmasq.8 | 5 ++++- - src/cache.c | 11 ++++++++++- - src/config.h | 1 + - src/dnsmasq.c | 5 +++++ - src/dnsmasq.h | 9 +++++++-- - src/dnssec.c | 14 +++++++------- - src/forward.c | 30 ++++++++++++++++++++++++++---- - src/option.c | 11 +++++++++-- - 9 files changed, 72 insertions(+), 17 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index e8bf80f81baa..0bbb7835df4f 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -40,6 +40,9 @@ version 2.73 - nameservers in the unsigned parts of the DNS tree - which don't respond well to DNSSEC queries. - -+ Add --log-queries=extra option, which makes logs easier -+ to search automatically. -+ - - version 2.72 - Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. -diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 -index 4236ba307df3..227d74bd80e7 100644 ---- a/man/dnsmasq.8 -+++ b/man/dnsmasq.8 -@@ -98,7 +98,10 @@ only, to stop dnsmasq daemonising in production, use - .B -k. - .TP - .B \-q, --log-queries --Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. -+Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. If the argument "extra" is supplied, ie -+.B --log-queries=extra -+then the log has extra information at the start of each line. -+This consists of a serial number which ties together the log lines associated with an individual query, and the IP address of the requestor. - .TP - .B \-8, --log-facility= - Set the facility to which dnsmasq will send syslog entries, this -diff --git a/src/cache.c b/src/cache.c -index ff1ca6f1c352..960bb7938778 100644 ---- a/src/cache.c -+++ b/src/cache.c -@@ -1638,7 +1638,16 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg) - if (strlen(name) == 0) - name = "."; - -- my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); -+ if (option_bool(OPT_EXTRALOG)) -+ { -+ prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2); -+ if (flags & F_NOEXTRA) -+ my_syslog(LOG_INFO, "* %s %s %s %s %s", daemon->addrbuff2, source, name, verb, dest); -+ else -+ my_syslog(LOG_INFO, "%u %s %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, source, name, verb, dest); -+ } -+ else -+ my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); - } - - -diff --git a/src/config.h b/src/config.h -index 145820ad2510..3b88d8193dca 100644 ---- a/src/config.h -+++ b/src/config.h -@@ -17,6 +17,7 @@ - #define FTABSIZ 150 /* max number of outstanding requests (default) */ - #define MAX_PROCS 20 /* max no children for TCP requests */ - #define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */ -+#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */ - #define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */ - #define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */ - #define DNSSEC_WORK 50 /* Max number of queries to validate one question */ -diff --git a/src/dnsmasq.c b/src/dnsmasq.c -index 5c7750d365fa..c0c0589d4ce1 100644 ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -93,6 +93,8 @@ int main (int argc, char **argv) - daemon->packet = safe_malloc(daemon->packet_buff_sz); - - daemon->addrbuff = safe_malloc(ADDRSTRLEN); -+ if (option_bool(OPT_EXTRALOG)) -+ daemon->addrbuff2 = safe_malloc(ADDRSTRLEN); - - #ifdef HAVE_DNSSEC - if (option_bool(OPT_DNSSEC_VALID)) -@@ -1587,6 +1589,9 @@ static void check_dns_listeners(fd_set *set, time_t now) - } - } - close(confd); -+ -+ /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */ -+ daemon->log_id += TCP_MAX_QUERIES; - } - #endif - else -diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index 2f4597294a56..4e9aea401b75 100644 ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -238,7 +238,8 @@ struct event_desc { - #define OPT_DNSSEC_NO_SIGN 48 - #define OPT_LOCAL_SERVICE 49 - #define OPT_LOOP_DETECT 50 --#define OPT_LAST 51 -+#define OPT_EXTRALOG 51 -+#define OPT_LAST 52 - - /* extra flags for my_syslog, we use a couple of facilities since they are known - not to occupy the same bits as priorities, no matter how syslog.h is set up. */ -@@ -442,6 +443,7 @@ struct crec { - #define F_NO_RR (1u<<25) - #define F_IPSET (1u<<26) - #define F_NSIGMATCH (1u<<27) -+#define F_NOEXTRA (1u<<28) - - /* Values of uid in crecs with F_CONFIG bit set. */ - #define SRC_INTERFACE 0 -@@ -599,7 +601,7 @@ struct frec { - #endif - unsigned int iface; - unsigned short orig_id, new_id; -- int fd, forwardall, flags; -+ int log_id, fd, forwardall, flags; - time_t time; - unsigned char *hash[HASH_SIZE]; - #ifdef HAVE_DNSSEC -@@ -1002,6 +1004,8 @@ extern struct daemon { - struct randfd randomsocks[RANDOM_SOCKS]; - int v6pktinfo; - struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */ -+ int log_id, log_display_id; /* ids of transactions for logging */ -+ union mysockaddr *log_source_addr; - - /* DHCP state */ - int dhcpfd, helperfd, pxefd; -@@ -1033,6 +1037,7 @@ extern struct daemon { - - /* utility string buffer, hold max sized IP address as string */ - char *addrbuff; -+ char *addrbuff2; /* only allocated when OPT_EXTRALOG */ - - } *daemon; - -diff --git a/src/dnssec.c b/src/dnssec.c -index 8f27677628b2..afb3dca38cb1 100644 ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -1038,7 +1038,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch - else - { - a.addr.keytag = keytag; -- log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u"); -+ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u"); - - recp1->addr.key.keylen = rdlen - 4; - recp1->addr.key.keydata = key; -@@ -1092,7 +1092,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch - return STAT_SECURE; - } - -- log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY"); -+ log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNSKEY"); - return STAT_BOGUS; - } - -@@ -1136,7 +1136,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char - - if (val == STAT_BOGUS) - { -- log_query(F_UPSTREAM, name, NULL, "BOGUS DS"); -+ log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS"); - return STAT_BOGUS; - } - -@@ -1201,7 +1201,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char - - cache_end_insert(); - -- log_query(F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS"); -+ log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS"); - } - - return nons ? STAT_NO_NS : STAT_NO_DS; -@@ -1885,7 +1885,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch - else - { - a.addr.keytag = keytag; -- log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); -+ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); - crecp->addr.ds.digest = digest; - crecp->addr.ds.keydata = key; - crecp->addr.ds.algo = algo; -@@ -2058,10 +2058,10 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i - char *types = querystr("dnssec-query", type); - - if (addr->sa.sa_family == AF_INET) -- log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types); -+ log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types); - #ifdef HAVE_IPV6 - else -- log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types); -+ log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types); - #endif - - header->qdcount = htons(1); -diff --git a/src/forward.c b/src/forward.c -index 55f583383bc6..713a64c0fa58 100644 ---- a/src/forward.c -+++ b/src/forward.c -@@ -279,10 +279,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, - plen = forward->stash_len; - - if (forward->sentto->addr.sa.sa_family == AF_INET) -- log_query(F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); -+ 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_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec"); -+ log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec"); - #endif - - if (forward->sentto->sfd) -@@ -389,6 +389,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, - struct server *firstsentto = start; - int forwarded = 0; - -+ /* If a query is retried, use the log_id for the retry when logging the answer. */ -+ forward->log_id = daemon->log_id; -+ - if (option_bool(OPT_ADD_MAC)) - plen = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); - -@@ -725,6 +728,11 @@ void reply_query(int fd, int family, time_t now) - if (!(forward = lookup_frec(ntohs(header->id), hash))) - return; - -+ /* log_query gets called indirectly all over the place, so -+ pass these in global variables - sorry. */ -+ daemon->log_display_id = forward->log_id; -+ daemon->log_source_addr = &forward->source; -+ - if (daemon->ignore_addr && RCODE(header) == NOERROR && - check_for_ignored_address(header, n, daemon->ignore_addr)) - return; -@@ -1258,6 +1266,11 @@ void receive_query(struct listener *listen, time_t now) - dst_addr_4.s_addr = 0; - } - } -+ -+ /* log_query gets called indirectly all over the place, so -+ pass these in global variables - sorry. */ -+ daemon->log_display_id = ++daemon->log_id; -+ daemon->log_source_addr = &source_addr; - - if (extract_request(header, (size_t)n, daemon->namebuff, &type)) - { -@@ -1675,7 +1688,8 @@ unsigned char *tcp_request(int confd, time_t now, - struct in_addr dst_addr_4; - union mysockaddr peer_addr; - socklen_t peer_len = sizeof(union mysockaddr); -- -+ int query_count = 0; -+ - if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1) - return packet; - -@@ -1712,7 +1726,8 @@ unsigned char *tcp_request(int confd, time_t now, - - while (1) - { -- if (!packet || -+ if (query_count == TCP_MAX_QUERIES || -+ !packet || - !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) || - !(size = c1 << 8 | c2) || - !read_write(confd, payload, size, 1)) -@@ -1721,6 +1736,13 @@ unsigned char *tcp_request(int confd, time_t now, - if (size < (int)sizeof(struct dns_header)) - continue; - -+ query_count++; -+ -+ /* log_query gets called indirectly all over the place, so -+ pass these in global variables - sorry. */ -+ daemon->log_display_id = ++daemon->log_id; -+ daemon->log_source_addr = &peer_addr; -+ - check_subnet = 0; - - /* save state of "cd" flag in query */ -diff --git a/src/option.c b/src/option.c -index 907d0cf88de9..b7372be0a090 100644 ---- a/src/option.c -+++ b/src/option.c -@@ -149,6 +149,7 @@ struct myoption { - #define LOPT_LOOP_DETECT 337 - #define LOPT_IGNORE_ADDR 338 - -+ - #ifdef HAVE_GETOPT_LONG - static const struct option opts[] = - #else -@@ -160,7 +161,7 @@ static const struct myoption opts[] = - { "no-poll", 0, 0, 'n' }, - { "help", 0, 0, 'w' }, - { "no-daemon", 0, 0, 'd' }, -- { "log-queries", 0, 0, 'q' }, -+ { "log-queries", 2, 0, 'q' }, - { "user", 2, 0, 'u' }, - { "group", 2, 0, 'g' }, - { "resolv-file", 2, 0, 'r' }, -@@ -357,7 +358,7 @@ static struct { - { LOPT_FORCE, ARG_DUP, "", gettext_noop("DHCP option sent even if the client does not request it."), NULL}, - { 'p', ARG_ONE, "", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL }, - { 'P', ARG_ONE, "", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" }, -- { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL }, -+ { 'q', ARG_DUP, NULL, gettext_noop("Log DNS queries."), NULL }, - { 'Q', ARG_ONE, "", gettext_noop("Force the originating port for upstream DNS queries."), NULL }, - { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL }, - { 'r', ARG_DUP, "", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, -@@ -2421,6 +2422,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma - ret_err(gen_err); - break; - -+ case 'q': /* --log-queries */ -+ set_option_bool(OPT_LOG); -+ if (arg && strcmp(arg, "extra") == 0) -+ set_option_bool(OPT_EXTRALOG); -+ break; -+ - case LOPT_MAX_LOGS: /* --log-async */ - daemon->max_logs = LOG_MAX; /* default */ - if (arg && !atoi_check(arg, &daemon->max_logs)) --- -2.1.0 - diff --git a/src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch b/src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch deleted file mode 100644 index 8714feb9ce..0000000000 --- a/src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 28de38768e2c7d763b9aa5b7a4d251d5e56bab0b Mon Sep 17 00:00:00 2001 -From: RinSatsuki -Date: Sat, 10 Jan 2015 15:22:21 +0000 -Subject: [PATCH 028/113] Add --min-cache-ttl option. - ---- - CHANGELOG | 7 +++++++ - man/dnsmasq.8 | 6 ++++++ - src/cache.c | 4 +++- - src/config.h | 1 + - src/dnsmasq.h | 2 +- - src/option.c | 11 +++++++++++ - 6 files changed, 29 insertions(+), 2 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 0bbb7835df4f..23fc6d0530cf 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -43,6 +43,13 @@ version 2.73 - Add --log-queries=extra option, which makes logs easier - to search automatically. - -+ Add --min-cache-ttl option. I've resisted this for a long -+ time, on the grounds that disbelieving TTLs is never a -+ good idea, but I've been persuaded that there are -+ sometimes reasons to do it. (Step forward, GFW). -+ To avoid misuse, there's a hard limit on the TTL -+ floor of one hour. Thansk to RinSatsuki for the patch. -+ - - version 2.72 - Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. -diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 -index 227d74bd80e7..5cfa355dea4a 100644 ---- a/man/dnsmasq.8 -+++ b/man/dnsmasq.8 -@@ -81,6 +81,12 @@ the upstream DNS servers. - .B --max-cache-ttl=