Remove dnsmasq patches

These are not applied any more because dnsmasq was updated
to the latest release version.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
This commit is contained in:
Michael Tremer
2015-07-09 12:31:32 +02:00
parent d6c40f585d
commit 8c8383e55e
118 changed files with 0 additions and 54163 deletions

View File

@@ -1,23 +0,0 @@
From f2658275b25ebfe691cdcb9fede85a3088cca168 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,86 +0,0 @@
From 00cd9d551998307225312fd21f761cfa8868bd2c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,36 +0,0 @@
From 6ac3bc0452a74e16e3d620a0757b0f8caab182ec Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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 <bsd/string.h>
+#endif
+
#include <sys/types.h>
#include <sys/ioctl.h>
@@ -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

View File

@@ -1,68 +0,0 @@
From e9828b6f66b22ce8873f8d30a773137d1aef1b92 Mon Sep 17 00:00:00 2001
From: Karl Vogel <karl.vogel@gmail.com>
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

View File

@@ -1,26 +0,0 @@
From 17b475912f6a4e72797a543dad59d4d5dde6bb1b Mon Sep 17 00:00:00 2001
From: Daniel Collins <daniel.collins@smoothwall.net>
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

View File

@@ -1,22 +0,0 @@
From 3d9d2dd0018603a2ae4b9cd65ac6ff959f4fd8c7 Mon Sep 17 00:00:00 2001
From: Tomas Hozza <thozza@redhat.com>
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

View File

@@ -1,107 +0,0 @@
From b9ff5c8f435173cfa616e3c398bdc089ef690a07 Mon Sep 17 00:00:00 2001
From: Vladislav Grishenko <themiron@mail.ru>
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

View File

@@ -1,39 +0,0 @@
From 98906275a02ae260fe3f82133bd79054f8315f06 Mon Sep 17 00:00:00 2001
From: Hans Dedecker <dedeckeh@gmail.com>
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 <dedeckeh@gmail.com>
---
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

View File

@@ -1,257 +0,0 @@
From 193de4abf59e49c6b70d54cfe9720fcb95ca2f71 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+#include <sys/inotify.h>
+
+#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

View File

@@ -1,73 +0,0 @@
From 857973e6f7e0a3d03535a9df7f9373fd7a0b65cc Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,46 +0,0 @@
From 800c5cc1e7438818fd80f08c2d472df249a6942d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,27 +0,0 @@
From ad946d555dce44eb690c7699933b6ff40ab85bb6 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,70 +0,0 @@
From 3ad3f3bbd4ee716a7d2fb1e115cf89bd1b1a5de9 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 16 Dec 2014 18:25:17 +0000
Subject: [PATCH 013/113] Fix breakage of --domain=<domain>,<subnet>,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=<domain>,<subnet>,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=/<domain>/
local=/xxx.yyy.zzz.in-addr.arpa/ */
struct server *serv = add_rev4(new->start, msize);
serv->flags |= SERV_NO_ADDR;
+
+ /* local=/<domain>/ */
+ 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=/<domain>/
local=/xxx.yyy.zzz.ip6.arpa/ */
struct server *serv = add_rev6(&new->start6, msize);
serv->flags |= SERV_NO_ADDR;
+
+ /* local=/<domain>/ */
+ 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

View File

@@ -1,27 +0,0 @@
From bd9520b7ade7098ee423acc38965376aa57feb07 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,148 +0,0 @@
From 476693678e778886b64d0b56e27eb7695cbcca99 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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=<domain>,<subnet>,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

View File

@@ -1,35 +0,0 @@
From 3267804598047bd1781cab91508d1bc516e5ddbb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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 = "<Root>";
- 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

View File

@@ -1,100 +0,0 @@
From 094b5c3d904bae9aeb3206d9f3b8348926b84975 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,99 +0,0 @@
From cbc652423403e3cef00e00240f6beef713142246 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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 <reverse>,<other>,<immortal>
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

View File

@@ -1,365 +0,0 @@
From fbc5205702c7f6f431d9f1043c553d7fb62ddfdb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,32 +0,0 @@
From 83d2ed09fc0216b567d7fb2197e4ff3eae150b0d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,192 +0,0 @@
From 32fc6dbe03569d70dd394420ceb73532cf303c33 Mon Sep 17 00:00:00 2001
From: Glen Huang <curvedmark@gmail.com>
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=<ipaddr>
+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, "<ipaddr>", 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

View File

@@ -1,25 +0,0 @@
From 0b1008d367d44e77352134a4c5178f896f0db3e7 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,29 +0,0 @@
From d310ab7ecbffce79d3d90debba621e0222f9bced Mon Sep 17 00:00:00 2001
From: Matthias Andree <matthias.andree@gmx.de>
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 <sys/inotify.h>
-
#ifdef HAVE_LINUX_NETWORK
+#include <sys/inotify.h>
+
/* 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

View File

@@ -1,68 +0,0 @@
From 81c538efcebfce2ce4a1d3a420b6c885b8f08df9 Mon Sep 17 00:00:00 2001
From: Yousong Zhou <yszhou4tech@gmail.com>
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

View File

@@ -1,30 +0,0 @@
From d8dbd903d024f84a149dac2f8a674a68dfed47a3 Mon Sep 17 00:00:00 2001
From: Yousong Zhou <yszhou4tech@gmail.com>
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

View File

@@ -1,792 +0,0 @@
From 97e618a0e3f29465acc689d87288596b006f197e Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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

View File

@@ -1,346 +0,0 @@
From 25cf5e373eb41c088d4ee5e625209c4cf6a5659e Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
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=<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, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
{ 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
{ 'P', ARG_ONE, "<integer>", 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, "<integer>", 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, "<path>", 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

View File

@@ -1,144 +0,0 @@
From 28de38768e2c7d763b9aa5b7a4d251d5e56bab0b Mon Sep 17 00:00:00 2001
From: RinSatsuki <aa65535@live.com>
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=<time>
Set a maximum TTL value for entries in the cache.
.TP
+.B --min-cache-ttl=<time>
+Extend short TTL values to the time given when caching them. Note that
+artificially extending TTL values is in general a bad idea, do not do it
+unless you have a good reason, and understand what you are doing.
+Dnsmasq limits the value of this option to one hour, unless recompiled.
+.TP
.B --auth-ttl=<time>
Set the TTL value returned in answers from the authoritative server.
.TP
diff --git a/src/cache.c b/src/cache.c
index 960bb7938778..945be071a0b6 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -461,9 +461,11 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
{
log_query(flags | F_UPSTREAM, name, addr, NULL);
- /* Don;t mess with TTL for DNSSEC records. */
+ /* Don't mess with TTL for DNSSEC records. */
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
ttl = daemon->max_cache_ttl;
+ if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
+ ttl = daemon->min_cache_ttl;
}
/* if previous insertion failed give up now. */
diff --git a/src/config.h b/src/config.h
index 3b88d8193dca..cdca231b4079 100644
--- a/src/config.h
+++ b/src/config.h
@@ -27,6 +27,7 @@
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */
+#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */
#define MAXLEASES 1000 /* maximum number of DHCP leases */
#define PING_WAIT 3 /* wait for ping address-in-use test */
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 4e9aea401b75..f8275e3ac479 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -943,7 +943,7 @@ extern struct daemon {
int max_logs; /* queue limit */
int cachesize, ftabsize;
int port, query_port, min_port;
- unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
+ unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp, *dhcp6;
struct ra_interface *ra_interfaces;
diff --git a/src/option.c b/src/option.c
index b7372be0a090..8b994098cc9f 100644
--- a/src/option.c
+++ b/src/option.c
@@ -148,6 +148,7 @@ struct myoption {
#define LOPT_DNSSEC_TIME 336
#define LOPT_LOOP_DETECT 337
#define LOPT_IGNORE_ADDR 338
+#define LOPT_MINCTTL 339
#ifdef HAVE_GETOPT_LONG
@@ -256,6 +257,7 @@ static const struct myoption opts[] =
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL },
+ { "min-cache-ttl", 1, 0, LOPT_MINCTTL },
{ "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
{ "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
{ "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
@@ -371,6 +373,8 @@ static struct {
{ 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
{ LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
{ LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
+ { LOPT_MAXCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live ceiling for cache."), NULL },
+ { LOPT_MINCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live floor for cache."), NULL },
{ 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
{ 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
{ 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
@@ -2457,6 +2461,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case 'T': /* --local-ttl */
case LOPT_NEGTTL: /* --neg-ttl */
case LOPT_MAXTTL: /* --max-ttl */
+ case LOPT_MINCTTL: /* --min-cache-ttl */
case LOPT_MAXCTTL: /* --max-cache-ttl */
case LOPT_AUTHTTL: /* --auth-ttl */
{
@@ -2467,6 +2472,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->neg_ttl = (unsigned long)ttl;
else if (option == LOPT_MAXTTL)
daemon->max_ttl = (unsigned long)ttl;
+ else if (option == LOPT_MINCTTL)
+ {
+ if (ttl > TTL_FLOOR_LIMIT)
+ ttl = TTL_FLOOR_LIMIT;
+ daemon->min_cache_ttl = (unsigned long)ttl;
+ }
else if (option == LOPT_MAXCTTL)
daemon->max_cache_ttl = (unsigned long)ttl;
else if (option == LOPT_AUTHTTL)
--
2.1.0

View File

@@ -1,31 +0,0 @@
From 9f79ee4ae34886c0319f06d8f162b81ef79d62fb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 12 Jan 2015 20:18:18 +0000
Subject: [PATCH 029/113] Log port of requestor when doing extra logging.
---
src/cache.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 945be071a0b6..09b6dbf8087a 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1642,11 +1642,11 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
if (option_bool(OPT_EXTRALOG))
{
- prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
+ int port = 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);
+ my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, 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);
+ my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest);
}
else
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
--
2.1.0

View File

@@ -1,45 +0,0 @@
From 5e321739db381a1d7b5964d76e9c81471d2564c9 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 12 Jan 2015 23:16:56 +0000
Subject: [PATCH 030/113] Don't answer from cache RRsets from wildcards, as we
don't have NSECs.
---
src/dnssec.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index afb3dca38cb1..d39ab85ed966 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -1818,11 +1818,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
struct blockdata *key;
struct crec *crecp;
char *wildname;
+ int have_wildcard = 0;
rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0);
if (rc == STAT_SECURE_WILDCARD)
{
+ have_wildcard = 1;
+
/* An attacker replay a wildcard answer with a different
answer and overlay a genuine RR. To prove this
hasn't happened, the answer must prove that
@@ -1913,7 +1916,11 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
p2 += 13; /* labels, orig_ttl, expiration, inception */
GETSHORT(keytag, p2);
- if ((key = blockdata_alloc((char*)psave, rdlen2)))
+ /* We don't cache sigs for wildcard answers, because to reproduce the
+ answer from the cache will require one or more NSEC/NSEC3 records
+ which we don't cache. The lack of the RRSIG ensures that a query for
+ this RRset asking for a secure answer will always be forwarded. */
+ if (!have_wildcard && (key = blockdata_alloc((char*)psave, rdlen2)))
{
if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
blockdata_free(key);
--
2.1.0

View File

@@ -1,25 +0,0 @@
From ae4624bf46b5e37ff1a9a2ba3c927e0dede95adb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 12 Jan 2015 23:22:08 +0000
Subject: [PATCH 031/113] Logs for DS records consistent.
---
src/rfc1035.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 75c4266b47dd..262274fc5b80 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1643,7 +1643,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
{
if (crecp->flags & F_NXDOMAIN)
nxdomain = 1;
- log_query(F_UPSTREAM, name, NULL, "secure no DS");
+ log_query(F_UPSTREAM, name, NULL, "no DS");
}
else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
{
--
2.1.0

View File

@@ -1,58 +0,0 @@
From 393415597c8b5b09558b789ab9ac238dbe3db65d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 18 Jan 2015 22:11:10 +0000
Subject: [PATCH 032/113] Cope with multiple interfaces with the same LL
address.
---
CHANGELOG | 4 ++++
src/auth.c | 5 ++++-
src/util.c | 1 +
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG b/CHANGELOG
index 23fc6d0530cf..bbd7e6619689 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -49,6 +49,10 @@ version 2.73
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.
+
+ Cope with multiple interfaces with the same link-local
+ address. (IPv6 addresses are scoped, so this is allowed.)
+ Thanks to Cory Benfield for help with this.
version 2.72
diff --git a/src/auth.c b/src/auth.c
index a327f16d8c0b..59e05d3da38e 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -413,7 +413,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
peer_addr->in.sin_port = 0;
#ifdef HAVE_IPV6
else
- peer_addr->in6.sin6_port = 0;
+ {
+ peer_addr->in6.sin6_port = 0;
+ peer_addr->in6.sin6_scope_id = 0;
+ }
#endif
for (peers = daemon->auth_peers; peers; peers = peers->next)
diff --git a/src/util.c b/src/util.c
index a729f339e219..d532444da207 100644
--- a/src/util.c
+++ b/src/util.c
@@ -274,6 +274,7 @@ int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
#ifdef HAVE_IPV6
if (s1->sa.sa_family == AF_INET6 &&
s1->in6.sin6_port == s2->in6.sin6_port &&
+ s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&
IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
return 1;
#endif
--
2.1.0

View File

@@ -1,25 +0,0 @@
From 2ae195f5a71f7c5a75717845de1bd72fc7dd67f3 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 18 Jan 2015 22:20:48 +0000
Subject: [PATCH 033/113] Don't treat SERVFAIL as a recoverable error.....
---
src/forward.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/forward.c b/src/forward.c
index 713a64c0fa58..b17bc34f865f 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -737,7 +737,7 @@ void reply_query(int fd, int family, time_t now)
check_for_ignored_address(header, n, daemon->ignore_addr))
return;
- if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
+ if (RCODE(header) == REFUSED &&
!option_bool(OPT_ORDER) &&
forward->forwardall == 0)
/* for broken servers, attempt to send to another one. */
--
2.1.0

View File

@@ -1,419 +0,0 @@
From 5f4dc5c6ca50655ab14f572c7e30815ed74cd51a Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 20 Jan 2015 20:51:02 +0000
Subject: [PATCH 034/113] Add --dhcp-hostsdir config option.
---
CHANGELOG | 5 +++
man/dnsmasq.8 | 9 +++++
src/dnsmasq.c | 28 ++++++++++----
src/dnsmasq.h | 15 ++++++--
src/inotify.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
src/option.c | 22 +++++++++--
6 files changed, 177 insertions(+), 21 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index bbd7e6619689..0076b557e95e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -53,6 +53,11 @@ version 2.73
Cope with multiple interfaces with the same link-local
address. (IPv6 addresses are scoped, so this is allowed.)
Thanks to Cory Benfield for help with this.
+
+ Add --dhcp-hostsdir. This allows addition of new host
+ configurations to a running dnsmasq instance much more
+ cheaply than having dnsmasq re-read all its existing
+ configuration each time.
version 2.72
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 5cfa355dea4a..005b5cca8d1f 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -977,6 +977,15 @@ is given, then read all the files contained in that directory. The advantage of
using this option is the same as for --dhcp-hostsfile: the
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a
+.TP
+.B --dhcp-hostsdir=<path>
+This is exactly equivalent to dhcp-hostfile, except for the following. The path MUST be a
+directory, and not an individual file. Changed or new files within
+the directory are read automatically, without the need to send SIGHUP.
+If a file is deleted for changed after it has been read by dnsmasq, then the
+host record it contained will remain until dnsmasq recieves a SIGHUP, or
+is restarted; ie host records are only added dynamically.
+.TP
.B --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index c0c0589d4ce1..04cc98278f62 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -142,6 +142,9 @@ int main (int argc, char **argv)
set_option_bool(OPT_NOWILD);
reset_option_bool(OPT_CLEVERBIND);
}
+
+ if (daemon->inotify_hosts)
+ die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF);
#endif
if (option_bool(OPT_DNSSEC_VALID))
@@ -316,13 +319,16 @@ int main (int argc, char **argv)
#ifdef HAVE_DNSSEC
blockdata_init();
#endif
+ }
#ifdef HAVE_LINUX_NETWORK
- if (!option_bool(OPT_NO_POLL))
- inotify_dnsmasq_init();
+ if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) ||
+ daemon->dhcp || daemon->doing_dhcp6)
+ inotify_dnsmasq_init();
+ else
+ daemon->inotifyfd = -1;
#endif
- }
-
+
if (option_bool(OPT_DBUS))
#ifdef HAVE_DBUS
{
@@ -745,7 +751,7 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_TFTP
- if (option_bool(OPT_TFTP))
+ if (option_bool(OPT_TFTP))
{
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
@@ -870,7 +876,7 @@ 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))
+ if (daemon->inotifyfd != -1)
{
FD_SET(daemon->inotifyfd, &rset);
bump_maxfd(daemon->inotifyfd, &maxfd);
@@ -943,8 +949,11 @@ int main (int argc, char **argv)
#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);
+ if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now))
+ {
+ if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
+ 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. */
@@ -1385,6 +1394,9 @@ void clear_cache_and_reload(time_t now)
if (option_bool(OPT_ETHERS))
dhcp_read_ethers();
reread_dhcp();
+#ifdef HAVE_LINUX_NETWORK
+ set_dhcp_inotify();
+#endif
dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs();
lease_update_file(now);
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index f8275e3ac479..d841fdc064ad 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -550,13 +550,17 @@ struct resolvc {
#endif
};
-/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */
+/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile and dhcp-hostsdir*/
#define AH_DIR 1
#define AH_INACTIVE 2
+#define AH_WD_DONE 4
struct hostsfile {
struct hostsfile *next;
int flags;
char *fname;
+#ifdef HAVE_LINUX_NETWORK
+ int wd; /* inotify watch descriptor */
+#endif
unsigned int index; /* matches to cache entries for logging */
};
@@ -961,7 +965,7 @@ extern struct daemon {
int doing_ra, doing_dhcp6;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
- struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
+ struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *inotify_hosts;
int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port;
int start_tftp_port, end_tftp_port;
@@ -1197,7 +1201,7 @@ void reset_option_bool(unsigned int opt);
struct hostsfile *expand_filelist(struct hostsfile *list);
char *parse_server(char *arg, union mysockaddr *addr,
union mysockaddr *source_addr, char *interface, int *flags);
-
+int option_read_hostsfile(char *file);
/* forward.c */
void reply_query(int fd, int family, time_t now);
void receive_query(struct listener *listen, time_t now);
@@ -1486,5 +1490,8 @@ int detect_loop(char *query, int type);
/* inotify.c */
#ifdef HAVE_LINUX_NETWORK
void inotify_dnsmasq_init();
-int inotify_check(void);
+int inotify_check(time_t now);
+# ifdef HAVE_DHCP
+void set_dhcp_inotify(void);
+# endif
#endif
diff --git a/src/inotify.c b/src/inotify.c
index 83730008c11b..52a30d7f44db 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -19,6 +19,11 @@
#include <sys/inotify.h>
+#ifdef HAVE_DHCP
+static void check_for_dhcp_inotify(struct inotify_event *in, time_t now);
+#endif
+
+
/* 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.
@@ -40,8 +45,6 @@ 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)
@@ -66,6 +69,7 @@ void inotify_dnsmasq_init()
{
*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 = '/';
@@ -78,7 +82,7 @@ void inotify_dnsmasq_init()
}
}
-int inotify_check(void)
+int inotify_check(time_t now)
{
int hit = 0;
@@ -101,13 +105,116 @@ int inotify_check(void)
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;
+
+#ifdef HAVE_DHCP
+ if (daemon->dhcp || daemon->doing_dhcp6)
+ check_for_dhcp_inotify(in, now);
+#endif
}
}
-
return hit;
}
-#endif
+#ifdef HAVE_DHCP
+/* initialisation for dhcp-hostdir. Set inotify watch for each directory, and read pre-existing files */
+void set_dhcp_inotify(void)
+{
+ struct hostsfile *ah;
-
+ for (ah = daemon->inotify_hosts; ah; ah = ah->next)
+ {
+ DIR *dir_stream = NULL;
+ struct dirent *ent;
+ struct stat buf;
+
+ if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
+ {
+ my_syslog(LOG_ERR, _("bad directory in dhcp-hostsdir %s"), ah->fname);
+ continue;
+ }
+
+ if (!(ah->flags & AH_WD_DONE))
+ {
+ ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
+ ah->flags |= AH_WD_DONE;
+ }
+ /* Read contents of dir _after_ calling add_watch, in the ho[e of avoiding
+ a race which misses files being added as we start */
+ if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
+ {
+ my_syslog(LOG_ERR, _("failed to create inotify for %s"), ah->fname);
+ continue;
+ }
+
+ while ((ent = readdir(dir_stream)))
+ {
+ size_t lendir = strlen(ah->fname);
+ size_t lenfile = strlen(ent->d_name);
+ char *path;
+
+ /* ignore emacs backups and dotfiles */
+ if (lenfile == 0 ||
+ ent->d_name[lenfile - 1] == '~' ||
+ (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
+ ent->d_name[0] == '.')
+ continue;
+
+ if ((path = whine_malloc(lendir + lenfile + 2)))
+ {
+ strcpy(path, ah->fname);
+ strcat(path, "/");
+ strcat(path, ent->d_name);
+
+ /* ignore non-regular files */
+ if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
+ option_read_hostsfile(path);
+
+ free(path);
+ }
+ }
+ }
+}
+
+static void check_for_dhcp_inotify(struct inotify_event *in, time_t now)
+{
+ struct hostsfile *ah;
+
+ /* ignore emacs backups and dotfiles */
+ if (in->len == 0 ||
+ in->name[in->len - 1] == '~' ||
+ (in->name[0] == '#' && in->name[in->len - 1] == '#') ||
+ in->name[0] == '.')
+ return;
+
+ for (ah = daemon->inotify_hosts; ah; ah = ah->next)
+ if (ah->wd == in->wd)
+ {
+ size_t lendir = strlen(ah->fname);
+ char *path;
+
+ if ((path = whine_malloc(lendir + in->len + 2)))
+ {
+ strcpy(path, ah->fname);
+ strcat(path, "/");
+ strcat(path, in->name);
+
+ if (option_read_hostsfile(path))
+ {
+ /* Propogate the consequences of loading a new dhcp-host */
+ dhcp_update_configs(daemon->dhcp_conf);
+ lease_update_from_configs();
+ lease_update_file(now);
+ lease_update_dns(1);
+ }
+
+ free(path);
+ }
+
+ return;
+ }
+}
+
+#endif /* DHCP */
+
+#endif /* LINUX_NETWORK */
diff --git a/src/option.c b/src/option.c
index 8b994098cc9f..22e11c37d374 100644
--- a/src/option.c
+++ b/src/option.c
@@ -149,7 +149,7 @@ struct myoption {
#define LOPT_LOOP_DETECT 337
#define LOPT_IGNORE_ADDR 338
#define LOPT_MINCTTL 339
-
+#define LOPT_DHCP_INOTIFY 340
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -248,6 +248,7 @@ static const struct myoption opts[] =
{ "interface-name", 1, 0, LOPT_INTNAME },
{ "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
{ "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
+ { "dhcp-hostsdir", 1, 0, LOPT_DHCP_INOTIFY },
{ "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
{ "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
@@ -336,6 +337,7 @@ static struct {
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
{ LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
{ LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
+ { LOPT_DHCP_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from a directory."), NULL },
{ LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
{ 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
{ 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
@@ -1710,8 +1712,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
#endif /* HAVE_DHCP */
- case LOPT_DHCP_HOST: /* --dhcp-hostfile */
+ case LOPT_DHCP_HOST: /* --dhcp-hostsfile */
case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
+ case LOPT_DHCP_INOTIFY: /* dhcp-hostsdir */
case 'H': /* --addn-hosts */
{
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
@@ -1734,6 +1737,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->next = daemon->dhcp_opts_file;
daemon->dhcp_opts_file = new;
}
+ else if (option == LOPT_DHCP_INOTIFY)
+ {
+ new->next = daemon->inotify_hosts;
+ daemon->inotify_hosts = new;
+ }
+
break;
}
@@ -4042,6 +4051,13 @@ static void read_file(char *file, FILE *f, int hard_opt)
fclose(f);
}
+#ifdef HAVE_DHCP
+int option_read_hostsfile(char *file)
+{
+ return one_file(file, LOPT_BANK);
+}
+#endif
+
static int one_file(char *file, int hard_opt)
{
FILE *f;
@@ -4139,7 +4155,7 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
/* don't read this as a file */
ah->flags |= AH_INACTIVE;
-
+
if (!(dir_stream = opendir(ah->fname)))
my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
ah->fname, strerror(errno));
--
2.1.0

View File

@@ -1,327 +0,0 @@
From fbf01f7046e75f9aa73fd4aab2a94e43386d9052 Mon Sep 17 00:00:00 2001
From: Conrad Kostecki <ck@conrad-kostecki.de>
Date: Tue, 20 Jan 2015 21:07:56 +0000
Subject: [PATCH 035/113] Update German translation.
---
po/de.po | 101 +++++++++++++++++++++++++++++----------------------------------
1 file changed, 47 insertions(+), 54 deletions(-)
diff --git a/po/de.po b/po/de.po
index e2317376d8a9..4c93c5b28ef2 100644
--- a/po/de.po
+++ b/po/de.po
@@ -9,10 +9,10 @@
# Simon Kelley <simon@thekelleys.org.uk>, 2005.
msgid ""
msgstr ""
-"Project-Id-Version: dnsmasq 2.70\n"
+"Project-Id-Version: dnsmasq 2.73\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2014-05-01 22:51+0100\n"
+"PO-Revision-Date: 2015-01-19 15:43+0100\n"
"Last-Translator: Conrad Kostecki <ck@conrad-kostecki.de>\n"
"Language-Team: German <de@li.org>\n"
"Language: de\n"
@@ -20,12 +20,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 1.6.5\n"
+"X-Generator: Poedit 1.7.3\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: cache.c:505
msgid "Internal error in cache."
-msgstr ""
+msgstr "Interner Fehler im Cache."
#: cache.c:908
#, c-format
@@ -126,7 +126,7 @@ msgstr "Lokale abzuhörende Adresse(n) angeben."
#: option.c:319
msgid "Return ipaddr for all hosts in specified domains."
-msgstr "IP-Adresse für alle Hosts in angebenen Domänen festlegen."
+msgstr "IP-Adresse für alle Hosts in angegebenen Domänen festlegen."
# FIXME: the English test is not to the point. Just use a shortened description
# from the manpage instead. -- MA
@@ -310,18 +310,16 @@ msgid "Specify path to resolv.conf (defaults to %s)."
msgstr "Pfad zu resolv.conf festlegen (%s voreingestellt)."
#: option.c:362
-#, fuzzy
msgid "Specify path to file with server= options"
-msgstr "Dateipfad für Prozesskennung (PID) festlegen (Voreinstellung: %s)."
+msgstr " Dateipfad mit der Option server= angeben"
#: option.c:363
msgid "Specify address(es) of upstream servers with optional domains."
msgstr "Adresse(n) vorgelagerter Server festlegen, optional mit Domänen."
#: option.c:364
-#, fuzzy
msgid "Specify address of upstream servers for reverse address queries"
-msgstr "Adresse(n) vorgelagerter Server festlegen, optional mit Domänen."
+msgstr "Adresse(n) vorgelagerter Server festlegen, für reverse Adressanfragen"
#: option.c:365
msgid "Never forward queries to specified domains."
@@ -657,23 +655,23 @@ msgstr "Spezifiziere eine Domain und Adressbereich für synthetisierte Namen"
#: option.c:446
msgid "Activate DNSSEC validation"
-msgstr ""
+msgstr "Aktiviere DNSSEC-Validierung"
#: option.c:447
msgid "Specify trust anchor key digest."
-msgstr ""
+msgstr "Spezifiziere Vertrauensursprung (Trust Anchor) der Schlüssel-Prüfdaten (Key Digest)."
#: option.c:448
msgid "Disable upstream checking for DNSSEC debugging."
-msgstr ""
+msgstr "Deaktiviere die Überprüfung vorgelagerter Server für DNSSEC-Debugging"
#: option.c:449
msgid "Ensure answers without DNSSEC are in unsigned zones."
-msgstr ""
+msgstr "Stellt sicher, dass Antworten ohne DNSSEC sich in einer unsignierten Zone befinden."
#: option.c:450
msgid "Don't check DNSSEC signature timestamps until first cache-reload"
-msgstr ""
+msgstr "DNSSEC Signatur-Zeitstempel nicht prüfen, bis erstmalig der Cache neugeladen wird"
#: option.c:452
msgid "Specify DHCPv6 prefix class"
@@ -697,11 +695,11 @@ msgstr "RA nicht protokollieren."
#: option.c:458
msgid "Accept queries only from directly-connected networks"
-msgstr ""
+msgstr "Akzeptiere nur Anfragen von direkt verbundenen Netzwerken"
#: option.c:459
msgid "Detect and remove DNS forwarding loops"
-msgstr ""
+msgstr "Erkennen und Entfernen von DNS-Weiterleitungsschleifen"
#: option.c:661
#, c-format
@@ -958,18 +956,16 @@ msgid "Bad name in host-record"
msgstr "Unzulässiger Name in host-record"
#: option.c:3826
-#, fuzzy
msgid "bad trust anchor"
-msgstr "unzulässiger Portbereich"
+msgstr "unzulässiger Vertrauensursprung (Trust Anchor)"
#: option.c:3840
msgid "bad HEX in trust anchor"
-msgstr ""
+msgstr "unzulässiger Hexwert in Vertrauensursprung (Trust Anchor)"
#: option.c:3850
-#, fuzzy
msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
-msgstr "unzulässige Option (prüfen Sie, ob dnsmasq mit DHCP/TFTP/DBus-Unterstützt übersetzt wurde)"
+msgstr "Nicht unterstützte Option (prüfen Sie, ob DNSMasq mit DHCP/TFTP/DNSSEC/DBus-Unterstützung übersetzt wurde)"
#: option.c:3909
msgid "missing \""
@@ -988,7 +984,6 @@ msgid "missing parameter"
msgstr "fehler Parameter"
#: option.c:3972
-#, fuzzy
msgid "illegal option"
msgstr "unzulässige Option"
@@ -1110,7 +1105,7 @@ msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s"
#: forward.c:1132 forward.c:1663
msgid "Ignoring query from non-local network"
-msgstr ""
+msgstr "Ignoriere Anfragen vom nicht lokalen Netzwerk"
#: forward.c:2101
#, c-format
@@ -1189,9 +1184,9 @@ msgid "using nameserver %s#%d for %s %s"
msgstr "Benutze Namensserver %s#%d für %s %s"
#: network.c:1483
-#, fuzzy, c-format
+#, c-format
msgid "NOT using nameserver %s#%d - query loop detected"
-msgstr "Benutze Namensserver %s#%d für %s %s"
+msgstr "Benutze Namensserver %s#%d NICHT - Anfragenschleife festgetellt"
#: network.c:1486
#, c-format
@@ -1205,16 +1200,15 @@ msgstr "Benutze Namensserver %s#%d"
#: dnsmasq.c:154
msgid "No trust anchors provided for DNSSEC"
-msgstr ""
+msgstr "Keine Vertrauensursprünge (Trust Anchor) für DNSSEC verfügbar"
#: dnsmasq.c:157
msgid "Cannot reduce cache size from default when DNSSEC enabled"
-msgstr ""
+msgstr "Kann die Standard Cachegröße nicht verkleinern, wenn DNSSEC aktiviert ist"
#: dnsmasq.c:159
-#, fuzzy
msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
-msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
+msgstr "DNSSEC nicht verfügbar: setzen Sie HAVE_DNSSEC in src/config.h"
#: dnsmasq.c:165
msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
@@ -1241,9 +1235,8 @@ msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
msgstr "Authoritatives DNS nicht verfügbar: Es muss HAVE_AUTH in src/config.h gesetzt sein"
#: dnsmasq.c:193
-#, fuzzy
msgid "Loop detection not available: set HAVE_LOOP in src/config.h"
-msgstr "TFTP-Server nicht verfügbar, setzen Sie HAVE_TFTP in src/config.h"
+msgstr "Loop-Erkennung nicht verfügbar, setzen Sie HAVE_LOOP in src/config.h"
#: dnsmasq.c:201
msgid "zone serial must be configured in --auth-soa"
@@ -1317,15 +1310,15 @@ msgstr "DBus-Unterstützung eingeschaltet: warte auf Systembus-Verbindung"
#: dnsmasq.c:672
msgid "DNS service limited to local subnets"
-msgstr ""
+msgstr "DNS-Dienst auf lokale Subnetze eingeschränkt"
#: dnsmasq.c:677
msgid "DNSSEC validation enabled"
-msgstr ""
+msgstr "DNSSEC-Validierung aktiviert"
#: dnsmasq.c:679
msgid "DNSSEC signature timestamps not checked until first cache reload"
-msgstr ""
+msgstr "DNSSEC Signatur-Zeitstempel werden erst ab dem ersten Neuladen des Caches überprüft"
#: dnsmasq.c:684
#, c-format
@@ -1366,7 +1359,7 @@ msgstr "DHCP, Sockets exklusiv an das Interface %s gebunden"
# FIXME: this and the next few must be full strings to be translatable - do not assemble in code"
#: dnsmasq.c:753
msgid "root is "
-msgstr "Wurzel ist"
+msgstr "Wurzel ist "
#: dnsmasq.c:753
msgid "enabled"
@@ -1432,7 +1425,7 @@ msgstr "Das TFTP-Verzeichnis %s ist nicht zugreifbar: %s"
#: dnsmasq.c:1151
msgid "now checking DNSSEC signature timestamps"
-msgstr ""
+msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel"
#: dnsmasq.c:1218
#, c-format
@@ -1506,7 +1499,7 @@ msgstr "DHCP-Paket ohne Adresse an Schnittstelle %s empfangen"
#: dhcp.c:408
#, c-format
msgid "ARP-cache injection failed: %s"
-msgstr ""
+msgstr "APR-Cache Injektion fehlgeschlagen: %s"
#: dhcp.c:506
#, c-format
@@ -1763,13 +1756,13 @@ msgid "DHCP request for unsupported hardware type (%d) received on %s"
msgstr "DHCP-Anfrage für nicht unterstützen Hardwaretyp (%d) auf %s empfangen"
#: bpf.c:376
-#, fuzzy, c-format
+#, c-format
msgid "cannot create PF_ROUTE socket: %s"
-msgstr "kann DHCP-Socket nicht erzeugen: %s"
+msgstr "Kann PF_ROUTE socket nicht erzeugen: %s"
#: bpf.c:397
msgid "Unknown protocol version from route socket"
-msgstr ""
+msgstr "Unbekannte Protokollversion vom Route Socket"
#: helper.c:153
msgid "lease() function missing in Lua script"
@@ -2020,50 +2013,50 @@ msgstr "konnte IPset-Kontroll-Socket nicht erzeugen: %s"
#: blockdata.c:58
#, c-format
msgid "DNSSEC memory in use %u, max %u, allocated %u"
-msgstr ""
+msgstr "DNSSEC Speicher in Benutzung %u, Max %u, zugewiesen %u"
#: tables.c:76
msgid "error: fill_addr missused"
-msgstr ""
+msgstr "Fehler: fill_addr falsch verwendet"
#: tables.c:105
-#, fuzzy, c-format
+#, c-format
msgid "failed to access pf devices: %s"
-msgstr "konnte auf %s nicht zugreifen: %s"
+msgstr "konnte auf pf Geräte nicht zugreifen: %s"
#: tables.c:119
-#, fuzzy, c-format
+#, c-format
msgid "warning: no opened pf devices %s"
-msgstr "Warnung: Keine Adresse für die Schnittstelle %s gefunden"
+msgstr "Warnung: Keine geöffneten pf Geräte %s"
#: tables.c:127
-#, fuzzy, c-format
+#, c-format
msgid "error: cannot use table name %s"
-msgstr "kann Hostnamen nicht ermitteln: %s"
+msgstr "Fehler: Kann Tabellenname %s nicht benutzen"
#: tables.c:135
#, c-format
msgid "error: cannot strlcpy table name %s"
-msgstr ""
+msgstr "Fehler: Kann den Tabellennamen %s nicht strlcpy"
#: tables.c:141
#, c-format
msgid "warning: pfr_add_tables: %s(%d)"
-msgstr ""
+msgstr "Warnung: pfr_add_tables: %s(%d)"
#: tables.c:147
msgid "info: table created"
-msgstr ""
+msgstr "Info: Tabelle erstellt"
#: tables.c:158
#, c-format
msgid "warning: DIOCR%sADDRS: %s"
-msgstr ""
+msgstr "Warnung: DIOCR%sADDRS: %s"
#: tables.c:162
-#, fuzzy, c-format
+#, c-format
msgid "%d addresses %s"
-msgstr "Fehlerhafte Adresse"
+msgstr "%d Adressen %s"
#~ msgid "no interface with address %s"
#~ msgstr "keine Schnittstelle mit Adresse %s"
--
2.1.0

View File

@@ -1,53 +0,0 @@
From 61b838dd574c51d96fef100285a0d225824534f9 Mon Sep 17 00:00:00 2001
From: Win King Wan <pinwing+dnsmasq@gmail.com>
Date: Wed, 21 Jan 2015 20:41:48 +0000
Subject: [PATCH 036/113] Don't reply to DHCPv6 SOLICIT messages when not
configured for statefull DHCPv6.
---
CHANGELOG | 4 ++++
src/rfc3315.c | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 0076b557e95e..a4cb901e83ae 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -59,6 +59,10 @@ version 2.73
cheaply than having dnsmasq re-read all its existing
configuration each time.
+ Don't reply to DHCPv6 SOLICIT messages if we're not
+ configured to do stateful DHCPv6. Thanks to Win King Wan
+ for the patch.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/rfc3315.c b/src/rfc3315.c
index ddb390bf1136..e593ec9c362c 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -824,6 +824,19 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
else
{
+ /* Windows 8 always requests an address even if the Managed bit
+ in RA is 0 and it keeps retrying if it receives a reply
+ stating that no addresses are available. We solve this
+ by not replying at all if we're not configured to give any
+ addresses by DHCPv6. RFC 3315 17.2.1. appears to allow this. */
+
+ for (c = state->context; c; c = c->current)
+ if (!(c->flags & CONTEXT_RA_STATELESS))
+ break;
+
+ if (!c)
+ return 0;
+
/* no address, return error */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOADDRS);
--
2.1.0

View File

@@ -1,214 +0,0 @@
From 0491805d2ff6e7727f0272c94fd97d9897d1e22c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 26 Jan 2015 11:23:43 +0000
Subject: [PATCH 037/113] Allow inotify to be disabled at compile time on
Linux.
---
CHANGELOG | 4 +++-
src/config.h | 13 ++++++++++++-
src/dnsmasq.c | 21 +++++++++++++--------
src/dnsmasq.h | 11 +++++++----
src/inotify.c | 4 ++--
5 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index a4cb901e83ae..c05dec63c587 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,7 +9,9 @@ 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.
+ updated rapidly and saves CPU by noy polling. To build
+ a binary that runs on old Linux kernels without inotify,
+ use make COPTS=-DNO_INOTIFY
Fix breakage of --domain=<domain>,<subnet>,local - only reverse
queries were intercepted. THis appears to have been broken
diff --git a/src/config.h b/src/config.h
index cdca231b4079..5e5009271eba 100644
--- a/src/config.h
+++ b/src/config.h
@@ -115,6 +115,8 @@ HAVE_DNSSEC
HAVE_LOOP
include functionality to probe for and remove DNS forwarding loops.
+HAVE_INOTIFY
+ use the Linux inotify facility to efficiently re-read configuration files.
NO_IPV6
NO_TFTP
@@ -123,6 +125,7 @@ NO_DHCP6
NO_SCRIPT
NO_LARGEFILE
NO_AUTH
+NO_INOTIFY
these are avilable to explictly disable compile time options which would
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
which are enabled by default in the distributed source tree. Building dnsmasq
@@ -355,6 +358,10 @@ HAVE_SOCKADDR_SA_LEN
#undef HAVE_LOOP
#endif
+#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
+#define HAVE_INOTIFY
+#endif
+
/* Define a string indicating which options are in use.
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
@@ -428,7 +435,11 @@ static char *compile_opts =
#ifndef HAVE_LOOP
"no-"
#endif
-"loop-detect";
+"loop-detect "
+#ifndef HAVE_INOTIFY
+"no-"
+#endif
+"inotify";
#endif
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 04cc98278f62..bc4f47170705 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -142,7 +142,9 @@ int main (int argc, char **argv)
set_option_bool(OPT_NOWILD);
reset_option_bool(OPT_CLEVERBIND);
}
+#endif
+#ifndef HAVE_INOTIFY
if (daemon->inotify_hosts)
die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF);
#endif
@@ -321,7 +323,7 @@ int main (int argc, char **argv)
#endif
}
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) ||
daemon->dhcp || daemon->doing_dhcp6)
inotify_dnsmasq_init();
@@ -802,7 +804,7 @@ int main (int argc, char **argv)
pid = getpid();
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
/* Using inotify, have to select a resolv file at startup */
poll_resolv(1, 0, now);
#endif
@@ -872,15 +874,18 @@ int main (int argc, char **argv)
bump_maxfd(daemon->icmp6fd, &maxfd);
}
#endif
-
-#if defined(HAVE_LINUX_NETWORK)
- FD_SET(daemon->netlinkfd, &rset);
- bump_maxfd(daemon->netlinkfd, &maxfd);
+
+#ifdef HAVE_INOTIFY
if (daemon->inotifyfd != -1)
{
FD_SET(daemon->inotifyfd, &rset);
bump_maxfd(daemon->inotifyfd, &maxfd);
}
+#endif
+
+#if defined(HAVE_LINUX_NETWORK)
+ FD_SET(daemon->netlinkfd, &rset);
+ bump_maxfd(daemon->netlinkfd, &maxfd);
#elif defined(HAVE_BSD_NETWORK)
FD_SET(daemon->routefd, &rset);
bump_maxfd(daemon->routefd, &maxfd);
@@ -948,7 +953,7 @@ int main (int argc, char **argv)
route_sock();
#endif
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now))
{
if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
@@ -1394,7 +1399,7 @@ void clear_cache_and_reload(time_t now)
if (option_bool(OPT_ETHERS))
dhcp_read_ethers();
reread_dhcp();
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
set_dhcp_inotify();
#endif
dhcp_update_configs(daemon->dhcp_conf);
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index d841fdc064ad..8091634f69db 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -544,7 +544,7 @@ struct resolvc {
int is_default, logged;
time_t mtime;
char *name;
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
int wd; /* inotify watch descriptor */
char *file; /* pointer to file part if path */
#endif
@@ -558,7 +558,7 @@ struct hostsfile {
struct hostsfile *next;
int flags;
char *fname;
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
int wd; /* inotify watch descriptor */
#endif
unsigned int index; /* matches to cache entries for logging */
@@ -1013,8 +1013,11 @@ extern struct daemon {
/* DHCP state */
int dhcpfd, helperfd, pxefd;
+#ifdef HAVE_INOTIFY
+ int inotifyfd;
+#endif
#if defined(HAVE_LINUX_NETWORK)
- int netlinkfd, inotifyfd;
+ int netlinkfd;
#elif defined(HAVE_BSD_NETWORK)
int dhcp_raw_fd, dhcp_icmp_fd, routefd;
#endif
@@ -1488,7 +1491,7 @@ int detect_loop(char *query, int type);
#endif
/* inotify.c */
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
void inotify_dnsmasq_init();
int inotify_check(time_t now);
# ifdef HAVE_DHCP
diff --git a/src/inotify.c b/src/inotify.c
index 52a30d7f44db..818fe8eddda4 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -15,7 +15,7 @@
*/
#include "dnsmasq.h"
-#ifdef HAVE_LINUX_NETWORK
+#ifdef HAVE_INOTIFY
#include <sys/inotify.h>
@@ -216,5 +216,5 @@ static void check_for_dhcp_inotify(struct inotify_event *in, time_t now)
#endif /* DHCP */
-#endif /* LINUX_NETWORK */
+#endif /* INOTIFY */
--
2.1.0

View File

@@ -1,562 +0,0 @@
From 70d1873dd9e70041ed4bb88c69d5b886b7cc634c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 31 Jan 2015 19:59:29 +0000
Subject: [PATCH 038/113] Expand inotify code to dhcp-hostsdir, dhcp-optsdir
and hostsdir.
---
src/cache.c | 81 +++++++++++++++++---------
src/dnsmasq.c | 9 ++-
src/dnsmasq.h | 14 +++--
src/inotify.c | 179 +++++++++++++++++++++++++++++-----------------------------
src/option.c | 37 +++++++++---
5 files changed, 187 insertions(+), 133 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 09b6dbf8087a..abaf25ec0f18 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -835,27 +835,42 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
Only insert each unique address once into this hashing structure.
This complexity avoids O(n^2) divergent CPU use whilst reading
- large (10000 entry) hosts files. */
-
- /* hash address */
- for (j = 0, i = 0; i < addrlen; i++)
- j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
-
- for (lookup = rhash[j]; lookup; lookup = lookup->next)
- if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
- memcmp(&lookup->addr.addr, addr, addrlen) == 0)
- {
- cache->flags &= ~F_REVERSE;
- break;
- }
+ large (10000 entry) hosts files.
+
+ Note that we only do this process when bulk-reading hosts files,
+ for incremental reads, rhash is NULL, and we use cache lookups
+ instead.
+ */
- /* maintain address hash chain, insert new unique address */
- if (!lookup)
+ if (rhash)
{
- cache->next = rhash[j];
- rhash[j] = cache;
+ /* hash address */
+ for (j = 0, i = 0; i < addrlen; i++)
+ j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
+
+ for (lookup = rhash[j]; lookup; lookup = lookup->next)
+ if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
+ memcmp(&lookup->addr.addr, addr, addrlen) == 0)
+ {
+ cache->flags &= ~F_REVERSE;
+ break;
+ }
+
+ /* maintain address hash chain, insert new unique address */
+ if (!lookup)
+ {
+ cache->next = rhash[j];
+ rhash[j] = cache;
+ }
}
-
+ else
+ {
+ /* incremental read, lookup in cache */
+ lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6));
+ if (lookup && lookup->flags & F_HOSTS)
+ cache->flags &= ~F_REVERSE;
+ }
+
cache->uid = index;
memcpy(&cache->addr.addr, addr, addrlen);
cache_hash(cache);
@@ -912,7 +927,7 @@ static int gettok(FILE *f, char *token)
}
}
-static int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
+int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
{
FILE *f = fopen(filename, "r");
char *token = daemon->namebuff, *domain_suffix = NULL;
@@ -958,7 +973,7 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st
addr_count++;
/* rehash every 1000 names. */
- if ((name_count - cache_size) > 1000)
+ if (rhash && ((name_count - cache_size) > 1000))
{
rehash(name_count);
cache_size = name_count;
@@ -1005,10 +1020,13 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st
}
fclose(f);
- rehash(name_count);
-
- my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
+ if (rhash)
+ {
+ rehash(name_count);
+ my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
+ }
+
return name_count;
}
@@ -1118,14 +1136,19 @@ void cache_reload(void)
my_syslog(LOG_INFO, _("cleared cache"));
return;
}
-
+
if (!option_bool(OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
-
+
daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (!(ah->flags & AH_INACTIVE))
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
+
+#ifdef HAVE_INOTIFY
+ set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
+#endif
+
}
#ifdef HAVE_DHCP
@@ -1505,7 +1528,13 @@ char *record_source(unsigned int index)
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (ah->index == index)
return ah->fname;
-
+
+#ifdef HAVE_INOTIFY
+ for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
+ if (ah->index == index)
+ return ah->fname;
+#endif
+
return "<unknown>";
}
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index bc4f47170705..2c629fe422aa 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -145,8 +145,8 @@ int main (int argc, char **argv)
#endif
#ifndef HAVE_INOTIFY
- if (daemon->inotify_hosts)
- die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF);
+ if (daemon->dynamic_dirs)
+ die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
#endif
if (option_bool(OPT_DNSSEC_VALID))
@@ -324,8 +324,7 @@ int main (int argc, char **argv)
}
#ifdef HAVE_INOTIFY
- if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) ||
- daemon->dhcp || daemon->doing_dhcp6)
+ if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
inotify_dnsmasq_init();
else
daemon->inotifyfd = -1;
@@ -1400,7 +1399,7 @@ void clear_cache_and_reload(time_t now)
dhcp_read_ethers();
reread_dhcp();
#ifdef HAVE_INOTIFY
- set_dhcp_inotify();
+ set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
#endif
dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs();
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 8091634f69db..0c322a93993e 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -554,6 +554,9 @@ struct resolvc {
#define AH_DIR 1
#define AH_INACTIVE 2
#define AH_WD_DONE 4
+#define AH_HOSTS 8
+#define AH_DHCP_HST 16
+#define AH_DHCP_OPT 32
struct hostsfile {
struct hostsfile *next;
int flags;
@@ -965,7 +968,7 @@ extern struct daemon {
int doing_ra, doing_dhcp6;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
- struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *inotify_hosts;
+ struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs;
int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port;
int start_tftp_port, end_tftp_port;
@@ -1071,6 +1074,8 @@ int cache_make_stat(struct txt_record *t);
char *cache_get_name(struct crec *crecp);
char *cache_get_cname_target(struct crec *crecp);
struct crec *cache_enumerate(int init);
+int read_hostsfile(char *filename, unsigned int index, int cache_size,
+ struct crec **rhash, int hashsz);
/* blockdata.c */
#ifdef HAVE_DNSSEC
@@ -1204,7 +1209,8 @@ void reset_option_bool(unsigned int opt);
struct hostsfile *expand_filelist(struct hostsfile *list);
char *parse_server(char *arg, union mysockaddr *addr,
union mysockaddr *source_addr, char *interface, int *flags);
-int option_read_hostsfile(char *file);
+int option_read_dynfile(char *file, int flags);
+
/* forward.c */
void reply_query(int fd, int family, time_t now);
void receive_query(struct listener *listen, time_t now);
@@ -1494,7 +1500,5 @@ int detect_loop(char *query, int type);
#ifdef HAVE_INOTIFY
void inotify_dnsmasq_init();
int inotify_check(time_t now);
-# ifdef HAVE_DHCP
-void set_dhcp_inotify(void);
-# endif
+void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
#endif
diff --git a/src/inotify.c b/src/inotify.c
index 818fe8eddda4..c537f4c1562a 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -19,11 +19,6 @@
#include <sys/inotify.h>
-#ifdef HAVE_DHCP
-static void check_for_dhcp_inotify(struct inotify_event *in, time_t now);
-#endif
-
-
/* 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.
@@ -82,57 +77,28 @@ void inotify_dnsmasq_init()
}
}
-int inotify_check(time_t now)
+
+/* initialisation for dynamic-dir. Set inotify watch for each directory, and read pre-existing files */
+void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)
{
- int hit = 0;
+ struct hostsfile *ah;
- while (1)
+ for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
{
- 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)
+ DIR *dir_stream = NULL;
+ struct dirent *ent;
+ struct stat buf;
+
+ if (!(ah->flags & flag))
+ continue;
+
+ if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
{
- 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;
-
-#ifdef HAVE_DHCP
- if (daemon->dhcp || daemon->doing_dhcp6)
- check_for_dhcp_inotify(in, now);
-#endif
+ my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
+ ah->fname, strerror(errno));
+ continue;
}
- }
- return hit;
-}
-
-#ifdef HAVE_DHCP
-/* initialisation for dhcp-hostdir. Set inotify watch for each directory, and read pre-existing files */
-void set_dhcp_inotify(void)
-{
- struct hostsfile *ah;
-
- for (ah = daemon->inotify_hosts; ah; ah = ah->next)
- {
- DIR *dir_stream = NULL;
- struct dirent *ent;
- struct stat buf;
-
- if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
- {
- my_syslog(LOG_ERR, _("bad directory in dhcp-hostsdir %s"), ah->fname);
- continue;
- }
-
+
if (!(ah->flags & AH_WD_DONE))
{
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
@@ -142,7 +108,8 @@ void set_dhcp_inotify(void)
a race which misses files being added as we start */
if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
{
- my_syslog(LOG_ERR, _("failed to create inotify for %s"), ah->fname);
+ my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),
+ ah->fname, strerror(errno));
continue;
}
@@ -167,54 +134,90 @@ void set_dhcp_inotify(void)
/* ignore non-regular files */
if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
- option_read_hostsfile(path);
-
+ {
+ if (ah->flags & AH_HOSTS)
+ total_size = read_hostsfile(path, ah->index, total_size, rhash, revhashsz);
+#ifdef HAVE_DHCP
+ else if (ah->flags & (AH_DHCP_HST | AH_DHCP_OPT))
+ option_read_dynfile(path, ah->flags);
+#endif
+ }
+
free(path);
}
}
}
}
-static void check_for_dhcp_inotify(struct inotify_event *in, time_t now)
+int inotify_check(time_t now)
{
+ int hit = 0;
struct hostsfile *ah;
- /* ignore emacs backups and dotfiles */
- if (in->len == 0 ||
- in->name[in->len - 1] == '~' ||
- (in->name[0] == '#' && in->name[in->len - 1] == '#') ||
- in->name[0] == '.')
- return;
-
- for (ah = daemon->inotify_hosts; ah; ah = ah->next)
- if (ah->wd == in->wd)
- {
- size_t lendir = strlen(ah->fname);
- char *path;
-
- if ((path = whine_malloc(lendir + in->len + 2)))
- {
- strcpy(path, ah->fname);
- strcat(path, "/");
- strcat(path, in->name);
-
- if (option_read_hostsfile(path))
+ 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;
+
+ /* ignore emacs backups and dotfiles */
+ if (in->len == 0 ||
+ in->name[in->len - 1] == '~' ||
+ (in->name[0] == '#' && in->name[in->len - 1] == '#') ||
+ in->name[0] == '.')
+ continue;
+
+ for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
+ if (ah->wd == in->wd)
{
- /* Propogate the consequences of loading a new dhcp-host */
- dhcp_update_configs(daemon->dhcp_conf);
- lease_update_from_configs();
- lease_update_file(now);
- lease_update_dns(1);
+ size_t lendir = strlen(ah->fname);
+ char *path;
+
+ if ((path = whine_malloc(lendir + in->len + 2)))
+ {
+ strcpy(path, ah->fname);
+ strcat(path, "/");
+ strcat(path, in->name);
+
+ if (ah->flags & AH_HOSTS)
+ read_hostsfile(path, ah->index, 0, NULL, 0);
+#ifdef HAVE_DHCP
+ else if (ah->flags & AH_DHCP_HST)
+ {
+ if (option_read_dynfile(path, AH_DHCP_HST))
+ {
+ /* Propogate the consequences of loading a new dhcp-host */
+ dhcp_update_configs(daemon->dhcp_conf);
+ lease_update_from_configs();
+ lease_update_file(now);
+ lease_update_dns(1);
+ }
+ }
+ else if (ah->flags & AH_DHCP_OPT)
+ option_read_dynfile(path, AH_DHCP_OPT);
+#endif
+
+ free(path);
+ }
}
-
- free(path);
- }
-
- return;
- }
+ }
+ }
+ return hit;
}
-#endif /* DHCP */
-
#endif /* INOTIFY */
diff --git a/src/option.c b/src/option.c
index 22e11c37d374..6ef80117cc8c 100644
--- a/src/option.c
+++ b/src/option.c
@@ -150,6 +150,8 @@ struct myoption {
#define LOPT_IGNORE_ADDR 338
#define LOPT_MINCTTL 339
#define LOPT_DHCP_INOTIFY 340
+#define LOPT_DHOPT_INOTIFY 341
+#define LOPT_HOST_INOTIFY 342
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -200,6 +202,7 @@ static const struct myoption opts[] =
{ "local-ttl", 1, 0, 'T' },
{ "no-negcache", 0, 0, 'N' },
{ "addn-hosts", 1, 0, 'H' },
+ { "hostsdir", 1, 0, LOPT_HOST_INOTIFY },
{ "query-port", 1, 0, 'Q' },
{ "except-interface", 1, 0, 'I' },
{ "no-dhcp-interface", 1, 0, '2' },
@@ -249,6 +252,7 @@ static const struct myoption opts[] =
{ "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
{ "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
{ "dhcp-hostsdir", 1, 0, LOPT_DHCP_INOTIFY },
+ { "dhcp-optsdir", 1, 0, LOPT_DHOPT_INOTIFY },
{ "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
{ "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
@@ -338,9 +342,11 @@ static struct {
{ LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL },
{ LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL },
{ LOPT_DHCP_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from a directory."), NULL },
+ { LOPT_DHOPT_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP options from a directory."), NULL },
{ LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
{ 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
{ 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
+ { LOPT_HOST_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read hosts files from a directory."), NULL },
{ 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL },
{ 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
{ 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
@@ -1712,10 +1718,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
#endif /* HAVE_DHCP */
- case LOPT_DHCP_HOST: /* --dhcp-hostsfile */
- case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
- case LOPT_DHCP_INOTIFY: /* dhcp-hostsdir */
- case 'H': /* --addn-hosts */
+ case LOPT_DHCP_HOST: /* --dhcp-hostsfile */
+ case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
+ case LOPT_DHCP_INOTIFY: /* --dhcp-hostsdir */
+ case LOPT_DHOPT_INOTIFY: /* --dhcp-optsdir */
+ case LOPT_HOST_INOTIFY: /* --hostsdir */
+ case 'H': /* --addn-hosts */
{
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
static unsigned int hosts_index = SRC_AH;
@@ -1737,10 +1745,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->next = daemon->dhcp_opts_file;
daemon->dhcp_opts_file = new;
}
- else if (option == LOPT_DHCP_INOTIFY)
+ else
{
- new->next = daemon->inotify_hosts;
- daemon->inotify_hosts = new;
+ new->next = daemon->dynamic_dirs;
+ daemon->dynamic_dirs = new;
+ if (option == LOPT_DHCP_INOTIFY)
+ new->flags |= AH_DHCP_HST;
+ else if (option == LOPT_DHOPT_INOTIFY)
+ new->flags |= AH_DHCP_OPT;
+ else if (option == LOPT_HOST_INOTIFY)
+ new->flags |= AH_HOSTS;
}
break;
@@ -4052,9 +4066,14 @@ static void read_file(char *file, FILE *f, int hard_opt)
}
#ifdef HAVE_DHCP
-int option_read_hostsfile(char *file)
+int option_read_dynfile(char *file, int flags)
{
- return one_file(file, LOPT_BANK);
+ if (flags & AH_DHCP_HST)
+ return one_file(file, LOPT_BANK);
+ else if (flags & AH_DHCP_OPT)
+ return one_file(file, LOPT_OPTS);
+
+ return 0;
}
#endif
--
2.1.0

View File

@@ -1,428 +0,0 @@
From aff3396280e944833f0e23d834aa6acd5fe2605a Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 31 Jan 2015 20:13:40 +0000
Subject: [PATCH 039/113] Update copyrights for dawn of 2015.
---
Makefile | 2 +-
src/auth.c | 2 +-
src/blockdata.c | 2 +-
src/bpf.c | 2 +-
src/cache.c | 2 +-
src/config.h | 2 +-
src/conntrack.c | 2 +-
src/dbus.c | 2 +-
src/dhcp-common.c | 2 +-
src/dhcp-protocol.h | 2 +-
src/dhcp.c | 2 +-
src/dhcp6-protocol.h | 2 +-
src/dhcp6.c | 2 +-
src/dns-protocol.h | 2 +-
src/dnsmasq.c | 2 +-
src/dnsmasq.h | 4 ++--
src/dnssec.c | 2 +-
src/domain.c | 2 +-
src/forward.c | 2 +-
src/helper.c | 2 +-
src/inotify.c | 2 +-
src/ip6addr.h | 2 +-
src/lease.c | 2 +-
src/log.c | 2 +-
src/loop.c | 2 +-
src/netlink.c | 2 +-
src/network.c | 2 +-
src/option.c | 2 +-
src/outpacket.c | 2 +-
src/radv-protocol.h | 2 +-
src/radv.c | 2 +-
src/rfc1035.c | 2 +-
src/rfc2131.c | 2 +-
src/rfc3315.c | 2 +-
src/slaac.c | 2 +-
src/tftp.c | 2 +-
src/util.c | 2 +-
37 files changed, 38 insertions(+), 38 deletions(-)
diff --git a/Makefile b/Makefile
index bcbd5571671d..21e4a5c4101c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+# dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/auth.c b/src/auth.c
index 59e05d3da38e..15721e52793f 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/blockdata.c b/src/blockdata.c
index 5a70a7967fa3..c8f5eae811eb 100644
--- a/src/blockdata.c
+++ b/src/blockdata.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/bpf.c b/src/bpf.c
index 4416b1c07287..997d87421bed 100644
--- a/src/bpf.c
+++ b/src/bpf.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/cache.c b/src/cache.c
index abaf25ec0f18..117ae279fd4e 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/config.h b/src/config.h
index 5e5009271eba..8def6f200461 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/conntrack.c b/src/conntrack.c
index 6a5133ab93af..0fa2da903b03 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dbus.c b/src/dbus.c
index a2a94dc85dac..5b69de518beb 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index 9d13ac8df6f1..ce115202a646 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h
index 4c0961472482..701b6cb3346e 100644
--- a/src/dhcp-protocol.h
+++ b/src/dhcp-protocol.h
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dhcp.c b/src/dhcp.c
index 7acf2c4311a9..f29be9b489a7 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dhcp6-protocol.h b/src/dhcp6-protocol.h
index 5927dc32f6af..928a2fa162ed 100644
--- a/src/dhcp6-protocol.h
+++ b/src/dhcp6-protocol.h
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dhcp6.c b/src/dhcp6.c
index bc48fdddd3de..3c56e77c6085 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dns-protocol.h b/src/dns-protocol.h
index 0aced3ce6952..16fade33d98c 100644
--- a/src/dns-protocol.h
+++ b/src/dns-protocol.h
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 2c629fe422aa..e903a24c8105 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 0c322a93993e..89e758b56a0a 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#define COPYRIGHT "Copyright (c) 2000-2014 Simon Kelley"
+#define COPYRIGHT "Copyright (c) 2000-2015 Simon Kelley"
#ifndef NO_LARGEFILE
/* Ensure we can use files >2GB (log files may grow this big) */
diff --git a/src/dnssec.c b/src/dnssec.c
index d39ab85ed966..a8dfe3871c85 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -1,5 +1,5 @@
/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
- and Copyright (c) 2012-2014 Simon Kelley
+ and Copyright (c) 2012-2015 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
diff --git a/src/domain.c b/src/domain.c
index fdd5e4f0838f..278698ca04b3 100644
--- a/src/domain.c
+++ b/src/domain.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/forward.c b/src/forward.c
index b17bc34f865f..438e9fa490b8 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/helper.c b/src/helper.c
index 4be53c361ee1..1fee72dead8c 100644
--- a/src/helper.c
+++ b/src/helper.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/inotify.c b/src/inotify.c
index c537f4c1562a..470d6ed99213 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/ip6addr.h b/src/ip6addr.h
index c7dcb39c33fa..f0b7e820e227 100644
--- a/src/ip6addr.h
+++ b/src/ip6addr.h
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/lease.c b/src/lease.c
index 5d56b1b9147e..545bbb7fd09c 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/log.c b/src/log.c
index 8083a8697323..a5ac605c7c5d 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/loop.c b/src/loop.c
index bb377ad12644..565f7d8e58e0 100644
--- a/src/loop.c
+++ b/src/loop.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/netlink.c b/src/netlink.c
index b39328376389..10f94db25a14 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/network.c b/src/network.c
index 14d2af2ce313..7045253d467b 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/option.c b/src/option.c
index 6ef80117cc8c..cb4e76ba0aa2 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/outpacket.c b/src/outpacket.c
index dce68f7cb09f..5b1ff9318bbd 100644
--- a/src/outpacket.c
+++ b/src/outpacket.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/radv-protocol.h b/src/radv-protocol.h
index 72ccda49d7fe..4cc1ea426e69 100644
--- a/src/radv-protocol.h
+++ b/src/radv-protocol.h
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/radv.c b/src/radv.c
index 3c8b162dbd8e..6da125b864ae 100644
--- a/src/radv.c
+++ b/src/radv.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 262274fc5b80..5ef5ddb7485e 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/rfc2131.c b/src/rfc2131.c
index 5c9040892f1d..55526443dc84 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/rfc3315.c b/src/rfc3315.c
index e593ec9c362c..c1ddc805988d 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/slaac.c b/src/slaac.c
index 351d6802f85e..abaad537e25a 100644
--- a/src/slaac.c
+++ b/src/slaac.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/tftp.c b/src/tftp.c
index a527911fc0df..a57a31514f44 100644
--- a/src/tftp.c
+++ b/src/tftp.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
diff --git a/src/util.c b/src/util.c
index d532444da207..91d02410b13f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2015 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
--
2.1.0

View File

@@ -1,53 +0,0 @@
From 3d04f46334d0e345f589eda1372e638b946fe637 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 31 Jan 2015 21:59:13 +0000
Subject: [PATCH 040/113] inotify documentation updates.
---
man/dnsmasq.8 | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 005b5cca8d1f..c858323d78bd 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -50,6 +50,10 @@ Additional hosts file. Read the specified file as well as /etc/hosts. If -h is g
only the specified file. This option may be repeated for more than one
additional hosts file. If a directory is given, then read all the files contained in that directory.
.TP
+.B --hostsdir=<path>
+Read all the hosts files contained in the directory. New or changed files
+are read automatically. See --dhcp-hostsdir for details.
+.TP
.B \-E, --expand-hosts
Add the domain to simple names (without a period) in /etc/hosts
in the same way as for DHCP-derived names. Note that this does not
@@ -979,12 +983,14 @@ dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a
.TP
.B --dhcp-hostsdir=<path>
-This is exactly equivalent to dhcp-hostfile, except for the following. The path MUST be a
+This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a
directory, and not an individual file. Changed or new files within
the directory are read automatically, without the need to send SIGHUP.
If a file is deleted for changed after it has been read by dnsmasq, then the
host record it contained will remain until dnsmasq recieves a SIGHUP, or
is restarted; ie host records are only added dynamically.
+.B --dhcp-optsdir=<path>
+This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir.
.TP
.B --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
@@ -1791,7 +1797,8 @@ clears its cache and then re-loads
.I /etc/hosts
and
.I /etc/ethers
-and any file given by --dhcp-hostsfile, --dhcp-optsfile or --addn-hosts.
+and any file given by --dhcp-hostsfile, --dhcp-hostsdir, --dhcp-optsfile,
+--dhcp-optsdir, --addn-hosts or --hostsdir.
The dhcp lease change script is called for all
existing DHCP leases. If
.B
--
2.1.0

View File

@@ -1,39 +0,0 @@
From 6ef15b34ca83c62a939f69356d5c3f7a6bfef3d0 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 31 Jan 2015 22:44:26 +0000
Subject: [PATCH 041/113] Fix broken ECDSA DNSSEC signatures.
---
CHANGELOG | 2 ++
src/dnssec.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG b/CHANGELOG
index c05dec63c587..c80dc0fdbe9e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -65,6 +65,8 @@ version 2.73
configured to do stateful DHCPv6. Thanks to Win King Wan
for the patch.
+ Fix broken DNSSEC validation of ECDSA signatures.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/dnssec.c b/src/dnssec.c
index a8dfe3871c85..26932373cd3e 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -275,7 +275,7 @@ static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len
}
if (sig_len != 2*t || key_len != 2*t ||
- (p = blockdata_retrieve(key_data, key_len, NULL)))
+ !(p = blockdata_retrieve(key_data, key_len, NULL)))
return 0;
mpz_import(x, t , 1, 1, 0, 0, p);
--
2.1.0

View File

@@ -1,29 +0,0 @@
From 106266761828a0acb006346ae47bf031dee46a5d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 1 Feb 2015 00:15:16 +0000
Subject: [PATCH 042/113] BSD make support
---
Makefile | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 21e4a5c4101c..2910320b6452 100644
--- a/Makefile
+++ b/Makefile
@@ -64,8 +64,10 @@ 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 ' ')
+
+sum?=$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
+sum!=$(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' '
+copts_conf = .copts_$(sum)
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 \
--
2.1.0

View File

@@ -1,25 +0,0 @@
From 8d8a54ec79d9f96979fabbd97b1dd2ddebc7d78f Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 1 Feb 2015 21:48:46 +0000
Subject: [PATCH 043/113] Fix build failure on openBSD.
---
src/tables.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/tables.c b/src/tables.c
index dcdef794c4d2..aae1252708db 100644
--- a/src/tables.c
+++ b/src/tables.c
@@ -21,7 +21,7 @@
#if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
#ifndef __FreeBSD__
-#include <bsd/string.h>
+#include <string.h>
#endif
#include <sys/types.h>
--
2.1.0

View File

@@ -1,25 +0,0 @@
From d36b732c4cfa91ea09af64b5dc0f3a85a075e5bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thi=C3=A9baud=20Weksteen?= <thiebaud@weksteen.fr>
Date: Mon, 2 Feb 2015 21:37:27 +0000
Subject: [PATCH 044/113] Manpage typo fix.
---
man/dnsmasq.8 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index c858323d78bd..27f85d40fbbb 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -516,7 +516,7 @@ zone files: the port, weight and priority numbers are in a different
order. More than one SRV record for a given service/domain is allowed,
all that match are returned.
.TP
-.B --host-record=<name>[,<name>....][<IPv4-address>],[<IPv6-address>]
+.B --host-record=<name>[,<name>....],[<IPv4-address>],[<IPv6-address>]
Add A, AAAA and PTR records to the DNS. This adds one or more names to
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
appear in more than one
--
2.1.0

View File

@@ -1,38 +0,0 @@
From 2941d3ac898cf84b544e47c9735c5e4111711db1 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 2 Feb 2015 22:36:42 +0000
Subject: [PATCH 045/113] Fixup dhcp-configs after reading extra hostfiles with
inotify.
---
src/inotify.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/inotify.c b/src/inotify.c
index 470d6ed99213..6f4cd79e0030 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -194,7 +194,19 @@ int inotify_check(time_t now)
strcat(path, in->name);
if (ah->flags & AH_HOSTS)
- read_hostsfile(path, ah->index, 0, NULL, 0);
+ {
+ read_hostsfile(path, ah->index, 0, NULL, 0);
+#ifdef HAVE_DHCP
+ if (daemon->dhcp || daemon->doing_dhcp6)
+ {
+ /* Propogate the consequences of loading a new dhcp-host */
+ dhcp_update_configs(daemon->dhcp_conf);
+ lease_update_from_configs();
+ lease_update_file(now);
+ lease_update_dns(1);
+ }
+#endif
+ }
#ifdef HAVE_DHCP
else if (ah->flags & AH_DHCP_HST)
{
--
2.1.0

View File

@@ -1,68 +0,0 @@
From f9c863708c6b0aea31ff7a466647685dc739de50 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 3 Feb 2015 21:52:48 +0000
Subject: [PATCH 046/113] Extra logging for inotify code.
---
src/cache.c | 9 ++++-----
src/inotify.c | 4 +++-
src/option.c | 4 +++-
3 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 117ae279fd4e..43245b771b53 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1022,11 +1022,10 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
fclose(f);
if (rhash)
- {
- rehash(name_count);
- my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
- }
-
+ rehash(name_count);
+
+ my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
+
return name_count;
}
diff --git a/src/inotify.c b/src/inotify.c
index 6f4cd79e0030..44ce0c9af051 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -192,7 +192,9 @@ int inotify_check(time_t now)
strcpy(path, ah->fname);
strcat(path, "/");
strcat(path, in->name);
-
+
+ my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path);
+
if (ah->flags & AH_HOSTS)
{
read_hostsfile(path, ah->index, 0, NULL, 0);
diff --git a/src/option.c b/src/option.c
index cb4e76ba0aa2..e4b4865d07a5 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4068,11 +4068,13 @@ static void read_file(char *file, FILE *f, int hard_opt)
#ifdef HAVE_DHCP
int option_read_dynfile(char *file, int flags)
{
+ my_syslog(MS_DHCP | LOG_INFO, _("read %s"), file);
+
if (flags & AH_DHCP_HST)
return one_file(file, LOPT_BANK);
else if (flags & AH_DHCP_OPT)
return one_file(file, LOPT_OPTS);
-
+
return 0;
}
#endif
--
2.1.0

View File

@@ -1,24 +0,0 @@
From efb8b5566aafc1f3ce18514a2df93af5a2e4998c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 7 Feb 2015 22:36:34 +0000
Subject: [PATCH 047/113] man page typo.
---
man/dnsmasq.8 | 1 +
1 file changed, 1 insertion(+)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 27f85d40fbbb..5cdd186afaa0 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -989,6 +989,7 @@ the directory are read automatically, without the need to send SIGHUP.
If a file is deleted for changed after it has been read by dnsmasq, then the
host record it contained will remain until dnsmasq recieves a SIGHUP, or
is restarted; ie host records are only added dynamically.
+.TP
.B --dhcp-optsdir=<path>
This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir.
.TP
--
2.1.0

View File

@@ -1,26 +0,0 @@
From f4f400776b3c1aa303d1a0fcd500f0ab5bc970f2 Mon Sep 17 00:00:00 2001
From: Shantanu Gadgil <shantanugadgil@yahoo.com>
Date: Wed, 11 Feb 2015 20:16:59 +0000
Subject: [PATCH 048/113] Fix get-version script which returned wrong tag in
some situations.
---
bld/get-version | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bld/get-version b/bld/get-version
index c246a3cc6a47..7ab75db729ac 100755
--- a/bld/get-version
+++ b/bld/get-version
@@ -20,7 +20,7 @@ else
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
if [ $? -eq 0 ]; then
- echo "${vers}" | sort | head -n 1 | sed 's/^v//'
+ echo "${vers}" | sort -r | head -n 1 | sed 's/^v//'
else
cat $1/VERSION
fi
--
2.1.0

View File

@@ -1,26 +0,0 @@
From 8ff70de618eb7de9147dbfbd4deca4a2dd62f0cb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 14 Feb 2015 20:02:37 +0000
Subject: [PATCH 049/113] Typos.
---
src/inotify.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/inotify.c b/src/inotify.c
index 44ce0c9af051..9422066257f5 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -104,7 +104,8 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
ah->flags |= AH_WD_DONE;
}
- /* Read contents of dir _after_ calling add_watch, in the ho[e of avoiding
+
+ /* Read contents of dir _after_ calling add_watch, in the hope of avoiding
a race which misses files being added as we start */
if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
{
--
2.1.0

View File

@@ -1,45 +0,0 @@
From caeea190f12efd20139f694aac4942d1ac00019f Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 14 Feb 2015 20:08:56 +0000
Subject: [PATCH 050/113] Make dynamic hosts files work when --no-hosts set.
---
src/cache.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 43245b771b53..c95624c42b1c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1133,17 +1133,18 @@ void cache_reload(void)
{
if (daemon->cachesize > 0)
my_syslog(LOG_INFO, _("cleared cache"));
- return;
}
-
- if (!option_bool(OPT_NO_HOSTS))
- total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
-
- daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
- for (ah = daemon->addn_hosts; ah; ah = ah->next)
- if (!(ah->flags & AH_INACTIVE))
- total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
-
+ else
+ {
+ if (!option_bool(OPT_NO_HOSTS))
+ total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
+
+ daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
+ for (ah = daemon->addn_hosts; ah; ah = ah->next)
+ if (!(ah->flags & AH_INACTIVE))
+ total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
+ }
+
#ifdef HAVE_INOTIFY
set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
#endif
--
2.1.0

View File

@@ -1,55 +0,0 @@
From 28b879ac47b872af6e8c5e86d76806c69338434d Mon Sep 17 00:00:00 2001
From: Chen Wei <weichen302@icloud.com>
Date: Tue, 17 Feb 2015 22:07:35 +0000
Subject: [PATCH 051/113] Fix trivial memory leaks to quieten valgrind.
---
src/dnsmasq.c | 2 ++
src/option.c | 11 +++++++++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index e903a24c8105..e6dabbf556f7 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -627,6 +627,8 @@ int main (int argc, char **argv)
}
#ifdef HAVE_LINUX_NETWORK
+ free(hdr);
+ free(data);
if (option_bool(OPT_DEBUG))
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif
diff --git a/src/option.c b/src/option.c
index e4b4865d07a5..ae0ad002d8b8 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4361,7 +4361,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
{
char *buff = opt_malloc(MAXDNAME);
int option, conffile_opt = '7', testmode = 0;
- char *arg, *conffile = CONFFILE;
+ char *arg, *conffile = NULL;
opterr = 0;
@@ -4476,7 +4476,14 @@ void read_opts(int argc, char **argv, char *compile_opts)
}
if (conffile)
- one_file(conffile, conffile_opt);
+ {
+ one_file(conffile, conffile_opt);
+ free(conffile);
+ }
+ else
+ {
+ one_file(CONFFILE, conffile_opt);
+ }
/* port might not be known when the address is parsed - fill in here */
if (daemon->servers)
--
2.1.0

View File

@@ -1,27 +0,0 @@
From 0705a7e2d57654b27c7e14f35ca77241c1821f4d Mon Sep 17 00:00:00 2001
From: Tomas Hozza <thozza@redhat.com>
Date: Mon, 23 Feb 2015 21:26:26 +0000
Subject: [PATCH 052/113] Fix uninitialized value used in get_client_mac()
---
src/dhcp6.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/dhcp6.c b/src/dhcp6.c
index 3c56e77c6085..c7144f5fee7c 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -246,7 +246,9 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
neigh.code = 0;
neigh.reserved = 0;
neigh.target = *client;
-
+ /* RFC4443 section-2.3: checksum has to be zero to be calculated */
+ neigh.checksum = 0;
+
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.sin6_len = sizeof(struct sockaddr_in6);
--
2.1.0

View File

@@ -1,73 +0,0 @@
From 47b9ac59c715827252ae6e6732903c3dabb697fb Mon Sep 17 00:00:00 2001
From: Joachim Zobel <jz-2014@heute-morgen.de>
Date: Mon, 23 Feb 2015 21:38:11 +0000
Subject: [PATCH 053/113] Log parsing utils in contrib/reverse-dns
---
contrib/reverse-dns/README | 18 ++++++++++++++++++
contrib/reverse-dns/reverse_replace.sh | 28 ++++++++++++++++++++++++++++
2 files changed, 46 insertions(+)
create mode 100644 contrib/reverse-dns/README
create mode 100644 contrib/reverse-dns/reverse_replace.sh
diff --git a/contrib/reverse-dns/README b/contrib/reverse-dns/README
new file mode 100644
index 000000000000..f87eb77c4c22
--- /dev/null
+++ b/contrib/reverse-dns/README
@@ -0,0 +1,18 @@
+Hi.
+
+To translate my routers netstat-nat output into names that actually talk
+to me I have started writing to simple shell scripts. They require
+
+log-queries
+log-facility=/var/log/dnsmasq.log
+
+to be set. With
+
+netstat-nat -n -4 | reverse_replace.sh
+
+I get retranslated output.
+
+Sincerely,
+Joachim
+
+
diff --git a/contrib/reverse-dns/reverse_replace.sh b/contrib/reverse-dns/reverse_replace.sh
new file mode 100644
index 000000000000..a11c164b7f19
--- /dev/null
+++ b/contrib/reverse-dns/reverse_replace.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# $Id: reverse_replace.sh 4 2015-02-17 20:14:59Z jo $
+#
+# Usage e.g.: netstat -n -4 | reverse_replace.sh
+# Parses stdin for IP4 addresses and replaces them
+# with names retrieved by reverse_dns.sh
+#
+
+DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+DNS=$DIR/reverse_dns.sh
+
+# sed regex
+IP_regex='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
+
+while read LINE; do
+ if grep --quiet $IP_regex <<< "$LINE"; then
+ IPs=`sed "s#.*\b\($IP_regex\)\b.*#\1 #g" <<< "$LINE"`
+ IPs=($IPs)
+ for IP in "${IPs[@]}"
+ do
+ NAME=`$DNS $IP`
+ # echo "$NAME is $IP";
+ LINE="${LINE/$IP/$NAME}"
+ done
+ fi
+ echo $LINE
+done < /dev/stdin
+
--
2.1.0

View File

@@ -1,252 +0,0 @@
From f6e62e2af96f5fa0d1e3d93167a93a8f09bf6e61 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 1 Mar 2015 18:17:54 +0000
Subject: [PATCH 054/113] Add --dnssec-timestamp option and facility.
---
CHANGELOG | 6 +++++
man/dnsmasq.8 | 6 +++++
src/dnsmasq.c | 11 +++++++-
src/dnsmasq.h | 2 ++
src/dnssec.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
src/option.c | 7 +++++
6 files changed, 108 insertions(+), 6 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index c80dc0fdbe9e..4f4fa305deaa 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -66,6 +66,12 @@ version 2.73
for the patch.
Fix broken DNSSEC validation of ECDSA signatures.
+
+ Add --dnssec-timestamp option, which provides an automatic
+ way to detect when the system time becomes valid after boot
+ on systems without an RTC, whilst allowing DNS queries before the
+ clock is valid so that NTP can run. Thanks to
+ Kevin Darbyshire-Bryant for developing this idea.
version 2.72
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 5cdd186afaa0..097e7d75145c 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -674,6 +674,12 @@ that dnsmasq should be started with this flag when the platform determines that
reliable time is established, a SIGHUP should be sent to dnsmasq, which enables time checking, and purges the cache of DNS records
which have not been throughly checked.
.TP
+.B --dnssec-timestamp=<path>
+Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the
+system time is considered to be valid once it becomes later than the timestamp on the specified file. The file is created and
+its timestamp set automatically by dnsmasq. The file must be stored on a persistent filesystem, so that it and its mtime are carried
+over system restarts.
+.TP
.B --proxy-dnssec
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
alternative to having dnsmasq validate DNSSEC, but it depends on the security of the network between
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index e6dabbf556f7..769a19afe6c5 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -58,6 +58,9 @@ int main (int argc, char **argv)
struct dhcp_context *context;
struct dhcp_relay *relay;
#endif
+#ifdef HAVE_DNSSEC
+ int badtime;
+#endif
#ifdef LOCALEDIR
setlocale(LC_ALL, "");
@@ -369,7 +372,11 @@ int main (int argc, char **argv)
if (baduser)
die(_("unknown user or group: %s"), baduser, EC_BADCONF);
-
+
+#ifdef HAVE_DNSSEC
+ badtime = setup_timestamp(ent_pw->pw_uid);
+#endif
+
/* implement group defaults, "dip" if available, or group associated with uid */
if (!daemon->group_set && !gp)
{
@@ -689,6 +696,8 @@ int main (int argc, char **argv)
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
if (option_bool(OPT_DNSSEC_TIME))
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
+ if (badtime)
+ my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
}
#endif
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 89e758b56a0a..b2f02dda63f0 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -986,6 +986,7 @@ extern struct daemon {
#endif
#ifdef HAVE_DNSSEC
struct ds_config *ds;
+ char *timestamp_file;
#endif
/* globally used stuff for DNS */
@@ -1151,6 +1152,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
size_t filter_rrsigs(struct dns_header *header, size_t plen);
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
+int setup_timestamp(uid_t uid);
/* util.c */
void rand_init(void);
diff --git a/src/dnssec.c b/src/dnssec.c
index 26932373cd3e..bf4406469de0 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -34,6 +34,7 @@
#include <nettle/dsa-compat.h>
#endif
+#include <utime.h>
#define SERIAL_UNDEF -100
#define SERIAL_EQ 0
@@ -394,17 +395,88 @@ static int serial_compare_32(unsigned long s1, unsigned long s2)
return SERIAL_UNDEF;
}
+/* Called at startup. If the timestamp file is configured and exists, put its mtime on
+ timestamp_time. If it doesn't exist, create it, and set the mtime to 1-1-2015.
+ Change the ownership to the user we'll be running as, so that we can update the mtime.
+*/
+static time_t timestamp_time;
+static int back_to_the_future;
+
+int setup_timestamp(uid_t uid)
+{
+ struct stat statbuf;
+
+ back_to_the_future = 0;
+
+ if (!option_bool(OPT_DNSSEC_VALID) || !daemon->timestamp_file)
+ return 0;
+
+ if (stat(daemon->timestamp_file, &statbuf) != -1)
+ {
+ timestamp_time = statbuf.st_mtime;
+ check_and_exit:
+ if (difftime(timestamp_time, time(0)) <= 0)
+ {
+ /* time already OK, update timestamp, and do key checking from the start. */
+ if (utime(daemon->timestamp_file, NULL) == -1)
+ my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
+ back_to_the_future = 1;
+ return 0;
+ }
+ return 1;
+ }
+
+ if (errno == ENOENT)
+ {
+ int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK, 0666);
+ if (fd != -1)
+ {
+ struct utimbuf timbuf;
+
+ close(fd);
+
+ timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */
+ if (utime(daemon->timestamp_file, &timbuf) == 0 &&
+ (getuid() != 0 || chown(daemon->timestamp_file, uid, -1) == 0))
+ goto check_and_exit;
+ }
+ }
+
+ die(_("Cannot create timestamp file %s: %s" ), daemon->timestamp_file, EC_BADCONF);
+ return 0;
+}
+
/* Check whether today/now is between date_start and date_end */
static int check_date_range(unsigned long date_start, unsigned long date_end)
{
- unsigned long curtime;
-
+ unsigned long curtime = time(0);
+
/* Checking timestamps may be temporarily disabled */
- if (option_bool(OPT_DNSSEC_TIME))
+
+ /* If the current time if _before_ the timestamp
+ on our persistent timestamp file, then assume the
+ time if not yet correct, and don't check the
+ key timestamps. As soon as the current time is
+ later then the timestamp, update the timestamp
+ and start checking keys */
+ if (daemon->timestamp_file)
+ {
+ if (back_to_the_future == 0 && difftime(timestamp_time, curtime) <= 0)
+ {
+ if (utime(daemon->timestamp_file, NULL) != 0)
+ my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
+
+ back_to_the_future = 1;
+ set_option_bool(OPT_DNSSEC_TIME);
+ queue_event(EVENT_RELOAD); /* purge cache */
+ }
+
+ if (back_to_the_future == 0)
+ return 1;
+ }
+ else if (option_bool(OPT_DNSSEC_TIME))
return 1;
- curtime = time(0);
-
/* We must explicitly check against wanted values, because of SERIAL_UNDEF */
return serial_compare_32(curtime, date_start) == SERIAL_GT
&& serial_compare_32(curtime, date_end) == SERIAL_LT;
diff --git a/src/option.c b/src/option.c
index ae0ad002d8b8..eace40bb566c 100644
--- a/src/option.c
+++ b/src/option.c
@@ -152,6 +152,7 @@ struct myoption {
#define LOPT_DHCP_INOTIFY 340
#define LOPT_DHOPT_INOTIFY 341
#define LOPT_HOST_INOTIFY 342
+#define LOPT_DNSSEC_STAMP 343
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -300,6 +301,7 @@ static const struct myoption opts[] =
{ "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
{ "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK },
{ "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
+ { "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP },
#ifdef OPTION6_PREFIX_CLASS
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
#endif
@@ -463,6 +465,7 @@ static struct {
{ LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
{ LOPT_DNSSEC_CHECK, OPT_DNSSEC_NO_SIGN, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
{ LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
+ { LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
#endif
@@ -3867,6 +3870,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
#ifdef HAVE_DNSSEC
+ case LOPT_DNSSEC_STAMP:
+ daemon->timestamp_file = opt_string_alloc(arg);
+ break;
+
case LOPT_TRUST_ANCHOR:
{
struct ds_config *new = opt_malloc(sizeof(struct ds_config));
--
2.1.0

View File

@@ -1,63 +0,0 @@
From 9003b50b13da624ca45f3e0cf99abb623b8d026b Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 2 Mar 2015 22:47:23 +0000
Subject: [PATCH 055/113] Fix last commit to not crash if uid changing not
configured.
---
src/dnsmasq.c | 2 +-
src/dnsmasq.h | 2 +-
src/dnssec.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 769a19afe6c5..9e05c0e31569 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -374,7 +374,7 @@ int main (int argc, char **argv)
die(_("unknown user or group: %s"), baduser, EC_BADCONF);
#ifdef HAVE_DNSSEC
- badtime = setup_timestamp(ent_pw->pw_uid);
+ badtime = setup_timestamp(ent_pw);
#endif
/* implement group defaults, "dip" if available, or group associated with uid */
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index b2f02dda63f0..a451cb4dd03c 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1152,7 +1152,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
size_t filter_rrsigs(struct dns_header *header, size_t plen);
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
-int setup_timestamp(uid_t uid);
+int setup_timestamp(struct passwd *ent_pw);
/* util.c */
void rand_init(void);
diff --git a/src/dnssec.c b/src/dnssec.c
index bf4406469de0..c60eacf73c6b 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -402,7 +402,7 @@ static int serial_compare_32(unsigned long s1, unsigned long s2)
static time_t timestamp_time;
static int back_to_the_future;
-int setup_timestamp(uid_t uid)
+int setup_timestamp(struct passwd *ent_pw)
{
struct stat statbuf;
@@ -437,7 +437,7 @@ int setup_timestamp(uid_t uid)
timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */
if (utime(daemon->timestamp_file, &timbuf) == 0 &&
- (getuid() != 0 || chown(daemon->timestamp_file, uid, -1) == 0))
+ (!ent_pw || getuid() != 0 || chown(daemon->timestamp_file, ent_pw->pw_uid, -1) == 0))
goto check_and_exit;
}
}
--
2.1.0

View File

@@ -1,194 +0,0 @@
From 4c960fa90a975d20f75a1ecabd217247f1922c8f Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 4 Mar 2015 20:32:26 +0000
Subject: [PATCH 056/113] New version of contrib/reverse-dns
---
contrib/reverse-dns/README | 22 +++---
contrib/reverse-dns/reverse_replace.sh | 131 ++++++++++++++++++++++++++++-----
2 files changed, 125 insertions(+), 28 deletions(-)
diff --git a/contrib/reverse-dns/README b/contrib/reverse-dns/README
index f87eb77c4c22..2ec4df1f957e 100644
--- a/contrib/reverse-dns/README
+++ b/contrib/reverse-dns/README
@@ -1,18 +1,18 @@
-Hi.
+The script reads stdin and replaces all IP addresses with names before
+outputting it again. IPs from private networks are reverse looked up
+via dns. Other IP adresses are searched for in the dnsmasq query log.
+This gives names (CNAMEs if I understand DNS correctly) that are closer
+to the name the client originally asked for then the names obtained by
+reverse lookup. Just run
-To translate my routers netstat-nat output into names that actually talk
-to me I have started writing to simple shell scripts. They require
+netstat -n -4 | ./reverse_replace.sh
+
+to see what it does. It needs
log-queries
log-facility=/var/log/dnsmasq.log
-to be set. With
-
-netstat-nat -n -4 | reverse_replace.sh
-
-I get retranslated output.
-
-Sincerely,
-Joachim
+in the dnsmasq configuration.
+The script runs on debian (with ash installed) and on busybox.
diff --git a/contrib/reverse-dns/reverse_replace.sh b/contrib/reverse-dns/reverse_replace.sh
index a11c164b7f19..5b4aebd71456 100644
--- a/contrib/reverse-dns/reverse_replace.sh
+++ b/contrib/reverse-dns/reverse_replace.sh
@@ -1,28 +1,125 @@
-#!/bin/bash
-# $Id: reverse_replace.sh 4 2015-02-17 20:14:59Z jo $
+#!/bin/ash
+# $Id: reverse_replace.sh 18 2015-03-01 16:12:35Z jo $
#
# Usage e.g.: netstat -n -4 | reverse_replace.sh
# Parses stdin for IP4 addresses and replaces them
-# with names retrieved by reverse_dns.sh
+# with names retrieved by parsing the dnsmasq log.
+# This currently only gives CNAMEs. But these
+# usually tell ou more than the mones from reverse
+# lookups.
+#
+# This has been tested on debian and asuswrt. Plese
+# report successful tests on other platforms.
+#
+# Author: Joachim Zobel <jz-2014@heute-morgen.de>
+# License: Consider this MIT style licensed. You can
+# do as you ike, but you must not remove my name.
#
-DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-DNS=$DIR/reverse_dns.sh
+LOG=/var/log/dnsmasq.log
+MAX_LINES=15000
-# sed regex
+# sed regex do match IPs
IP_regex='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
+# private IP ranges
+IP_private='\(^127\.\)\|\(^192\.168\.\)\|\(^10\.\)\|\(^172\.1[6-9]\.\)\|\(^172\.2[0-9]\.\)\|\(^172\.3[0-1]\.\)'
-while read LINE; do
- if grep --quiet $IP_regex <<< "$LINE"; then
- IPs=`sed "s#.*\b\($IP_regex\)\b.*#\1 #g" <<< "$LINE"`
- IPs=($IPs)
- for IP in "${IPs[@]}"
- do
- NAME=`$DNS $IP`
- # echo "$NAME is $IP";
- LINE="${LINE/$IP/$NAME}"
- done
+#######################################################################
+# Find Commands
+
+HOST=nslookup
+if type host > /dev/null 2>&1; then
+ # echo "No need for nslookup, host is there"
+ HOST=host
+fi
+
+#######################################################################
+# Functions
+
+# Use shell variables for an (IP) lookup table
+create_lookup_table()
+{
+ # Parse log into lookup table
+ local CMDS="$( tail -"$MAX_LINES" "$LOG" | \
+ grep " is $IP_regex" | \
+ sed "s#.* \([^ ]*\) is \($IP_regex\).*#set_val \2 \1;#" )"
+
+ local IFS='
+'
+ for CMD in $CMDS
+ do
+ eval $CMD
+ done
+}
+
+set_val()
+{
+ local _IP=$(echo $1 | tr . _)
+ local KEY="__IP__$_IP"
+ eval "$KEY"=$2
+}
+
+get_val()
+{
+ local _IP=$(echo $1 | tr . _)
+ local KEY="__IP__$_IP"
+ eval echo -n '${'"$KEY"'}'
+}
+
+dns_lookup()
+{
+ local IP=$1
+
+ local RTN="$($HOST $IP | \
+ sed 's#\s\+#\n#g' | \
+ grep -v '^$' | \
+ tail -1 | tr -d '\n' | \
+ sed 's#\.$##')"
+ if echo $RTN | grep -q NXDOMAIN; then
+ echo -n $IP
+ else
+ echo -n "$RTN"
+ fi
+}
+
+reverse_dns()
+{
+ local IP=$1
+
+ # Skip if it is not an IP
+ if ! echo $IP | grep -q "^$IP_regex$"; then
+ echo -n $IP
+ return
+ fi
+
+ # Do a dns lookup, if it is a local IP
+ if echo $IP | grep -q $IP_private; then
+ dns_lookup $IP
+ return
fi
+
+ local NAME="$(get_val $IP)"
+
+ if [ -z "$NAME" ]; then
+ echo -n $IP
+ else
+ echo -n $NAME
+ fi
+}
+
+#######################################################################
+# Main
+create_lookup_table
+
+while read LINE; do
+ for IP in $(echo "$LINE" | \
+ sed "s#\b\($IP_regex\)\b#\n\1\n#g" | \
+ grep $IP_regex)
+ do
+ NAME=`reverse_dns $IP `
+ # echo "$NAME $IP"
+ LINE=`echo "$LINE" | sed "s#$IP#$NAME#" `
+ done
echo $LINE
-done < /dev/stdin
+done
--
2.1.0

View File

@@ -1,202 +0,0 @@
From 360f2513ab12a9bf1e262d388dd2ea8a566590a3 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 7 Mar 2015 18:28:06 +0000
Subject: [PATCH 057/113] Tweak DNSSEC timestamp code to create file later,
removing need to chown it.
---
man/dnsmasq.8 | 3 ++-
src/dnsmasq.c | 35 ++++++++++++++++++++++-------------
src/dnsmasq.h | 3 ++-
src/dnssec.c | 18 ++++++++++--------
4 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 097e7d75145c..2db780d90987 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -678,7 +678,8 @@ which have not been throughly checked.
Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the
system time is considered to be valid once it becomes later than the timestamp on the specified file. The file is created and
its timestamp set automatically by dnsmasq. The file must be stored on a persistent filesystem, so that it and its mtime are carried
-over system restarts.
+over system restarts. The timestamp file is created after dnsmasq has dropped root, so it must be in a location writable by the
+unprivileged user that dnsmasq runs as.
.TP
.B --proxy-dnssec
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 9e05c0e31569..f3e5bcffec4f 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -58,9 +58,6 @@ int main (int argc, char **argv)
struct dhcp_context *context;
struct dhcp_relay *relay;
#endif
-#ifdef HAVE_DNSSEC
- int badtime;
-#endif
#ifdef LOCALEDIR
setlocale(LC_ALL, "");
@@ -156,10 +153,10 @@ int main (int argc, char **argv)
{
#ifdef HAVE_DNSSEC
if (!daemon->ds)
- die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
+ die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
if (daemon->cachesize < CACHESIZ)
- die(_("Cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
+ die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
#else
die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
#endif
@@ -172,10 +169,10 @@ int main (int argc, char **argv)
#ifdef HAVE_CONNTRACK
if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
- die (_("Cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
+ die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
#else
if (option_bool(OPT_CONNTRACK))
- die(_("Conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
+ die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
#endif
#ifdef HAVE_SOLARIS_NETWORK
@@ -195,7 +192,7 @@ int main (int argc, char **argv)
#ifndef HAVE_LOOP
if (option_bool(OPT_LOOP_DETECT))
- die(_("Loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
+ die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
#endif
now = dnsmasq_time();
@@ -373,10 +370,6 @@ int main (int argc, char **argv)
if (baduser)
die(_("unknown user or group: %s"), baduser, EC_BADCONF);
-#ifdef HAVE_DNSSEC
- badtime = setup_timestamp(ent_pw);
-#endif
-
/* implement group defaults, "dip" if available, or group associated with uid */
if (!daemon->group_set && !gp)
{
@@ -693,10 +686,23 @@ int main (int argc, char **argv)
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
+ int rc;
+
+ /* Delay creating the timestamp file until here, after we've changed user, so that
+ it has the correct owner to allow updating the mtime later.
+ This means we have to report fatal errors via the pipe. */
+ if ((rc = setup_timestamp()) == -1)
+ {
+ send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
+ _exit(0);
+ }
+
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
+
if (option_bool(OPT_DNSSEC_TIME))
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
- if (badtime)
+
+ if (rc == 1)
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
}
#endif
@@ -1170,6 +1176,9 @@ static void fatal_event(struct event_desc *ev, char *msg)
case EVENT_TFTP_ERR:
die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
+
+ case EVENT_TIME_ERR:
+ die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
}
}
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index a451cb4dd03c..fc7259881358 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -167,6 +167,7 @@ struct event_desc {
#define EVENT_INIT 21
#define EVENT_NEWADDR 22
#define EVENT_NEWROUTE 23
+#define EVENT_TIME_ERR 24
/* Exit codes. */
#define EC_GOOD 0
@@ -1152,7 +1153,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
size_t filter_rrsigs(struct dns_header *header, size_t plen);
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
-int setup_timestamp(struct passwd *ent_pw);
+int setup_timestamp(void);
/* util.c */
void rand_init(void);
diff --git a/src/dnssec.c b/src/dnssec.c
index c60eacf73c6b..ad0d6f072ba2 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -397,18 +397,21 @@ static int serial_compare_32(unsigned long s1, unsigned long s2)
/* Called at startup. If the timestamp file is configured and exists, put its mtime on
timestamp_time. If it doesn't exist, create it, and set the mtime to 1-1-2015.
- Change the ownership to the user we'll be running as, so that we can update the mtime.
+ return -1 -> Cannot create file.
+ 0 -> not using timestamp, or timestamp exists and is in past.
+ 1 -> timestamp exists and is in future.
*/
+
static time_t timestamp_time;
static int back_to_the_future;
-int setup_timestamp(struct passwd *ent_pw)
+int setup_timestamp(void)
{
struct stat statbuf;
back_to_the_future = 0;
- if (!option_bool(OPT_DNSSEC_VALID) || !daemon->timestamp_file)
+ if (!daemon->timestamp_file)
return 0;
if (stat(daemon->timestamp_file, &statbuf) != -1)
@@ -428,7 +431,8 @@ int setup_timestamp(struct passwd *ent_pw)
if (errno == ENOENT)
{
- int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK, 0666);
+ /* NB. for explanation of O_EXCL flag, see comment on pidfile in dnsmasq.c */
+ int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK | O_EXCL, 0666);
if (fd != -1)
{
struct utimbuf timbuf;
@@ -436,14 +440,12 @@ int setup_timestamp(struct passwd *ent_pw)
close(fd);
timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */
- if (utime(daemon->timestamp_file, &timbuf) == 0 &&
- (!ent_pw || getuid() != 0 || chown(daemon->timestamp_file, ent_pw->pw_uid, -1) == 0))
+ if (utime(daemon->timestamp_file, &timbuf) == 0)
goto check_and_exit;
}
}
- die(_("Cannot create timestamp file %s: %s" ), daemon->timestamp_file, EC_BADCONF);
- return 0;
+ return -1;
}
/* Check whether today/now is between date_start and date_end */
--
2.1.0

View File

@@ -1,458 +0,0 @@
From ff841ebf5a5d6864ff48571f607c32ce80dbb75a Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 11 Mar 2015 21:36:30 +0000
Subject: [PATCH 058/113] Fix boilerplate code for re-running system calls on
EINTR and EAGAIN etc.
The nasty code with static variable in retry_send() which
avoids looping forever needs to be called on success of the syscall,
to reset the static variable.
---
src/bpf.c | 2 +-
src/dhcp.c | 2 +-
src/dhcp6.c | 6 +++---
src/dnsmasq.c | 35 +++++++++++++++++----------------
src/dnsmasq.h | 2 +-
src/forward.c | 41 ++++++++++++++++++--------------------
src/ipset.c | 8 ++++----
src/loop.c | 5 +++--
src/netlink.c | 8 ++++----
src/radv.c | 5 +++--
src/util.c | 63 ++++++++++++++++++++++++++++++++++-------------------------
11 files changed, 93 insertions(+), 84 deletions(-)
diff --git a/src/bpf.c b/src/bpf.c
index 997d87421bed..a066641f969f 100644
--- a/src/bpf.c
+++ b/src/bpf.c
@@ -359,7 +359,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
iov[3].iov_base = mess;
iov[3].iov_len = len;
- while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
+ while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
}
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
diff --git a/src/dhcp.c b/src/dhcp.c
index f29be9b489a7..5c3089ab94ff 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -443,7 +443,7 @@ void dhcp_packet(time_t now, int pxe_fd)
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
#endif
- while(sendmsg(fd, &msg, 0) == -1 && retry_send());
+ while(retry_send(sendmsg(fd, &msg, 0)));
}
/* check against secondary interface addresses */
diff --git a/src/dhcp6.c b/src/dhcp6.c
index c7144f5fee7c..ee2aa5d3bf3c 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -225,9 +225,9 @@ void dhcp6_packet(time_t now)
if (port != 0)
{
from.sin6_port = htons(port);
- while (sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(0),
- 0, (struct sockaddr *)&from, sizeof(from)) == -1 &&
- retry_send());
+ while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
+ save_counter(0), 0, (struct sockaddr *)&from,
+ sizeof(from))));
}
}
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index f3e5bcffec4f..b784951950d4 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -444,7 +444,7 @@ int main (int argc, char **argv)
char *msg;
/* close our copy of write-end */
- close(err_pipe[1]);
+ while (retry_send(close(err_pipe[1])));
/* check for errors after the fork */
if (read_event(err_pipe[0], &ev, &msg))
@@ -453,7 +453,7 @@ int main (int argc, char **argv)
_exit(EC_GOOD);
}
- close(err_pipe[0]);
+ while (retry_send(close(err_pipe[0])));
/* NO calls to die() from here on. */
@@ -505,10 +505,12 @@ int main (int argc, char **argv)
{
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
err = 1;
-
- while (!err && close(fd) == -1)
- if (!retry_send())
- err = 1;
+ else
+ {
+ while (retry_send(close(fd)));
+ if (errno != 0)
+ err = 1;
+ }
}
if (err)
@@ -813,7 +815,7 @@ int main (int argc, char **argv)
/* finished start-up - release original process */
if (err_pipe[1] != -1)
- close(err_pipe[1]);
+ while (retry_send(close(err_pipe[1])));
if (daemon->port != 0)
check_servers();
@@ -1319,7 +1321,7 @@ static void async_event(int pipe, time_t now)
do {
helper_write();
} while (!helper_buf_empty() || do_script_run(now));
- close(daemon->helperfd);
+ while (retry_send(close(daemon->helperfd)));
}
#endif
@@ -1544,7 +1546,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
{
- close(confd);
+ while (retry_send(close(confd)));
continue;
}
@@ -1609,7 +1611,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if (!client_ok)
{
shutdown(confd, SHUT_RDWR);
- close(confd);
+ while (retry_send(close(confd)));
}
#ifndef NO_FORK
else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
@@ -1624,7 +1626,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
break;
}
}
- close(confd);
+ while (retry_send(close(confd)));
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
daemon->log_id += TCP_MAX_QUERIES;
@@ -1669,7 +1671,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
shutdown(confd, SHUT_RDWR);
- close(confd);
+ while (retry_send(close(confd)));
if (buff)
free(buff);
@@ -1678,7 +1680,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
- close(s->tcpfd);
+ while (retry_send(close(s->tcpfd)));
}
#ifndef NO_FORK
if (!option_bool(OPT_DEBUG))
@@ -1756,9 +1758,8 @@ int icmp_ping(struct in_addr addr)
j = (j & 0xffff) + (j >> 16);
packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
- while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
- (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
- retry_send());
+ while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
+ (struct sockaddr *)&saddr, sizeof(saddr))));
for (now = start = dnsmasq_time();
difftime(now, start) < (float)PING_WAIT;)
@@ -1820,7 +1821,7 @@ int icmp_ping(struct in_addr addr)
}
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
- close(fd);
+ while (retry_send(close(fd)));
#else
opt = 1;
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index fc7259881358..de95d0e875e3 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1177,7 +1177,7 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
u64 addr6part(struct in6_addr *addr);
void setaddr6part(struct in6_addr *addr, u64 host);
#endif
-int retry_send(void);
+int retry_send(ssize_t rc);
void prettyprint_time(char *buf, unsigned int t);
int prettyprint_addr(union mysockaddr *addr, char *buf);
int parse_hex(char *in, unsigned char *out, int maxlen,
diff --git a/src/forward.c b/src/forward.c
index 438e9fa490b8..7c0fa8da3fdf 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -103,15 +103,11 @@ int send_from(int fd, int nowild, char *packet, size_t len,
#endif
}
- while (sendmsg(fd, &msg, 0) == -1)
+ while (retry_send(sendmsg(fd, &msg, 0)));
+
+ /* If interface is still in DAD, EINVAL results - ignore that. */
+ if (errno != 0 && errno != EINVAL)
{
- if (retry_send())
- continue;
-
- /* If interface is still in DAD, EINVAL results - ignore that. */
- if (errno == EINVAL)
- break;
-
my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
return 0;
}
@@ -297,9 +293,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
fd = forward->rfd4->fd;
}
- while (sendto(fd, (char *)header, plen, 0,
- &forward->sentto->addr.sa,
- sa_len(&forward->sentto->addr)) == -1 && retry_send());
+ while (retry_send( sendto(fd, (char *)header, plen, 0,
+ &forward->sentto->addr.sa,
+ sa_len(&forward->sentto->addr))));
return 1;
}
@@ -469,14 +465,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
#endif
}
- if (sendto(fd, (char *)header, plen, 0,
- &start->addr.sa,
- sa_len(&start->addr)) == -1)
- {
- if (retry_send())
- continue;
- }
- else
+ if (retry_send(sendto(fd, (char *)header, plen, 0,
+ &start->addr.sa,
+ sa_len(&start->addr))))
+ continue;
+
+ if (errno == 0)
{
/* Keep info in case we want to re-send this packet */
daemon->srv_save = start;
@@ -932,7 +926,9 @@ void reply_query(int fd, int family, time_t now)
if (fd != -1)
{
- while (sendto(fd, (char *)header, nn, 0, &server->addr.sa, sa_len(&server->addr)) == -1 && retry_send());
+ while (retry_send(sendto(fd, (char *)header, nn, 0,
+ &server->addr.sa,
+ sa_len(&server->addr))));
server->queries++;
}
@@ -2228,8 +2224,9 @@ void resend_query()
else
return;
- while(sendto(fd, daemon->packet, daemon->packet_len, 0,
- &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
+ while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
+ &daemon->srv_save->addr.sa,
+ sa_len(&daemon->srv_save->addr))));
}
}
diff --git a/src/ipset.c b/src/ipset.c
index 8c5b72722371..a315e86bc7f4 100644
--- a/src/ipset.c
+++ b/src/ipset.c
@@ -121,7 +121,6 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
struct my_nlattr *nested[2];
uint8_t proto;
int addrsz = INADDRSZ;
- ssize_t rc;
#ifdef HAVE_IPV6
if (af == AF_INET6)
@@ -162,9 +161,10 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
nested[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
- while ((rc = sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
- (struct sockaddr *)&snl, sizeof(snl))) == -1 && retry_send());
- return rc;
+ while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
+ (struct sockaddr *)&snl, sizeof(snl))));
+
+ return errno == 0 ? 0 : -1;
}
diff --git a/src/loop.c b/src/loop.c
index 565f7d8e58e0..c9ed075670de 100644
--- a/src/loop.c
+++ b/src/loop.c
@@ -45,8 +45,9 @@ void loop_send_probes()
fd = rfd->fd;
}
- while (sendto(fd, daemon->packet, len, 0, &serv->addr.sa, sa_len(&serv->addr)) == -1 && retry_send());
-
+ while (retry_send(sendto(fd, daemon->packet, len, 0,
+ &serv->addr.sa, sa_len(&serv->addr))));
+
free_rfd(rfd);
}
}
diff --git a/src/netlink.c b/src/netlink.c
index 10f94db25a14..753784dc20b4 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -169,10 +169,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
req.g.rtgen_family = family;
/* Don't block in recvfrom if send fails */
- while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
- (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
-
- if (len == -1)
+ while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
+ (struct sockaddr *)&addr, sizeof(addr))));
+
+ if (errno != 0)
return 0;
while (1)
diff --git a/src/radv.c b/src/radv.c
index 6da125b864ae..d0faddf8684a 100644
--- a/src/radv.c
+++ b/src/radv.c
@@ -479,8 +479,9 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
}
- while (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
- (struct sockaddr *)&addr, sizeof(addr)) == -1 && retry_send());
+ while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
+ save_counter(0), 0, (struct sockaddr *)&addr,
+ sizeof(addr))));
}
diff --git a/src/util.c b/src/util.c
index 91d02410b13f..648bc4d4b428 100644
--- a/src/util.c
+++ b/src/util.c
@@ -569,17 +569,27 @@ void bump_maxfd(int fd, int *max)
*max = fd;
}
-int retry_send(void)
+/* rc is return from sendto and friends.
+ Return 1 if we should retry.
+ Set errno to zero if we succeeded. */
+int retry_send(ssize_t rc)
{
+ static int retries = 0;
+ struct timespec waiter;
+
+ if (rc != -1)
+ {
+ retries = 0;
+ errno = 0;
+ return 0;
+ }
+
/* Linux kernels can return EAGAIN in perpetuity when calling
sendmsg() and the relevant interface has gone. Here we loop
retrying in EAGAIN for 1 second max, to avoid this hanging
dnsmasq. */
- static int retries = 0;
- struct timespec waiter;
-
- if (errno == EAGAIN || errno == EWOULDBLOCK)
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
{
waiter.tv_sec = 0;
waiter.tv_nsec = 10000;
@@ -587,13 +597,13 @@ int retry_send(void)
if (retries++ < 1000)
return 1;
}
-
- retries = 0;
-
- if (errno == EINTR)
- return 1;
-
- return 0;
+
+ retries = 0;
+
+ if (errno == EINTR)
+ return 1;
+
+ return 0;
}
int read_write(int fd, unsigned char *packet, int size, int rw)
@@ -602,22 +612,21 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
for (done = 0; done < size; done += n)
{
- retry:
- if (rw)
- n = read(fd, &packet[done], (size_t)(size - done));
- else
- n = write(fd, &packet[done], (size_t)(size - done));
-
- if (n == 0)
- return 0;
- else if (n == -1)
- {
- if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
- goto retry;
- else
- return 0;
- }
+ do {
+ if (rw)
+ n = read(fd, &packet[done], (size_t)(size - done));
+ else
+ n = write(fd, &packet[done], (size_t)(size - done));
+
+ if (n == 0)
+ return 0;
+
+ } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
+
+ if (errno != 0)
+ return 0;
}
+
return 1;
}
--
2.1.0

View File

@@ -1,75 +0,0 @@
From 979fe86bc8693f660eddea232ae39cbbb50b294c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 19 Mar 2015 22:50:22 +0000
Subject: [PATCH 059/113] Make --address=/example.com/ equivalent to
--server=/example.com/
---
man/dnsmasq.8 | 7 +++++--
src/network.c | 4 ++--
src/option.c | 2 --
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 2db780d90987..1f1dd7b69c53 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -460,7 +460,7 @@ but provides some syntactic sugar to make specifying address-to-name queries eas
is exactly equivalent to
.B --server=/3.2.1.in-addr.arpa/192.168.0.1
.TP
-.B \-A, --address=/<domain>/[domain/]<ipaddr>
+.B \-A, --address=/<domain>/[domain/][<ipaddr>]
Specify an IP address to return for any host in the given domains.
Queries in the domains are never forwarded and always replied to
with the specified IP address which may be IPv4 or IPv6. To give
@@ -472,7 +472,10 @@ domain specification works in the same was as for --server, with the
additional facility that /#/ matches any domain. Thus
--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
answered from /etc/hosts or DHCP and not sent to an upstream
-nameserver by a more specific --server directive.
+nameserver by a more specific --server directive. As for --server,
+one or more domains with no address returns a no-such-domain answer, so
+--address=/example.com/ is equivalent to --server=/example.com/ and returns
+NXDOMAIN for example.com and all its subdomains.
.TP
.B --ipset=/<domain>/[domain/]<ipset>[,<ipset>]
Places the resolved IP addresses of queries for the specified domains
diff --git a/src/network.c b/src/network.c
index 7045253d467b..992f023c31de 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1459,7 +1459,7 @@ void check_servers(void)
}
}
- if (!(serv->flags & SERV_NO_REBIND))
+ if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
{
if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
{
@@ -1475,7 +1475,7 @@ void check_servers(void)
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
else if (serv->flags & SERV_USE_RESOLV)
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
- else if (!(serv->flags & SERV_LITERAL_ADDRESS))
+ else
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
}
#ifdef HAVE_LOOP
diff --git a/src/option.c b/src/option.c
index eace40bb566c..3009eb545fde 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2284,8 +2284,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{
if (!(newlist->flags & SERV_NO_REBIND))
newlist->flags |= SERV_NO_ADDR; /* no server */
- if (newlist->flags & SERV_LITERAL_ADDRESS)
- ret_err(gen_err);
}
else if (strcmp(arg, "#") == 0)
--
2.1.0

View File

@@ -1,81 +0,0 @@
From 65c721200023ef0023114459a8d12f8b0a24cfd8 Mon Sep 17 00:00:00 2001
From: Lung-Pin Chang <changlp@cs.nctu.edu.tw>
Date: Thu, 19 Mar 2015 23:22:21 +0000
Subject: [PATCH 060/113] dhcp: set outbound interface via cmsg in unicast
reply
If multiple routes to the same network exist, Linux blindly picks
the first interface (route) based on destination address, which might not be
the one we're actually offering leases. Rather than relying on this,
always set the interface for outgoing unicast DHCP packets.
---
src/dhcp.c | 45 +++++++++++++++++++++++++--------------------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/src/dhcp.c b/src/dhcp.c
index 5c3089ab94ff..f1f43f8d8f90 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -376,10 +376,9 @@ void dhcp_packet(time_t now, int pxe_fd)
}
}
#if defined(HAVE_LINUX_NETWORK)
- else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
- mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
+ else
{
- /* broadcast to 255.255.255.255 (or mac address invalid) */
+ /* fill cmsg for outbound interface (both broadcast & unicast) */
struct in_pktinfo *pkt;
msg.msg_control = control_u.control;
msg.msg_controllen = sizeof(control_u);
@@ -389,23 +388,29 @@ void dhcp_packet(time_t now, int pxe_fd)
pkt->ipi_spec_dst.s_addr = 0;
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
cmptr->cmsg_level = IPPROTO_IP;
- cmptr->cmsg_type = IP_PKTINFO;
- dest.sin_addr.s_addr = INADDR_BROADCAST;
- dest.sin_port = htons(daemon->dhcp_client_port);
- }
- else
- {
- /* unicast to unconfigured client. Inject mac address direct into ARP cache.
- struct sockaddr limits size to 14 bytes. */
- dest.sin_addr = mess->yiaddr;
- dest.sin_port = htons(daemon->dhcp_client_port);
- memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
- arp_req.arp_ha.sa_family = mess->htype;
- memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
- /* interface name already copied in */
- arp_req.arp_flags = ATF_COM;
- if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
- my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
+ cmptr->cmsg_type = IP_PKTINFO;
+
+ if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
+ mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
+ {
+ /* broadcast to 255.255.255.255 (or mac address invalid) */
+ dest.sin_addr.s_addr = INADDR_BROADCAST;
+ dest.sin_port = htons(daemon->dhcp_client_port);
+ }
+ else
+ {
+ /* unicast to unconfigured client. Inject mac address direct into ARP cache.
+ struct sockaddr limits size to 14 bytes. */
+ dest.sin_addr = mess->yiaddr;
+ dest.sin_port = htons(daemon->dhcp_client_port);
+ memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
+ arp_req.arp_ha.sa_family = mess->htype;
+ memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
+ /* interface name already copied in */
+ arp_req.arp_flags = ATF_COM;
+ if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
+ my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
+ }
}
#elif defined(HAVE_SOLARIS_NETWORK)
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
--
2.1.0

View File

@@ -1,27 +0,0 @@
From 8805283088d670baecb92569252c01cf754cda51 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 26 Mar 2015 21:15:43 +0000
Subject: [PATCH 061/113] Don't fail DNSSEC when a signed CNAME dangles into an
unsigned zone.
---
src/dnssec.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index ad0d6f072ba2..db5c768bd751 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -2032,7 +2032,8 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
/* First marshall the NSEC records, if we've not done it previously */
if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
- return STAT_BOGUS; /* No NSECs */
+ return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
+ an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
/* Get name of missing answer */
if (!extract_name(header, plen, &qname, name, 1, 0))
--
2.1.0

View File

@@ -1,48 +0,0 @@
From 150162bc37170a6edae9d488435e836b1e4e3a4e Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 27 Mar 2015 09:58:26 +0000
Subject: [PATCH 062/113] Return SERVFAIL when validation abandoned.
---
src/forward.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/forward.c b/src/forward.c
index 7c0fa8da3fdf..985814c3aec5 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -663,6 +663,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
header->ancount = htons(0);
header->nscount = htons(0);
header->arcount = htons(0);
+ header->hb3 &= ~HB3_TC;
}
/* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
@@ -991,7 +992,10 @@ void reply_query(int fd, int family, time_t now)
char *result;
if (forward->work_counter == 0)
- result = "ABANDONED";
+ {
+ result = "ABANDONED";
+ status = STAT_BOGUS;
+ }
else
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
@@ -1938,7 +1942,10 @@ unsigned char *tcp_request(int confd, time_t now,
char *result;
if (keycount == 0)
- result = "ABANDONED";
+ {
+ result = "ABANDONED";
+ status = STAT_BOGUS;
+ }
else
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
--
2.1.0

View File

@@ -1,37 +0,0 @@
From 0b8a5a30a77331974ba24a04e43e720585dfbc61 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 27 Mar 2015 11:44:55 +0000
Subject: [PATCH 063/113] Protect against broken DNSSEC upstreams.
---
src/dnssec.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index db5c768bd751..14bae7e9bf75 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -1177,7 +1177,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
STAT_NO_DS It's proved there's no DS here.
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
+ STAT_NEED_KEY 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)
@@ -1208,7 +1208,10 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
val = STAT_BOGUS;
- if (val == STAT_BOGUS)
+ /* If the key needed to validate the DS is on the same domain as the DS, we'll
+ loop getting nowhere. Stop that now. This can happen of the DS answer comes
+ from the DS's zone, and not the parent zone. */
+ if (val == STAT_BOGUS || (val == STAT_NEED_KEY && hostname_isequal(name, keyname)))
{
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS");
return STAT_BOGUS;
--
2.1.0

View File

@@ -1,197 +0,0 @@
From 1e153945def3c50d1e59ceea6a768db0ac770f98 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 28 Mar 2015 21:34:07 +0000
Subject: [PATCH 064/113] DNSSEC fix for non-ascii characters in labels.
---
src/dnssec.c | 34 +++++++++++++++++-----------------
src/rfc1035.c | 5 +++--
2 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index 14bae7e9bf75..8bd5294ce773 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -552,7 +552,7 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
(*desc)++;
- if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
+ if (d == 0 && extract_name(header, plen, p, buff, 2, 0))
/* domain-name, canonicalise */
return to_wire(buff);
else
@@ -811,7 +811,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
GETLONG(sig_inception, p);
GETSHORT(key_tag, p);
- if (!extract_name(header, plen, &p, keyname, 1, 0))
+ if (!extract_name(header, plen, &p, keyname, 2, 0))
return STAT_BOGUS;
/* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
@@ -866,7 +866,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
u16 len, *dp;
p = rrset[i];
- if (!extract_name(header, plen, &p, name, 1, 10))
+ if (!extract_name(header, plen, &p, name, 2, 10))
return STAT_BOGUS;
name_start = name;
@@ -923,7 +923,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* namebuff used for workspace above, restore to leave unchanged on exit */
p = (unsigned char*)(rrset[0]);
- extract_name(header, plen, &p, name, 1, 0);
+ extract_name(header, plen, &p, name, 2, 0);
if (key)
{
@@ -963,7 +963,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
struct all_addr a;
if (ntohs(header->qdcount) != 1 ||
- !extract_name(header, plen, &p, name, 1, 4))
+ !extract_name(header, plen, &p, name, 2, 4))
return STAT_BOGUS;
GETSHORT(qtype, p);
@@ -1202,7 +1202,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
val = STAT_BOGUS;
p = (unsigned char *)(header+1);
- extract_name(header, plen, &p, name, 1, 4);
+ extract_name(header, plen, &p, name, 2, 4);
p += 4; /* qtype, qclass */
if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
@@ -1419,12 +1419,12 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
for (i = 0; i < nsec_count; i++)
{
p = nsecs[i];
- if (!extract_name(header, plen, &p, workspace1, 1, 10))
+ if (!extract_name(header, plen, &p, workspace1, 2, 10))
return STAT_BOGUS;
p += 8; /* class, type, TTL */
GETSHORT(rdlen, p);
psave = p;
- if (!extract_name(header, plen, &p, workspace2, 1, 10))
+ if (!extract_name(header, plen, &p, workspace2, 2, 10))
return STAT_BOGUS;
rc = hostname_cmp(workspace1, name);
@@ -1553,7 +1553,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i]))
{
- if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
+ if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return 0;
@@ -1730,7 +1730,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i]))
{
- if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
+ if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return STAT_BOGUS;
@@ -1796,7 +1796,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
qname = p1 = (unsigned char *)(header+1);
- if (!extract_name(header, plen, &p1, name, 1, 4))
+ if (!extract_name(header, plen, &p1, name, 2, 4))
return STAT_BOGUS;
GETSHORT(qtype, p1);
@@ -1836,7 +1836,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
qname = p1;
/* looped CNAMES */
- if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
+ if (!cname_count-- || !extract_name(header, plen, &p1, name, 2, 0))
return STAT_BOGUS;
p1 = ans_start;
@@ -1857,7 +1857,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
{
- if (!extract_name(header, plen, &p1, name, 1, 10))
+ if (!extract_name(header, plen, &p1, name, 2, 10))
return STAT_BOGUS; /* bad packet */
GETSHORT(type1, p1);
@@ -2039,7 +2039,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
/* Get name of missing answer */
- if (!extract_name(header, plen, &qname, name, 1, 0))
+ if (!extract_name(header, plen, &qname, name, 2, 0))
return STAT_BOGUS;
if (nsec_type == T_NSEC)
@@ -2061,7 +2061,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
int cname_count = CNAME_CHAIN;
/* Get question */
- if (!extract_name(header, plen, &p, name, 1, 4))
+ if (!extract_name(header, plen, &p, name, 2, 4))
return STAT_BOGUS;
p +=2; /* type */
@@ -2102,7 +2102,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
/* Loop down CNAME chain/ */
if (!cname_count-- ||
- !extract_name(header, plen, &p, name, 1, 0) ||
+ !extract_name(header, plen, &p, name, 2, 0) ||
!(p = skip_questions(header, plen)))
return STAT_BOGUS;
@@ -2419,7 +2419,7 @@ unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name
for (q = ntohs(header->qdcount); q != 0; q--)
{
- if (!extract_name(header, plen, &p, name, 1, 4))
+ if (!extract_name(header, plen, &p, name, 2, 4))
break; /* bad packet */
len = to_wire(name);
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 5ef5ddb7485e..10832a3d5d2e 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -16,6 +16,7 @@
#include "dnsmasq.h"
+/* isExtract == 2 -> DNSSEC mode, no bitstrings, no ascii checks. */
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes)
{
@@ -86,7 +87,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if ((l & 0x3f) != 1)
return 0; /* we only understand bitstrings */
- if (!isExtract)
+ if (isExtract != 1)
return 0; /* Cannot compare bitsrings */
count = *p++;
@@ -128,7 +129,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if (isExtract)
{
unsigned char c = *p;
- if (isascii(c) && !iscntrl(c) && c != '.')
+ if ((isExtract == 2 || (isascii(c) && !iscntrl(c))) && c != '.')
*cp++ = *p;
else
return 0;
--
2.1.0

View File

@@ -1,246 +0,0 @@
From 394ff492da6af5da7e7d356be9586683bc5fc011 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 29 Mar 2015 22:17:14 +0100
Subject: [PATCH 065/113] Allow control characters in names in the cache,
handle when logging.
---
src/cache.c | 19 +++++++++++++++++--
src/dnssec.c | 34 +++++++++++++++++-----------------
src/rfc1035.c | 7 +++----
3 files changed, 37 insertions(+), 23 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index c95624c42b1c..873c5779044c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1399,6 +1399,19 @@ int cache_make_stat(struct txt_record *t)
return 1;
}
+/* There can be names in the cache containing control chars, don't
+ mess up logging or open security holes. */
+static char *sanitise(char *name)
+{
+ unsigned char *r;
+ for (r = (unsigned char *)name; *r; r++)
+ if (!isprint((int)*r))
+ return "<name unprintable>";
+
+ return name;
+}
+
+
void dump_cache(time_t now)
{
struct server *serv, *serv1;
@@ -1452,9 +1465,9 @@ void dump_cache(time_t now)
*a = 0;
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
n = "<Root>";
- p += sprintf(p, "%-30.30s ", n);
+ p += sprintf(p, "%-30.30s ", sanitise(n));
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
- a = cache_get_cname_target(cache);
+ a = sanitise(cache_get_cname_target(cache));
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
{
@@ -1587,6 +1600,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
if (!option_bool(OPT_LOG))
return;
+ name = sanitise(name);
+
if (addr)
{
if (flags & F_KEYTAG)
diff --git a/src/dnssec.c b/src/dnssec.c
index 8bd5294ce773..14bae7e9bf75 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -552,7 +552,7 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
(*desc)++;
- if (d == 0 && extract_name(header, plen, p, buff, 2, 0))
+ if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
/* domain-name, canonicalise */
return to_wire(buff);
else
@@ -811,7 +811,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
GETLONG(sig_inception, p);
GETSHORT(key_tag, p);
- if (!extract_name(header, plen, &p, keyname, 2, 0))
+ if (!extract_name(header, plen, &p, keyname, 1, 0))
return STAT_BOGUS;
/* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
@@ -866,7 +866,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
u16 len, *dp;
p = rrset[i];
- if (!extract_name(header, plen, &p, name, 2, 10))
+ if (!extract_name(header, plen, &p, name, 1, 10))
return STAT_BOGUS;
name_start = name;
@@ -923,7 +923,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* namebuff used for workspace above, restore to leave unchanged on exit */
p = (unsigned char*)(rrset[0]);
- extract_name(header, plen, &p, name, 2, 0);
+ extract_name(header, plen, &p, name, 1, 0);
if (key)
{
@@ -963,7 +963,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
struct all_addr a;
if (ntohs(header->qdcount) != 1 ||
- !extract_name(header, plen, &p, name, 2, 4))
+ !extract_name(header, plen, &p, name, 1, 4))
return STAT_BOGUS;
GETSHORT(qtype, p);
@@ -1202,7 +1202,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
val = STAT_BOGUS;
p = (unsigned char *)(header+1);
- extract_name(header, plen, &p, name, 2, 4);
+ extract_name(header, plen, &p, name, 1, 4);
p += 4; /* qtype, qclass */
if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
@@ -1419,12 +1419,12 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
for (i = 0; i < nsec_count; i++)
{
p = nsecs[i];
- if (!extract_name(header, plen, &p, workspace1, 2, 10))
+ if (!extract_name(header, plen, &p, workspace1, 1, 10))
return STAT_BOGUS;
p += 8; /* class, type, TTL */
GETSHORT(rdlen, p);
psave = p;
- if (!extract_name(header, plen, &p, workspace2, 2, 10))
+ if (!extract_name(header, plen, &p, workspace2, 1, 10))
return STAT_BOGUS;
rc = hostname_cmp(workspace1, name);
@@ -1553,7 +1553,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i]))
{
- if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
+ if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return 0;
@@ -1730,7 +1730,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i]))
{
- if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
+ if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return STAT_BOGUS;
@@ -1796,7 +1796,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
qname = p1 = (unsigned char *)(header+1);
- if (!extract_name(header, plen, &p1, name, 2, 4))
+ if (!extract_name(header, plen, &p1, name, 1, 4))
return STAT_BOGUS;
GETSHORT(qtype, p1);
@@ -1836,7 +1836,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
qname = p1;
/* looped CNAMES */
- if (!cname_count-- || !extract_name(header, plen, &p1, name, 2, 0))
+ if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
return STAT_BOGUS;
p1 = ans_start;
@@ -1857,7 +1857,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
{
- if (!extract_name(header, plen, &p1, name, 2, 10))
+ if (!extract_name(header, plen, &p1, name, 1, 10))
return STAT_BOGUS; /* bad packet */
GETSHORT(type1, p1);
@@ -2039,7 +2039,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
/* Get name of missing answer */
- if (!extract_name(header, plen, &qname, name, 2, 0))
+ if (!extract_name(header, plen, &qname, name, 1, 0))
return STAT_BOGUS;
if (nsec_type == T_NSEC)
@@ -2061,7 +2061,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
int cname_count = CNAME_CHAIN;
/* Get question */
- if (!extract_name(header, plen, &p, name, 2, 4))
+ if (!extract_name(header, plen, &p, name, 1, 4))
return STAT_BOGUS;
p +=2; /* type */
@@ -2102,7 +2102,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
/* Loop down CNAME chain/ */
if (!cname_count-- ||
- !extract_name(header, plen, &p, name, 2, 0) ||
+ !extract_name(header, plen, &p, name, 1, 0) ||
!(p = skip_questions(header, plen)))
return STAT_BOGUS;
@@ -2419,7 +2419,7 @@ unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name
for (q = ntohs(header->qdcount); q != 0; q--)
{
- if (!extract_name(header, plen, &p, name, 2, 4))
+ if (!extract_name(header, plen, &p, name, 1, 4))
break; /* bad packet */
len = to_wire(name);
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 10832a3d5d2e..7a07b0cee906 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -16,7 +16,6 @@
#include "dnsmasq.h"
-/* isExtract == 2 -> DNSSEC mode, no bitstrings, no ascii checks. */
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes)
{
@@ -87,7 +86,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if ((l & 0x3f) != 1)
return 0; /* we only understand bitstrings */
- if (isExtract != 1)
+ if (!isExtract)
return 0; /* Cannot compare bitsrings */
count = *p++;
@@ -129,8 +128,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if (isExtract)
{
unsigned char c = *p;
- if ((isExtract == 2 || (isascii(c) && !iscntrl(c))) && c != '.')
- *cp++ = *p;
+ if (c != 0 && c != '.')
+ *cp++ = c;
else
return 0;
}
--
2.1.0

View File

@@ -1,30 +0,0 @@
From 794fccca7ffebfba4468bfffc6276b68bbf6afd9 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 29 Mar 2015 22:35:44 +0100
Subject: [PATCH 066/113] Fix crash in last commit.
---
src/cache.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 873c5779044c..d7bea574c0d8 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1404,9 +1404,10 @@ int cache_make_stat(struct txt_record *t)
static char *sanitise(char *name)
{
unsigned char *r;
- for (r = (unsigned char *)name; *r; r++)
- if (!isprint((int)*r))
- return "<name unprintable>";
+ if (name)
+ for (r = (unsigned char *)name; *r; r++)
+ if (!isprint((int)*r))
+ return "<name unprintable>";
return name;
}
--
2.1.0

File diff suppressed because it is too large Load Diff

View File

@@ -1,199 +0,0 @@
From 30d0879ed55cb67b1b735beab3d93f3bb3ef1dd2 Mon Sep 17 00:00:00 2001
From: Stefan Tomanek <stefan.tomanek+dnsmasq@wertarbyte.de>
Date: Tue, 31 Mar 2015 22:32:11 +0100
Subject: [PATCH 068/113] add --tftp-no-fail to ignore missing tftp root
---
CHANGELOG | 3 +++
dnsmasq.conf.example | 3 +++
man/dnsmasq.8 | 3 +++
src/dnsmasq.c | 40 ++++++++++++++++++++++++++++++----------
src/dnsmasq.h | 4 +++-
src/option.c | 3 +++
6 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 4f4fa305deaa..34432ae4807f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -72,6 +72,9 @@ version 2.73
on systems without an RTC, whilst allowing DNS queries before the
clock is valid so that NTP can run. Thanks to
Kevin Darbyshire-Bryant for developing this idea.
+
+ Add --tftp-no-fail option. Thanks to Stefan Tomanek for
+ the patch.
version 2.72
diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example
index 1bd305dbdbad..67be99acb028 100644
--- a/dnsmasq.conf.example
+++ b/dnsmasq.conf.example
@@ -486,6 +486,9 @@
# Set the root directory for files available via FTP.
#tftp-root=/var/ftpd
+# Do not abort if the tftp-root is unavailable
+#tftp-no-fail
+
# Make the TFTP server more secure: with this set, only files owned by
# the user dnsmasq is running as will be send over the net.
#tftp-secure
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 1f1dd7b69c53..6b4626cc0aad 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -1711,6 +1711,9 @@ Absolute paths (starting with /) are allowed, but they must be within
the tftp-root. If the optional interface argument is given, the
directory is only used for TFTP requests via that interface.
.TP
+.B --tftp-no-fail
+Do not abort startup if specified tftp root directories are inaccessible.
+.TP
.B --tftp-unique-root
Add the IP address of the TFTP client as a path component on the end
of the TFTP-root (in standard dotted-quad format). Only valid if a
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index b784951950d4..0d4d4558a2e2 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -58,6 +58,9 @@ int main (int argc, char **argv)
struct dhcp_context *context;
struct dhcp_relay *relay;
#endif
+#ifdef HAVE_TFTP
+ int tftp_prefix_missing = 0;
+#endif
#ifdef LOCALEDIR
setlocale(LC_ALL, "");
@@ -636,7 +639,7 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_TFTP
- if (option_bool(OPT_TFTP))
+ if (option_bool(OPT_TFTP))
{
DIR *dir;
struct tftp_prefix *p;
@@ -645,24 +648,33 @@ int main (int argc, char **argv)
{
if (!((dir = opendir(daemon->tftp_prefix))))
{
- send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
- _exit(0);
+ tftp_prefix_missing = 1;
+ if (!option_bool(OPT_TFTP_NO_FAIL))
+ {
+ send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
+ _exit(0);
+ }
}
closedir(dir);
}
-
+
for (p = daemon->if_prefix; p; p = p->next)
{
+ p->missing = 0;
if (!((dir = opendir(p->prefix))))
- {
- send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
- _exit(0);
- }
+ {
+ p->missing = 1;
+ if (!option_bool(OPT_TFTP_NO_FAIL))
+ {
+ send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
+ _exit(0);
+ }
+ }
closedir(dir);
}
}
#endif
-
+
if (daemon->port == 0)
my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
else if (daemon->cachesize != 0)
@@ -772,7 +784,8 @@ int main (int argc, char **argv)
#ifdef HAVE_TFTP
if (option_bool(OPT_TFTP))
- {
+ {
+ struct tftp_prefix *p;
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
max_fd = FD_SETSIZE;
@@ -782,7 +795,14 @@ int main (int argc, char **argv)
daemon->tftp_prefix ? _("root is ") : _("enabled"),
daemon->tftp_prefix ? daemon->tftp_prefix: "",
option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
+
+ if (tftp_prefix_missing)
+ my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
+ for (p = daemon->if_prefix; p; p = p->next)
+ if (p->missing)
+ my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
+
/* This is a guess, it assumes that for small limits,
disjoint files might be served, but for large limits,
a single file will be sent to may clients (the file only needs
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index de95d0e875e3..42952fc76c7a 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -240,7 +240,8 @@ struct event_desc {
#define OPT_LOCAL_SERVICE 49
#define OPT_LOOP_DETECT 50
#define OPT_EXTRALOG 51
-#define OPT_LAST 52
+#define OPT_TFTP_NO_FAIL 52
+#define OPT_LAST 53
/* 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. */
@@ -901,6 +902,7 @@ struct addr_list {
struct tftp_prefix {
char *interface;
char *prefix;
+ int missing;
struct tftp_prefix *next;
};
diff --git a/src/option.c b/src/option.c
index 3009eb545fde..f91cfbb1aa54 100644
--- a/src/option.c
+++ b/src/option.c
@@ -153,6 +153,7 @@ struct myoption {
#define LOPT_DHOPT_INOTIFY 341
#define LOPT_HOST_INOTIFY 342
#define LOPT_DNSSEC_STAMP 343
+#define LOPT_TFTP_NO_FAIL 344
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -235,6 +236,7 @@ static const struct myoption opts[] =
{ "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
{ "enable-tftp", 2, 0, LOPT_TFTP },
{ "tftp-secure", 0, 0, LOPT_SECURE },
+ { "tftp-no-fail", 0, 0, LOPT_TFTP_NO_FAIL },
{ "tftp-unique-root", 0, 0, LOPT_APREF },
{ "tftp-root", 1, 0, LOPT_PREFIX },
{ "tftp-max", 1, 0, LOPT_TFTP_MAX },
@@ -419,6 +421,7 @@ static struct {
{ LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
{ LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
{ LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
+ { LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noop("Do not terminate the service if TFTP directories are inaccessible."), NULL },
{ LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
{ LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
--
2.1.0

View File

@@ -1,85 +0,0 @@
From 7aa970e2c7043201663d86a4b5d8cd5c592cef39 Mon Sep 17 00:00:00 2001
From: Stefan Tomanek <stefan.tomanek+dnsmasq@wertarbyte.de>
Date: Wed, 1 Apr 2015 17:55:07 +0100
Subject: [PATCH 069/113] Whitespace fixes.
---
src/dnsmasq.c | 14 +++++++-------
src/tftp.c | 2 +-
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 0d4d4558a2e2..a7c5da8fbd01 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -345,7 +345,7 @@ int main (int argc, char **argv)
#else
die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
#endif
-
+
if (daemon->port != 0)
pre_allocate_sfds();
@@ -657,7 +657,7 @@ int main (int argc, char **argv)
}
closedir(dir);
}
-
+
for (p = daemon->if_prefix; p; p = p->next)
{
p->missing = 0;
@@ -669,12 +669,12 @@ int main (int argc, char **argv)
send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
_exit(0);
}
- }
+ }
closedir(dir);
}
}
#endif
-
+
if (daemon->port == 0)
my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
else if (daemon->cachesize != 0)
@@ -784,7 +784,7 @@ int main (int argc, char **argv)
#ifdef HAVE_TFTP
if (option_bool(OPT_TFTP))
- {
+ {
struct tftp_prefix *p;
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
@@ -795,10 +795,10 @@ int main (int argc, char **argv)
daemon->tftp_prefix ? _("root is ") : _("enabled"),
daemon->tftp_prefix ? daemon->tftp_prefix: "",
option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
-
+
if (tftp_prefix_missing)
my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
-
+
for (p = daemon->if_prefix; p; p = p->next)
if (p->missing)
my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
diff --git a/src/tftp.c b/src/tftp.c
index a57a31514f44..d3fb6d7492e4 100644
--- a/src/tftp.c
+++ b/src/tftp.c
@@ -236,7 +236,7 @@ void tftp_request(struct listener *listen, time_t now)
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
}
-
+
if (name)
{
/* check for per-interface prefix */
--
2.1.0

View File

@@ -1,254 +0,0 @@
From fe3992f9fa69fa975ea31919c53933b5f6a63527 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 3 Apr 2015 21:25:05 +0100
Subject: [PATCH 070/113] Return INSECURE, rather than BOGUS when DS proved not
to exist.
Return INSECURE when validating DNS replies which have RRSIGs, but
when a needed DS record in the trust chain is proved not to exist.
It's allowed for a zone to set up DNSKEY and RRSIG records first, then
add a DS later, completing the chain of trust.
Also, since we don't have the infrastructure to track that these
non-validated replies have RRSIGS, don't cache them, so we don't
provide answers with missing RRSIGS from the cache.
---
src/dnsmasq.h | 1 +
src/dnssec.c | 2 +-
src/forward.c | 87 +++++++++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 69 insertions(+), 21 deletions(-)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 42952fc76c7a..6fe4a4189188 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -583,6 +583,7 @@ struct hostsfile {
#define STAT_NO_NS 10
#define STAT_NEED_DS_NEG 11
#define STAT_CHASE_CNAME 12
+#define STAT_INSECURE_DS 13
#define FREC_NOREBIND 1
#define FREC_CHECKING_DISABLED 2
diff --git a/src/dnssec.c b/src/dnssec.c
index 14bae7e9bf75..05e0983cb251 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -981,7 +981,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
/* If we've cached that DS provably doesn't exist, result must be INSECURE */
if (crecp->flags & F_NEG)
- return STAT_INSECURE;
+ return STAT_INSECURE_DS;
/* NOTE, we need to find ONE DNSKEY which matches the DS */
for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--)
diff --git a/src/forward.c b/src/forward.c
index 985814c3aec5..e8cf615aa939 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -521,7 +521,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
- int no_cache, int cache_secure, int ad_reqd, int do_bit, int added_pheader, int check_subnet, union mysockaddr *query_source)
+ int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
+ int check_subnet, union mysockaddr *query_source)
{
unsigned char *pheader, *sizep;
char **sets = 0;
@@ -634,7 +635,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
}
#ifdef HAVE_DNSSEC
- if (no_cache && !(header->hb4 & HB4_CD))
+ if (bogusanswer && !(header->hb4 & HB4_CD))
{
if (!option_bool(OPT_DNSSEC_DEBUG))
{
@@ -786,7 +787,7 @@ void reply_query(int fd, int family, time_t now)
everything is broken */
if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != SERVFAIL)
{
- int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0;
+ int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
if (option_bool(OPT_NO_REBIND))
check_rebind = !(forward->flags & FREC_NOREBIND);
@@ -819,7 +820,13 @@ 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_NO_NS)
+ /* Provably no DS, everything below is insecure, even if signatures are offered */
+ if (status == STAT_NO_DS)
+ /* We only cache sigs when we've validated a reply.
+ Avoid caching a reply with sigs if there's a vaildated break in the
+ DS chain, so we don't return replies from cache missing sigs. */
+ status = STAT_INSECURE_DS;
+ else if (status == STAT_NO_NS)
status = STAT_BOGUS;
}
else if (forward->flags & FREC_CHECK_NOSIGN)
@@ -959,8 +966,14 @@ 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_NO_NS)
- status = STAT_BOGUS;
+ /* Provably no DS, everything below is insecure, even if signatures are offered */
+ if (status == STAT_NO_DS)
+ /* We only cache sigs when we've validated a reply.
+ Avoid caching a reply with sigs if there's a vaildated break in the
+ DS chain, so we don't return replies from cache missing sigs. */
+ status = STAT_INSECURE_DS;
+ else if (status == STAT_NO_NS)
+ status = STAT_BOGUS;
}
else if (forward->flags & FREC_CHECK_NOSIGN)
{
@@ -985,6 +998,17 @@ void reply_query(int fd, int family, time_t now)
}
}
+ no_cache_dnssec = 0;
+
+ if (status == STAT_INSECURE_DS)
+ {
+ /* We only cache sigs when we've validated a reply.
+ Avoid caching a reply with sigs if there's a vaildated break in the
+ DS chain, so we don't return replies from cache missing sigs. */
+ status = STAT_INSECURE;
+ no_cache_dnssec = 1;
+ }
+
if (status == STAT_TRUNCATED)
header->hb3 |= HB3_TC;
else
@@ -1002,12 +1026,13 @@ void reply_query(int fd, int family, time_t now)
log_query(F_KEYTAG | F_SECSTAT, "result", NULL, result);
}
- no_cache_dnssec = 0;
-
if (status == STAT_SECURE)
cache_secure = 1;
else if (status == STAT_BOGUS)
- no_cache_dnssec = 1;
+ {
+ no_cache_dnssec = 1;
+ bogusanswer = 1;
+ }
}
#endif
@@ -1017,7 +1042,7 @@ void reply_query(int fd, int family, time_t now)
else
header->hb4 &= ~HB4_CD;
- if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, no_cache_dnssec, cache_secure,
+ if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
{
@@ -1420,7 +1445,7 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam
}
}
-/* Move toward the root, until we find a signed non-existance of a DS, in which case
+/* Move down from the root, until we find a signed non-existance of a DS, in which case
an unsigned answer is OK, or we find a signed DS, in which case there should be
a signature, and the answer is BOGUS */
static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, size_t plen, int class, char *name,
@@ -1570,8 +1595,13 @@ 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_NO_NS))
- new_status = STAT_BOGUS;
+ if (status == STAT_NEED_DS)
+ {
+ if (new_status == STAT_NO_DS)
+ new_status = STAT_INSECURE_DS;
+ else if (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);
@@ -1630,8 +1660,13 @@ 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_NO_NS))
- new_status = STAT_BOGUS; /* Validated no DS */
+ if (status == STAT_NEED_DS)
+ {
+ if (new_status == STAT_NO_DS)
+ new_status = STAT_INSECURE_DS;
+ else if (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);
@@ -1652,7 +1687,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
goto another_tcp_key;
}
}
-
+
free(packet);
}
return new_status;
@@ -1673,7 +1708,7 @@ unsigned char *tcp_request(int confd, time_t now,
int local_auth = 0;
#endif
int checking_disabled, ad_question, do_bit, added_pheader = 0;
- int check_subnet, no_cache_dnssec = 0, cache_secure = 0;
+ int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
size_t m;
unsigned short qtype;
unsigned int gotname;
@@ -1941,6 +1976,15 @@ unsigned char *tcp_request(int confd, time_t now,
int status = tcp_key_recurse(now, STAT_TRUNCATED, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
char *result;
+ if (status == STAT_INSECURE_DS)
+ {
+ /* We only cache sigs when we've validated a reply.
+ Avoid caching a reply with sigs if there's a vaildated break in the
+ DS chain, so we don't return replies from cache missing sigs. */
+ status = STAT_INSECURE;
+ no_cache_dnssec = 1;
+ }
+
if (keycount == 0)
{
result = "ABANDONED";
@@ -1952,8 +1996,11 @@ unsigned char *tcp_request(int confd, time_t now,
log_query(F_KEYTAG | F_SECSTAT, "result", NULL, result);
if (status == STAT_BOGUS)
- no_cache_dnssec = 1;
-
+ {
+ no_cache_dnssec = 1;
+ bogusanswer = 1;
+ }
+
if (status == STAT_SECURE)
cache_secure = 1;
}
@@ -1987,7 +2034,7 @@ unsigned char *tcp_request(int confd, time_t now,
#endif
m = process_reply(header, now, last_server, (unsigned int)m,
- option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec,
+ option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, bogusanswer,
cache_secure, ad_question, do_bit, added_pheader, check_subnet, &peer_addr);
break;
--
2.1.0

View File

@@ -1,26 +0,0 @@
From 982faf402487e265ed11ac03524531d42b03c966 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 3 Apr 2015 21:42:30 +0100
Subject: [PATCH 071/113] Fix compiler warning when not including DNSSEC.
---
src/forward.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/forward.c b/src/forward.c
index e8cf615aa939..3f6b9a23b6ab 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -530,7 +530,8 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
size_t plen;
(void)ad_reqd;
- (void) do_bit;
+ (void)do_bit;
+ (void)bogusanswer;
#ifdef HAVE_IPSET
if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
--
2.1.0

View File

@@ -1,54 +0,0 @@
From 04b0ac05377936d121a36873bb63d492cde292c9 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 6 Apr 2015 17:19:13 +0100
Subject: [PATCH 072/113] Fix crash caused by looking up servers.bind when many
servers defined.
---
CHANGELOG | 7 ++++++-
src/cache.c | 4 ++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 34432ae4807f..6aa3d851a297 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -75,7 +75,12 @@ version 2.73
Add --tftp-no-fail option. Thanks to Stefan Tomanek for
the patch.
-
+
+ Fix crash caused by looking up servers.bind, CHAOS text record,
+ when more than about five --servers= lines are in the dnsmasq
+ config. This causes memory corruption which causes a crash later.
+ Thanks to Matt Coddington for sterling work chasing this down.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/cache.c b/src/cache.c
index d7bea574c0d8..178d654ca92e 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1367,7 +1367,7 @@ int cache_make_stat(struct txt_record *t)
}
port = prettyprint_addr(&serv->addr, daemon->addrbuff);
lenp = p++; /* length */
- bytes_avail = (p - buff) + bufflen;
+ bytes_avail = bufflen - (p - buff );
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
if (bytes_needed >= bytes_avail)
{
@@ -1381,7 +1381,7 @@ int cache_make_stat(struct txt_record *t)
lenp = p - 1;
buff = new;
bufflen = newlen;
- bytes_avail = (p - buff) + bufflen;
+ bytes_avail = bufflen - (p - buff );
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
}
*lenp = bytes_needed;
--
2.1.0

View File

@@ -1,62 +0,0 @@
From ad4a8ff7d9097008d7623df8543df435bfddeac8 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 9 Apr 2015 21:48:00 +0100
Subject: [PATCH 073/113] Fix crash on receipt of certain malformed DNS
requests.
---
CHANGELOG | 3 +++
src/rfc1035.c | 9 ++++++---
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 6aa3d851a297..9af617056f1f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -125,6 +125,9 @@ version 2.72
Fix problem with --local-service option on big-endian platforms
Thanks to Richard Genoud for the patch.
+ Fix crash on receipt of certain malformed DNS requests. Thanks
+ to Nick Sampanis for spotting the problem.
+
version 2.71
Subtle change to error handling to help DNSSEC validation
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 7a07b0cee906..a995ab50d74a 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1198,7 +1198,10 @@ unsigned int extract_request(struct dns_header *header, size_t qlen, char *name,
size_t setup_reply(struct dns_header *header, size_t qlen,
struct all_addr *addrp, unsigned int flags, unsigned long ttl)
{
- unsigned char *p = skip_questions(header, qlen);
+ unsigned char *p;
+
+ if (!(p = skip_questions(header, qlen)))
+ return 0;
/* clear authoritative and truncated flags, set QR flag */
header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
@@ -1214,7 +1217,7 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
SET_RCODE(header, NOERROR); /* empty domain */
else if (flags == F_NXDOMAIN)
SET_RCODE(header, NXDOMAIN);
- else if (p && flags == F_IPV4)
+ else if (flags == F_IPV4)
{ /* we know the address */
SET_RCODE(header, NOERROR);
header->ancount = htons(1);
@@ -1222,7 +1225,7 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
}
#ifdef HAVE_IPV6
- else if (p && flags == F_IPV6)
+ else if (flags == F_IPV6)
{
SET_RCODE(header, NOERROR);
header->ancount = htons(1);
--
2.1.0

View File

@@ -1,113 +0,0 @@
From 38440b204db65f9be16c4c3daa7e991e4356f6ed Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 12 Apr 2015 21:52:47 +0100
Subject: [PATCH 074/113] Fix crash in auth code with odd configuration.
---
CHANGELOG | 32 +++++++++++++++++++++-----------
src/auth.c | 13 ++++++++-----
2 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 9af617056f1f..f2142c71cbdc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -68,18 +68,31 @@ version 2.73
Fix broken DNSSEC validation of ECDSA signatures.
Add --dnssec-timestamp option, which provides an automatic
- way to detect when the system time becomes valid after boot
- on systems without an RTC, whilst allowing DNS queries before the
- clock is valid so that NTP can run. Thanks to
- Kevin Darbyshire-Bryant for developing this idea.
+ way to detect when the system time becomes valid after
+ boot on systems without an RTC, whilst allowing DNS
+ queries before the clock is valid so that NTP can run.
+ Thanks to Kevin Darbyshire-Bryant for developing this idea.
Add --tftp-no-fail option. Thanks to Stefan Tomanek for
the patch.
- Fix crash caused by looking up servers.bind, CHAOS text record,
- when more than about five --servers= lines are in the dnsmasq
- config. This causes memory corruption which causes a crash later.
- Thanks to Matt Coddington for sterling work chasing this down.
+ Fix crash caused by looking up servers.bind, CHAOS text
+ record, when more than about five --servers= lines are
+ in the dnsmasq config. This causes memory corruption
+ which causes a crash later. Thanks to Matt Coddington for
+ sterling work chasing this down.
+
+ Fix crash on receipt of certain malformed DNS requests.
+ Thanks to Nick Sampanis for spotting the problem.
+
+ Fix crash in authoritative DNS code, if a .arpa zone
+ is declared as authoritative, and then a PTR query which
+ is not to be treated as authoritative arrived. Normally,
+ directly declaring .arpa zone as authoritative is not
+ done, so this crash wouldn't be seen. Instead the
+ relevant .arpa zone should be specified as a subnet
+ in the auth-zone declaration. Thanks to Johnny S. Lee
+ for the bugreport and initial patch.
version 2.72
@@ -125,10 +138,7 @@ version 2.72
Fix problem with --local-service option on big-endian platforms
Thanks to Richard Genoud for the patch.
- Fix crash on receipt of certain malformed DNS requests. Thanks
- to Nick Sampanis for spotting the problem.
-
version 2.71
Subtle change to error handling to help DNSSEC validation
when servers fail to provide NODATA answers for
diff --git a/src/auth.c b/src/auth.c
index 15721e52793f..4a5c39fc5c07 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -141,7 +141,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = find_subnet(zone, flag, &addr)))
break;
-
+
if (!zone)
{
auth = 0;
@@ -186,7 +186,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (intr)
{
- if (in_zone(zone, intr->name, NULL))
+ if (local_query || in_zone(zone, intr->name, NULL))
{
found = 1;
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
@@ -208,8 +208,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
*p = 0; /* must be bare name */
/* add external domain */
- strcat(name, ".");
- strcat(name, zone->domain);
+ if (zone)
+ {
+ strcat(name, ".");
+ strcat(name, zone->domain);
+ }
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
@@ -217,7 +220,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
T_PTR, C_IN, "d", name))
anscount++;
}
- else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
+ else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
{
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
found = 1;
--
2.1.0

View File

@@ -1,106 +0,0 @@
From 78c6184752dce27849e36cce4360abc27b8d76d2 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 16 Apr 2015 15:05:30 +0100
Subject: [PATCH 075/113] Auth: correct replies to NS and SOA in .arpa zones.
---
CHANGELOG | 8 ++++++++
src/auth.c | 51 ++++++++++++++++++++++++++++++---------------------
2 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index f2142c71cbdc..0619788e9cef 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -94,6 +94,14 @@ version 2.73
in the auth-zone declaration. Thanks to Johnny S. Lee
for the bugreport and initial patch.
+ Fix authoritative DNS code to correctly reply to NS
+ and SOA queries for .arpa zones for which we are
+ declared authoritative by means of a subnet in auth-zone.
+ Previously we provided correct answers to PTR queries
+ in such zones (including NS and SOA) but not direct
+ NS and SOA queries. Thanks to Johnny S. Lee for
+ pointing out the problem.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/auth.c b/src/auth.c
index 4a5c39fc5c07..2b0b7d6b052d 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -131,24 +131,27 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
continue;
}
- if (qtype == T_PTR)
+ if ((qtype == T_PTR || qtype == T_SOA || qtype == T_NS) &&
+ (flag = in_arpa_name_2_addr(name, &addr)) &&
+ !local_query)
{
- if (!(flag = in_arpa_name_2_addr(name, &addr)))
- continue;
-
- if (!local_query)
+ for (zone = daemon->auth_zones; zone; zone = zone->next)
+ if ((subnet = find_subnet(zone, flag, &addr)))
+ break;
+
+ if (!zone)
{
- for (zone = daemon->auth_zones; zone; zone = zone->next)
- if ((subnet = find_subnet(zone, flag, &addr)))
- break;
-
- if (!zone)
- {
- auth = 0;
- continue;
- }
+ auth = 0;
+ continue;
}
+ else if (qtype == T_SOA)
+ soa = 1, found = 1;
+ else if (qtype == T_NS)
+ ns = 1, found = 1;
+ }
+ if (qtype == T_PTR && flag)
+ {
intr = NULL;
if (flag == F_IPV4)
@@ -243,14 +246,20 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
cname_restart:
- for (zone = daemon->auth_zones; zone; zone = zone->next)
- if (in_zone(zone, name, &cut))
- break;
-
- if (!zone)
+ if (found)
+ /* NS and SOA .arpa requests have set found above. */
+ cut = NULL;
+ else
{
- auth = 0;
- continue;
+ for (zone = daemon->auth_zones; zone; zone = zone->next)
+ if (in_zone(zone, name, &cut))
+ break;
+
+ if (!zone)
+ {
+ auth = 0;
+ continue;
+ }
}
for (rec = daemon->mxnames; rec; rec = rec->next)
--
2.1.0

View File

@@ -1,36 +0,0 @@
From b4c0f092d8ce63ea4763c0ac17aa8d24318ad301 Mon Sep 17 00:00:00 2001
From: Stefan Tomanek <stefan.tomanek+dnsmasq@wertarbyte.de>
Date: Thu, 16 Apr 2015 15:20:59 +0100
Subject: [PATCH 076/113] Fix (srk induced) crash in new tftp_no_fail code.
---
src/dnsmasq.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index a7c5da8fbd01..20b15c05103a 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -655,7 +655,8 @@ int main (int argc, char **argv)
_exit(0);
}
}
- closedir(dir);
+ else
+ closedir(dir);
}
for (p = daemon->if_prefix; p; p = p->next)
@@ -670,7 +671,8 @@ int main (int argc, char **argv)
_exit(0);
}
}
- closedir(dir);
+ else
+ closedir(dir);
}
}
#endif
--
2.1.0

View File

@@ -1,26 +0,0 @@
From 0df29f5e23fd2f16181847db1fcf3a8b392d869a Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 16 Apr 2015 15:24:52 +0100
Subject: [PATCH 077/113] Note CVE-2015-3294
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 0619788e9cef..7f2b1e002e9e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -84,6 +84,9 @@ version 2.73
Fix crash on receipt of certain malformed DNS requests.
Thanks to Nick Sampanis for spotting the problem.
+ Note that this is could allow the dnsmasq process's
+ memory to be read by an attacker under certain
+ circumstances, so it has a CVE, CVE-2015-3294
Fix crash in authoritative DNS code, if a .arpa zone
is declared as authoritative, and then a PTR query which
--
2.1.0

View File

@@ -1,59 +0,0 @@
From 554b580e970275d5a869cb4fbfb2716f92b2f664 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 17 Apr 2015 22:50:20 +0100
Subject: [PATCH 078/113] Log domain when reporting DNSSEC validation failure.
---
src/forward.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/forward.c b/src/forward.c
index 3f6b9a23b6ab..1c7da3f5655c 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -1014,7 +1014,7 @@ void reply_query(int fd, int family, time_t now)
header->hb3 |= HB3_TC;
else
{
- char *result;
+ char *result, *domain = "result";
if (forward->work_counter == 0)
{
@@ -1024,7 +1024,10 @@ void reply_query(int fd, int family, time_t now)
else
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
- log_query(F_KEYTAG | F_SECSTAT, "result", NULL, result);
+ if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
+ domain = daemon->namebuff;
+
+ log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
}
if (status == STAT_SECURE)
@@ -1975,7 +1978,7 @@ unsigned char *tcp_request(int confd, time_t now,
{
int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
int status = tcp_key_recurse(now, STAT_TRUNCATED, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
- char *result;
+ char *result, *domain = "result";
if (status == STAT_INSECURE_DS)
{
@@ -1993,8 +1996,10 @@ unsigned char *tcp_request(int confd, time_t now,
}
else
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
-
- log_query(F_KEYTAG | F_SECSTAT, "result", NULL, result);
+ if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
+ domain = daemon->namebuff;
+
+ log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
if (status == STAT_BOGUS)
{
--
2.1.0

View File

@@ -1,28 +0,0 @@
From a006eb7e1486023480ea40244720ef7aab51de71 Mon Sep 17 00:00:00 2001
From: Moshe Levi <moshele@mellanox.com>
Date: Sun, 19 Apr 2015 22:10:40 +0100
Subject: [PATCH 079/113] Check IP address command line arg in dhcp_release.c
---
contrib/wrt/dhcp_release.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/contrib/wrt/dhcp_release.c b/contrib/wrt/dhcp_release.c
index 53f47dda3aec..a51f04b30cab 100644
--- a/contrib/wrt/dhcp_release.c
+++ b/contrib/wrt/dhcp_release.c
@@ -277,6 +277,11 @@ int main(int argc, char **argv)
exit(1);
}
+ if (inet_addr(argv[2]) == INADDR_NONE)
+ {
+ perror("invalid ip address");
+ exit(1);
+ }
lease.s_addr = inet_addr(argv[2]);
server = find_interface(lease, nl, if_nametoindex(argv[1]));
--
2.1.0

View File

@@ -1,53 +0,0 @@
From 338b340be9e7198f5c0f68133d070d6598a0814c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 20 Apr 2015 21:34:05 +0100
Subject: [PATCH 080/113] Revert 61b838dd574c51d96fef100285a0d225824534f9 and
just quieten log instead.
---
src/rfc3315.c | 24 ++++++++++--------------
1 file changed, 10 insertions(+), 14 deletions(-)
diff --git a/src/rfc3315.c b/src/rfc3315.c
index c1ddc805988d..c45116a40a09 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -824,25 +824,21 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
else
{
- /* Windows 8 always requests an address even if the Managed bit
- in RA is 0 and it keeps retrying if it receives a reply
- stating that no addresses are available. We solve this
- by not replying at all if we're not configured to give any
- addresses by DHCPv6. RFC 3315 17.2.1. appears to allow this. */
-
- for (c = state->context; c; c = c->current)
- if (!(c->flags & CONTEXT_RA_STATELESS))
- break;
-
- if (!c)
- return 0;
-
/* no address, return error */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOADDRS);
put_opt6_string(_("no addresses available"));
end_opt6(o1);
- log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
+
+ /* Some clients will ask repeatedly when we're not giving
+ out addresses because we're in stateless mode. Avoid spamming
+ the log in that case. */
+ for (c = state->context; c; c = c->current)
+ if (!(c->flags & CONTEXT_RA_STATELESS))
+ {
+ log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
+ break;
+ }
}
break;
--
2.1.0

View File

@@ -1,215 +0,0 @@
From cbe379ad6b52a538a4416a7cd992817e5637ccf9 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 21 Apr 2015 22:57:06 +0100
Subject: [PATCH 081/113] Handle domain names with '.' or /000 within labels.
Only in DNSSEC mode, where we might need to validate or store
such names. In none-DNSSEC mode, simply don't cache these, as before.
---
src/dns-protocol.h | 4 ++++
src/dnsmasq.c | 15 +++++++++++++--
src/dnssec.c | 40 +++++++++++++++++++++++++++++++---------
src/rfc1035.c | 16 +++++++++++++++-
src/util.c | 9 ++++++++-
5 files changed, 71 insertions(+), 13 deletions(-)
diff --git a/src/dns-protocol.h b/src/dns-protocol.h
index 16fade33d98c..7f5d686bb150 100644
--- a/src/dns-protocol.h
+++ b/src/dns-protocol.h
@@ -142,3 +142,7 @@ struct dns_header {
#define ADD_RDLEN(header, pp, plen, len) \
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
+
+/* Escape character in our presentation format for names.
+ Cannot be '.' or /000 and must be !isprint() */
+#define NAME_ESCAPE 1
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 20b15c05103a..19a6428b09e8 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -102,8 +102,19 @@ int main (int argc, char **argv)
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
- daemon->keyname = safe_malloc(MAXDNAME);
- daemon->workspacename = safe_malloc(MAXDNAME);
+ /* Note that both /000 and '.' are allowed within labels. These get
+ represented in presentation format using NAME_ESCAPE as an escape
+ character when in DNSSEC mode.
+ In theory, if all the characters in a name were /000 or
+ '.' or NAME_ESCAPE then all would have to be escaped, so the
+ presentation format would be twice as long as the spec.
+
+ daemon->namebuff was previously allocated by the option-reading
+ code before we knew if we're in DNSSEC mode, so reallocate here. */
+ free(daemon->namebuff);
+ daemon->namebuff = safe_malloc(MAXDNAME * 2);
+ daemon->keyname = safe_malloc(MAXDNAME * 2);
+ daemon->workspacename = safe_malloc(MAXDNAME * 2);
}
#endif
diff --git a/src/dnssec.c b/src/dnssec.c
index 05e0983cb251..c116a7b5f6f4 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -321,10 +321,18 @@ static int verify(struct blockdata *key_data, unsigned int key_len, unsigned cha
thus generating names in canonical form.
Calling to_wire followed by from_wire is almost an identity,
except that the UC remains mapped to LC.
+
+ Note that both /000 and '.' are allowed within labels. These get
+ represented in presentation format using NAME_ESCAPE as an escape
+ character. In theory, if all the characters in a name were /000 or
+ '.' or NAME_ESCAPE then all would have to be escaped, so the
+ presentation format would be twice as long as the spec (1024).
+ The buffers are all delcared as 2049 (allowing for the trailing zero)
+ for this reason.
*/
static int to_wire(char *name)
{
- unsigned char *l, *p, term;
+ unsigned char *l, *p, *q, term;
int len;
for (l = (unsigned char*)name; *l != 0; l = p)
@@ -332,7 +340,10 @@ static int to_wire(char *name)
for (p = l; *p != '.' && *p != 0; p++)
if (*p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a';
-
+ else if (*p == NAME_ESCAPE)
+ for (q = p; *q; q++)
+ *q = *(q+1);
+
term = *p;
if ((len = p - l) != 0)
@@ -351,13 +362,23 @@ static int to_wire(char *name)
/* Note: no compression allowed in input. */
static void from_wire(char *name)
{
- unsigned char *l;
+ unsigned char *l, *p, *last;
int len;
-
+
+ for (last = (unsigned char *)name; *last != 0; last += *last+1);
+
for (l = (unsigned char *)name; *l != 0; l += len+1)
{
len = *l;
memmove(l, l+1, len);
+ for (p = l; p < l + len; p++)
+ if (*p == '.' || *p == 0 || *p == NAME_ESCAPE)
+ {
+ memmove(p+1, p, 1 + last - p);
+ len++;
+ *p++ = NAME_ESCAPE;
+ }
+
l[len] = '.';
}
@@ -645,7 +666,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, MAXDNAME - left1, &p1, &dp1)) == 0)
+ if ((len1 = get_rdata(header, plen, end1, buff1 + left1, (MAXDNAME * 2) - left1, &p1, &dp1)) == 0)
{
quit = 1;
len1 = end1 - p1;
@@ -656,7 +677,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, MAXDNAME - left2, &p2, &dp2)) == 0)
+ if ((len2 = get_rdata(header, plen, end2, buff2 + left2, (MAXDNAME *2) - left2, &p2, &dp2)) == 0)
{
quit = 1;
len2 = end2 - p2;
@@ -902,10 +923,11 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
end = p + rdlen;
- /* canonicalise rdata and calculate length of same, use name buffer as workspace */
+ /* canonicalise rdata and calculate length of same, use name buffer as workspace.
+ Note that name buffer is twice MAXDNAME long in DNSSEC mode. */
cp = p;
dp = rr_desc;
- for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg);
+ for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)) != 0; len += seg);
len += end - cp;
len = htons(len);
hash->update(ctx, 2, (unsigned char *)&len);
@@ -913,7 +935,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, MAXDNAME, &cp, &dp)))
+ while ((seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)))
hash->update(ctx, seg, (unsigned char *)name);
if (cp != end)
hash->update(ctx, end - cp, cp);
diff --git a/src/rfc1035.c b/src/rfc1035.c
index a995ab50d74a..19fecc818c06 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -128,6 +128,15 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if (isExtract)
{
unsigned char c = *p;
+#ifdef HAVE_DNSSEC
+ if (option_bool(OPT_DNSSEC_VALID))
+ {
+ if (c == 0 || c == '.' || c == NAME_ESCAPE)
+ *cp++ = NAME_ESCAPE;
+ *cp++ = c;
+ }
+ else
+#endif
if (c != 0 && c != '.')
*cp++ = c;
else
@@ -144,9 +153,14 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
cp++;
if (c1 >= 'A' && c1 <= 'Z')
c1 += 'a' - 'A';
+#ifdef HAVE_DNSSEC
+ if (option_bool(OPT_DNSSEC_VALID) && c1 == NAME_ESCAPE)
+ c1 = *cp++;
+#endif
+
if (c2 >= 'A' && c2 <= 'Z')
c2 += 'a' - 'A';
-
+
if (c1 != c2)
retvalue = 2;
}
diff --git a/src/util.c b/src/util.c
index 648bc4d4b428..0c1a48b4700a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -226,7 +226,14 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
{
unsigned char *cp = p++;
for (j = 0; *sval && (*sval != '.'); sval++, j++)
- *p++ = *sval;
+ {
+#ifdef HAVE_DNSSEC
+ if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
+ *p++ = *(++sval);
+ else
+#endif
+ *p++ = *sval;
+ }
*cp = j;
if (*sval)
sval++;
--
2.1.0

View File

@@ -1,136 +0,0 @@
From b8f16556d36924cd8dc7663cb4129d7b1f3fc2be Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 22 Apr 2015 21:14:31 +0100
Subject: [PATCH 082/113] Tweaks to previous, DNS label charset commit.
---
src/dns-protocol.h | 6 +++++-
src/dnssec.c | 9 ++++++---
src/rfc1035.c | 25 ++++++++++++++++++-------
src/util.c | 2 +-
4 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/src/dns-protocol.h b/src/dns-protocol.h
index 7f5d686bb150..4b71746f8d26 100644
--- a/src/dns-protocol.h
+++ b/src/dns-protocol.h
@@ -144,5 +144,9 @@ struct dns_header {
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
/* Escape character in our presentation format for names.
- Cannot be '.' or /000 and must be !isprint() */
+ Cannot be '.' or /000 and must be !isprint().
+ Note that escaped chars are stored as
+ <NAME_ESCAPE> <orig-char+1>
+ to ensure that the escaped form of /000 doesn't include /000
+*/
#define NAME_ESCAPE 1
diff --git a/src/dnssec.c b/src/dnssec.c
index c116a7b5f6f4..a9e12153ccf2 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -341,9 +341,11 @@ static int to_wire(char *name)
if (*p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a';
else if (*p == NAME_ESCAPE)
- for (q = p; *q; q++)
+ {
+ for (q = p; *q; q++)
*q = *(q+1);
-
+ (*p)--;
+ }
term = *p;
if ((len = p - l) != 0)
@@ -376,7 +378,8 @@ static void from_wire(char *name)
{
memmove(p+1, p, 1 + last - p);
len++;
- *p++ = NAME_ESCAPE;
+ *p++ = NAME_ESCAPE;
+ (*p)++;
}
l[len] = '.';
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 19fecc818c06..32df31ad603c 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -20,7 +20,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes)
{
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
- unsigned int j, l, hops = 0;
+ unsigned int j, l, namelen = 0, hops = 0;
int retvalue = 1;
if (isExtract)
@@ -94,9 +94,15 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
count = 256;
digs = ((count-1)>>2)+1;
- /* output is \[x<hex>/siz]. which is digs+9 chars */
- if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
+ /* output is \[x<hex>/siz]. which is digs+6/7/8 chars */
+ namelen += digs+6;
+ if (count > 9)
+ namelen++;
+ if (count > 99)
+ namelen++;
+ if (namelen+1 >= MAXDNAME)
return 0;
+
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
return 0;
@@ -119,7 +125,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
}
else
{ /* label_type = 0 -> label. */
- if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
+ namelen += l;
+ if (namelen+1 >= MAXDNAME)
return 0;
if (!CHECK_LEN(header, p, plen, l))
return 0;
@@ -132,8 +139,12 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if (option_bool(OPT_DNSSEC_VALID))
{
if (c == 0 || c == '.' || c == NAME_ESCAPE)
- *cp++ = NAME_ESCAPE;
- *cp++ = c;
+ {
+ *cp++ = NAME_ESCAPE;
+ *cp++ = c+1;
+ }
+ else
+ *cp++ = c;
}
else
#endif
@@ -155,7 +166,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
c1 += 'a' - 'A';
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && c1 == NAME_ESCAPE)
- c1 = *cp++;
+ c1 = (*cp++)-1;
#endif
if (c2 >= 'A' && c2 <= 'Z')
diff --git a/src/util.c b/src/util.c
index 0c1a48b4700a..9299703c6d30 100644
--- a/src/util.c
+++ b/src/util.c
@@ -229,7 +229,7 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
{
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
- *p++ = *(++sval);
+ *p++ = (*(++sval))-1;
else
#endif
*p++ = *sval;
--
2.1.0

View File

@@ -1,46 +0,0 @@
From a5ae1f85873829efe473075ad77806cc02792622 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 25 Apr 2015 21:46:10 +0100
Subject: [PATCH 083/113] Logs in DHCPv6 not suppressed by dhcp6-quiet.
---
CHANGELOG | 6 +++++-
src/rfc3315.c | 4 ++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 7f2b1e002e9e..af2b22cf8f73 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -103,7 +103,11 @@ version 2.73
Previously we provided correct answers to PTR queries
in such zones (including NS and SOA) but not direct
NS and SOA queries. Thanks to Johnny S. Lee for
- pointing out the problem.
+ pointing out the problem.
+
+ Fix logging of DHCPREPLY which should be suppressed
+ by quiet-dhcp6. Thanks to J. Pablo Abonia for
+ spotting the problem.
version 2.72
diff --git a/src/rfc3315.c b/src/rfc3315.c
index c45116a40a09..b4f5dd2db61f 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -1047,9 +1047,9 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
{
preferred_time = valid_time = 0;
message = _("address invalid");
- }
+ }
- if (message)
+ if (message && (message != state->hostname))
log6_packet(state, "DHCPREPLY", req_addr, message);
else
log6_quiet(state, "DHCPREPLY", req_addr, message);
--
2.1.0

View File

@@ -1,28 +0,0 @@
From 8efd731cc4ed2baa42aa69d0a9d336392e9987cb Mon Sep 17 00:00:00 2001
From: "Johnny S. Lee" <_@jsl.io>
Date: Sun, 26 Apr 2015 22:23:57 +0100
Subject: [PATCH 084/113] Make get-version work when repo is a git submodule.
---
bld/get-version | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/bld/get-version b/bld/get-version
index 7ab75db729ac..5372869c0852 100755
--- a/bld/get-version
+++ b/bld/get-version
@@ -11,8 +11,9 @@
# If there is more than one v[0-9].* tag, sort them and use the
# first. This favours, eg v2.63 over 2.63rc6.
-if which git >/dev/null 2>&1 && [ -d $1/.git ]; then
- cd $1; git describe | sed 's/^v//'
+if which git >/dev/null 2>&1 && \
+ ([ -d $1/.git ] || grep '^gitdir:' $1/.git >/dev/null 2>&1); then
+ cd $1; git describe | sed 's/^v//'
elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
# unsubstituted VERSION, but no git available.
echo UNKNOWN
--
2.1.0

View File

@@ -1,40 +0,0 @@
From e66b4dff3c562c7836d5be4c26972d665ad783f1 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 28 Apr 2015 20:45:57 +0100
Subject: [PATCH 085/113] Fix argument-order botch which broke DNSSEC for TCP
queries.
---
src/forward.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/forward.c b/src/forward.c
index 1c7da3f5655c..a8e403c4b25e 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -1996,8 +1996,9 @@ unsigned char *tcp_request(int confd, time_t now,
}
else
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
- if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
- domain = daemon->namebuff;
+
+ if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
+ domain = daemon->namebuff;
log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
@@ -2040,8 +2041,8 @@ unsigned char *tcp_request(int confd, time_t now,
#endif
m = process_reply(header, now, last_server, (unsigned int)m,
- option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, bogusanswer,
- cache_secure, ad_question, do_bit, added_pheader, check_subnet, &peer_addr);
+ option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
+ ad_question, do_bit, added_pheader, check_subnet, &peer_addr);
break;
}
--
2.1.0

View File

@@ -1,29 +0,0 @@
From 2ed162ac204f3609fe4d9f9a0430baeaa352d88f Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 28 Apr 2015 21:26:35 +0100
Subject: [PATCH 086/113] Don't remove RRSIG RR from answers to ANY queries
when the do bit is not set.
---
src/rfc1035.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 32df31ad603c..5828055caa5d 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1608,6 +1608,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
GETSHORT(qtype, p);
GETSHORT(qclass, p);
+ /* Don't filter RRSIGS from answers to ANY queries, even if do-bit
+ not set. */
+ if (qtype == T_ANY)
+ *do_bit = 1;
+
ans = 0; /* have we answered this question */
if (qtype == T_TXT || qtype == T_ANY)
--
2.1.0

View File

@@ -1,57 +0,0 @@
From 64bcff1c7c72eecda8750bc2dca8b4c5dc38a837 Mon Sep 17 00:00:00 2001
From: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
Date: Tue, 28 Apr 2015 21:55:18 +0100
Subject: [PATCH 087/113] Constify some DHCP lease management functions.
---
src/dnsmasq.h | 7 ++++---
src/lease.c | 8 ++++----
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 6fe4a4189188..824a86009439 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1304,9 +1304,10 @@ void lease_update_slaac(time_t now);
void lease_set_iaid(struct dhcp_lease *lease, int iaid);
void lease_make_duid(time_t now);
#endif
-void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
- unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
-void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain);
+void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
+ const unsigned char *clid, int hw_len, int hw_type,
+ int clid_len, time_t now, int force);
+void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain);
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now);
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
diff --git a/src/lease.c b/src/lease.c
index 545bbb7fd09c..8adb60588671 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -813,9 +813,9 @@ void lease_set_iaid(struct dhcp_lease *lease, int iaid)
}
#endif
-void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
- unsigned char *clid, int hw_len, int hw_type, int clid_len,
- time_t now, int force)
+void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
+ const unsigned char *clid, int hw_len, int hw_type,
+ int clid_len, time_t now, int force)
{
#ifdef HAVE_DHCP6
int change = force;
@@ -897,7 +897,7 @@ static void kill_name(struct dhcp_lease *lease)
lease->hostname = lease->fqdn = NULL;
}
-void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain)
+void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain)
{
struct dhcp_lease *lease_tmp;
char *new_name = NULL, *new_fqdn = NULL;
--
2.1.0

View File

@@ -1,332 +0,0 @@
From a77cec8d58231d71cbc26615f0c0f0292c09ef54 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 8 May 2015 16:25:38 +0100
Subject: [PATCH 088/113] Handle UDP packet loss when fragmentation of large
packets is broken.
---
CHANGELOG | 6 ++++++
src/config.h | 1 +
src/dnsmasq.h | 5 +++--
src/dnssec.c | 11 +++++++++--
src/forward.c | 37 +++++++++++++++++++++++++++++--------
src/network.c | 1 +
src/option.c | 18 +++++++++++-------
src/rfc1035.c | 22 ++++++----------------
8 files changed, 66 insertions(+), 35 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index af2b22cf8f73..d8fc57a418bb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -109,6 +109,12 @@ version 2.73
by quiet-dhcp6. Thanks to J. Pablo Abonia for
spotting the problem.
+ Try and handle net connections with broken fragmentation
+ that lose large UDP packets. If a server times out,
+ reduce the maximum UDP packet size field in the EDNS0
+ header to 1280 bytes. If it then answers, make that
+ change permanent.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/config.h b/src/config.h
index 8def6f200461..f75fe9db7081 100644
--- a/src/config.h
+++ b/src/config.h
@@ -19,6 +19,7 @@
#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 SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 824a86009439..ab16f79b3ec9 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -504,7 +504,7 @@ struct server {
char interface[IF_NAMESIZE+1];
struct serverfd *sfd;
char *domain; /* set if this server only handles a domain. */
- int flags, tcpfd;
+ int flags, tcpfd, edns_pktsz;
unsigned int queries, failed_queries;
#ifdef HAVE_LOOP
u32 uid;
@@ -594,6 +594,7 @@ struct hostsfile {
#define FREC_DO_QUESTION 64
#define FREC_ADDED_PHEADER 128
#define FREC_CHECK_NOSIGN 256
+#define FREC_TEST_PKTSZ 512
#ifdef HAVE_DNSSEC
#define HASH_SIZE 20 /* SHA-1 digest size */
@@ -1148,7 +1149,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
#endif
/* dnssec.c */
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr);
+size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
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 *nons);
diff --git a/src/dnssec.c b/src/dnssec.c
index a9e12153ccf2..e91d7c2cf040 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -2162,10 +2162,12 @@ int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
}
}
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
+size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class,
+ int type, union mysockaddr *addr, int edns_pktsz)
{
unsigned char *p;
char *types = querystr("dnssec-query", type);
+ size_t ret;
if (addr->sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
@@ -2194,7 +2196,12 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
PUTSHORT(type, p);
PUTSHORT(class, p);
- return add_do_bit(header, p - (unsigned char *)header, end);
+ ret = add_do_bit(header, p - (unsigned char *)header, end);
+
+ if (find_pseudoheader(header, ret, NULL, &p, NULL))
+ PUTSHORT(edns_pktsz, p);
+
+ return ret;
}
/* Go through a domain name, find "pointers" and fix them up based on how many bytes
diff --git a/src/forward.c b/src/forward.c
index a8e403c4b25e..592243fd4d35 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -253,6 +253,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
void *hash = &crc;
#endif
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
+ unsigned char *pheader;
(void)do_bit;
@@ -261,19 +262,32 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward = NULL;
else if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
{
+ /* If we didn't get an answer advertising a maximal packet in EDNS,
+ fall back to 1280, which should work everywhere on IPv6.
+ If that generates an answer, it will become the new default
+ for this server */
+ forward->flags |= FREC_TEST_PKTSZ;
+
#ifdef HAVE_DNSSEC
/* If we've already got an answer to this query, but we're awaiting keys for validation,
there's no point retrying the query, retry the key query instead...... */
if (forward->blocking_query)
{
int fd;
-
+
+ forward->flags &= ~FREC_TEST_PKTSZ;
+
while (forward->blocking_query)
forward = forward->blocking_query;
+
+ forward->flags |= FREC_TEST_PKTSZ;
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
plen = forward->stash_len;
+ if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
+ PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : forward->sentto->edns_pktsz, pheader);
+
if (forward->sentto->addr.sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
#ifdef HAVE_IPV6
@@ -417,7 +431,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
plen = new_plen;
}
#endif
-
+
while (1)
{
/* only send to servers dealing with our domain.
@@ -464,6 +478,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
#endif
}
+
+ if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
+ PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : start->edns_pktsz, pheader);
if (retry_send(sendto(fd, (char *)header, plen, 0,
&start->addr.sa,
@@ -760,7 +777,6 @@ void reply_query(int fd, int family, time_t now)
}
server = forward->sentto;
-
if ((forward->sentto->flags & SERV_TYPE) == 0)
{
if (RCODE(header) == REFUSED)
@@ -781,7 +797,12 @@ void reply_query(int fd, int family, time_t now)
if (!option_bool(OPT_ALL_SERVERS))
daemon->last_server = server;
}
-
+
+ /* We tried resending to this server with a smaller maximum size and got an answer.
+ Make that permanent. */
+ if (server && (forward->flags & FREC_TEST_PKTSZ))
+ server->edns_pktsz = SAFE_PKTSZ;
+
/* If the answer is an error, keep the forward record in place in case
we get a good reply from another server. Kill it when we've
had replies from all to avoid filling the forwarding table when
@@ -890,7 +911,7 @@ void reply_query(int fd, int family, time_t now)
{
new->flags |= FREC_DNSKEY_QUERY;
nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
- daemon->keyname, forward->class, T_DNSKEY, &server->addr);
+ daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
}
else
{
@@ -899,7 +920,7 @@ void reply_query(int fd, int family, time_t now)
else
new->flags |= FREC_DS_QUERY;
nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
- daemon->keyname, forward->class, T_DS, &server->addr);
+ daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
}
if ((hash = hash_questions(header, nn, daemon->namebuff)))
memcpy(new->hash, hash, HASH_SIZE);
@@ -1526,7 +1547,7 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
/* 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);
+ m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr, server->edns_pktsz);
*length = htons(m);
@@ -1638,7 +1659,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
another_tcp_key:
m = dnssec_generate_query(new_header, ((char *) new_header) + 65536, keyname, class,
- new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr);
+ new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
*length = htons(m);
diff --git a/src/network.c b/src/network.c
index 992f023c31de..a1d90c876fc1 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1396,6 +1396,7 @@ void add_update_server(int flags,
serv->domain = domain_str;
serv->next = next;
serv->queries = serv->failed_queries = 0;
+ serv->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_LOOP
serv->uid = rand32();
#endif
diff --git a/src/option.c b/src/option.c
index f91cfbb1aa54..c7add88de7ac 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4498,15 +4498,19 @@ void read_opts(int argc, char **argv, char *compile_opts)
{
struct server *tmp;
for (tmp = daemon->servers; tmp; tmp = tmp->next)
- if (!(tmp->flags & SERV_HAS_SOURCE))
- {
- if (tmp->source_addr.sa.sa_family == AF_INET)
- tmp->source_addr.in.sin_port = htons(daemon->query_port);
+ {
+ tmp->edns_pktsz = daemon->edns_pktsz;
+
+ if (!(tmp->flags & SERV_HAS_SOURCE))
+ {
+ if (tmp->source_addr.sa.sa_family == AF_INET)
+ tmp->source_addr.in.sin_port = htons(daemon->query_port);
#ifdef HAVE_IPV6
- else if (tmp->source_addr.sa.sa_family == AF_INET6)
- tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
+ else if (tmp->source_addr.sa.sa_family == AF_INET6)
+ tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
#endif
- }
+ }
+ }
}
if (daemon->if_addrs)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 5828055caa5d..8b1709dd3495 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -552,7 +552,7 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
return plen;
*p++ = 0; /* empty name */
PUTSHORT(T_OPT, p);
- PUTSHORT(daemon->edns_pktsz, p); /* max packet length */
+ PUTSHORT(SAFE_PKTSZ, p); /* max packet length, this will be overwritten */
PUTSHORT(0, p); /* extended RCODE and version */
PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
lenp = p;
@@ -1537,7 +1537,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
unsigned short flag;
int q, ans, anscount = 0, addncount = 0;
int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
- int is_sign;
struct crec *crecp;
int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
struct mx_srv_record *rec;
@@ -1557,28 +1556,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
forward rather than answering from the cache, which doesn't include
security information, unless we're in DNSSEC validation mode. */
- if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
+ if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
{
- unsigned short udpsz, flags;
- unsigned char *psave = pheader;
-
+ unsigned short flags;
+
have_pseudoheader = 1;
- GETSHORT(udpsz, pheader);
- pheader += 2; /* ext_rcode */
+ pheader += 4; /* udp size, ext_rcode */
GETSHORT(flags, pheader);
if ((sec_reqd = flags & 0x8000))
*do_bit = 1;/* do bit */
- *ad_reqd = 1;
-
- /* If our client is advertising a larger UDP packet size
- than we allow, trim it so that we don't get an overlarge
- response from upstream */
-
- if (!is_sign && (udpsz > daemon->edns_pktsz))
- PUTSHORT(daemon->edns_pktsz, psave);
+ *ad_reqd = 1;
dryrun = 1;
}
--
2.1.0

View File

@@ -1,331 +0,0 @@
From a77cec8d58231d71cbc26615f0c0f0292c09ef54 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 8 May 2015 16:25:38 +0100
Subject: [PATCH] Handle UDP packet loss when fragmentation of large packets
is broken.
---
CHANGELOG | 6 ++++++
src/config.h | 1 +
src/dnsmasq.h | 5 +++--
src/dnssec.c | 11 +++++++++--
src/forward.c | 37 +++++++++++++++++++++++++++++--------
src/network.c | 1 +
src/option.c | 18 +++++++++++-------
src/rfc1035.c | 22 ++++++----------------
8 files changed, 66 insertions(+), 35 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index af2b22c..d8fc57a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -109,6 +109,12 @@ version 2.73
by quiet-dhcp6. Thanks to J. Pablo Abonia for
spotting the problem.
+ Try and handle net connections with broken fragmentation
+ that lose large UDP packets. If a server times out,
+ reduce the maximum UDP packet size field in the EDNS0
+ header to 1280 bytes. If it then answers, make that
+ change permanent.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/config.h b/src/config.h
index 8def6f2..f75fe9d 100644
--- a/src/config.h
+++ b/src/config.h
@@ -19,6 +19,7 @@
#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 SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 824a860..ab16f79 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -504,7 +504,7 @@ struct server {
char interface[IF_NAMESIZE+1];
struct serverfd *sfd;
char *domain; /* set if this server only handles a domain. */
- int flags, tcpfd;
+ int flags, tcpfd, edns_pktsz;
unsigned int queries, failed_queries;
#ifdef HAVE_LOOP
u32 uid;
@@ -594,6 +594,7 @@ struct hostsfile {
#define FREC_DO_QUESTION 64
#define FREC_ADDED_PHEADER 128
#define FREC_CHECK_NOSIGN 256
+#define FREC_TEST_PKTSZ 512
#ifdef HAVE_DNSSEC
#define HASH_SIZE 20 /* SHA-1 digest size */
@@ -1148,7 +1149,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
#endif
/* dnssec.c */
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr);
+size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
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 *nons);
diff --git a/src/dnssec.c b/src/dnssec.c
index a9e1215..e91d7c2 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -2162,10 +2162,12 @@ int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
}
}
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
+size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class,
+ int type, union mysockaddr *addr, int edns_pktsz)
{
unsigned char *p;
char *types = querystr("dnssec-query", type);
+ size_t ret;
if (addr->sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
@@ -2194,7 +2196,12 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
PUTSHORT(type, p);
PUTSHORT(class, p);
- return add_do_bit(header, p - (unsigned char *)header, end);
+ ret = add_do_bit(header, p - (unsigned char *)header, end);
+
+ if (find_pseudoheader(header, ret, NULL, &p, NULL))
+ PUTSHORT(edns_pktsz, p);
+
+ return ret;
}
/* Go through a domain name, find "pointers" and fix them up based on how many bytes
diff --git a/src/forward.c b/src/forward.c
index a8e403c..592243f 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -253,6 +253,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
void *hash = &crc;
#endif
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
+ unsigned char *pheader;
(void)do_bit;
@@ -261,19 +262,32 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward = NULL;
else if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
{
+ /* If we didn't get an answer advertising a maximal packet in EDNS,
+ fall back to 1280, which should work everywhere on IPv6.
+ If that generates an answer, it will become the new default
+ for this server */
+ forward->flags |= FREC_TEST_PKTSZ;
+
#ifdef HAVE_DNSSEC
/* If we've already got an answer to this query, but we're awaiting keys for validation,
there's no point retrying the query, retry the key query instead...... */
if (forward->blocking_query)
{
int fd;
-
+
+ forward->flags &= ~FREC_TEST_PKTSZ;
+
while (forward->blocking_query)
forward = forward->blocking_query;
+
+ forward->flags |= FREC_TEST_PKTSZ;
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
plen = forward->stash_len;
+ if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
+ PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : forward->sentto->edns_pktsz, pheader);
+
if (forward->sentto->addr.sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
#ifdef HAVE_IPV6
@@ -417,7 +431,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
plen = new_plen;
}
#endif
-
+
while (1)
{
/* only send to servers dealing with our domain.
@@ -464,6 +478,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
#endif
}
+
+ if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
+ PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : start->edns_pktsz, pheader);
if (retry_send(sendto(fd, (char *)header, plen, 0,
&start->addr.sa,
@@ -760,7 +777,6 @@ void reply_query(int fd, int family, time_t now)
}
server = forward->sentto;
-
if ((forward->sentto->flags & SERV_TYPE) == 0)
{
if (RCODE(header) == REFUSED)
@@ -781,7 +797,12 @@ void reply_query(int fd, int family, time_t now)
if (!option_bool(OPT_ALL_SERVERS))
daemon->last_server = server;
}
-
+
+ /* We tried resending to this server with a smaller maximum size and got an answer.
+ Make that permanent. */
+ if (server && (forward->flags & FREC_TEST_PKTSZ))
+ server->edns_pktsz = SAFE_PKTSZ;
+
/* If the answer is an error, keep the forward record in place in case
we get a good reply from another server. Kill it when we've
had replies from all to avoid filling the forwarding table when
@@ -890,7 +911,7 @@ void reply_query(int fd, int family, time_t now)
{
new->flags |= FREC_DNSKEY_QUERY;
nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
- daemon->keyname, forward->class, T_DNSKEY, &server->addr);
+ daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
}
else
{
@@ -899,7 +920,7 @@ void reply_query(int fd, int family, time_t now)
else
new->flags |= FREC_DS_QUERY;
nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
- daemon->keyname, forward->class, T_DS, &server->addr);
+ daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
}
if ((hash = hash_questions(header, nn, daemon->namebuff)))
memcpy(new->hash, hash, HASH_SIZE);
@@ -1526,7 +1547,7 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
/* 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);
+ m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr, server->edns_pktsz);
*length = htons(m);
@@ -1638,7 +1659,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
another_tcp_key:
m = dnssec_generate_query(new_header, ((char *) new_header) + 65536, keyname, class,
- new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr);
+ new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
*length = htons(m);
diff --git a/src/network.c b/src/network.c
index 992f023..a1d90c8 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1396,6 +1396,7 @@ void add_update_server(int flags,
serv->domain = domain_str;
serv->next = next;
serv->queries = serv->failed_queries = 0;
+ serv->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_LOOP
serv->uid = rand32();
#endif
diff --git a/src/option.c b/src/option.c
index f91cfbb..c7add88 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4498,15 +4498,19 @@ void read_opts(int argc, char **argv, char *compile_opts)
{
struct server *tmp;
for (tmp = daemon->servers; tmp; tmp = tmp->next)
- if (!(tmp->flags & SERV_HAS_SOURCE))
- {
- if (tmp->source_addr.sa.sa_family == AF_INET)
- tmp->source_addr.in.sin_port = htons(daemon->query_port);
+ {
+ tmp->edns_pktsz = daemon->edns_pktsz;
+
+ if (!(tmp->flags & SERV_HAS_SOURCE))
+ {
+ if (tmp->source_addr.sa.sa_family == AF_INET)
+ tmp->source_addr.in.sin_port = htons(daemon->query_port);
#ifdef HAVE_IPV6
- else if (tmp->source_addr.sa.sa_family == AF_INET6)
- tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
+ else if (tmp->source_addr.sa.sa_family == AF_INET6)
+ tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
#endif
- }
+ }
+ }
}
if (daemon->if_addrs)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 5828055..8b1709d 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -552,7 +552,7 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
return plen;
*p++ = 0; /* empty name */
PUTSHORT(T_OPT, p);
- PUTSHORT(daemon->edns_pktsz, p); /* max packet length */
+ PUTSHORT(SAFE_PKTSZ, p); /* max packet length, this will be overwritten */
PUTSHORT(0, p); /* extended RCODE and version */
PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
lenp = p;
@@ -1537,7 +1537,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
unsigned short flag;
int q, ans, anscount = 0, addncount = 0;
int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
- int is_sign;
struct crec *crecp;
int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
struct mx_srv_record *rec;
@@ -1557,28 +1556,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
forward rather than answering from the cache, which doesn't include
security information, unless we're in DNSSEC validation mode. */
- if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
+ if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
{
- unsigned short udpsz, flags;
- unsigned char *psave = pheader;
-
+ unsigned short flags;
+
have_pseudoheader = 1;
- GETSHORT(udpsz, pheader);
- pheader += 2; /* ext_rcode */
+ pheader += 4; /* udp size, ext_rcode */
GETSHORT(flags, pheader);
if ((sec_reqd = flags & 0x8000))
*do_bit = 1;/* do bit */
- *ad_reqd = 1;
-
- /* If our client is advertising a larger UDP packet size
- than we allow, trim it so that we don't get an overlarge
- response from upstream */
-
- if (!is_sign && (udpsz > daemon->edns_pktsz))
- PUTSHORT(daemon->edns_pktsz, psave);
+ *ad_reqd = 1;
dryrun = 1;
}
--
1.7.10.4

View File

@@ -1,58 +0,0 @@
From b059c96dc69dfe3055c5b32b078a05c53b11ebb3 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 8 May 2015 20:25:51 +0100
Subject: [PATCH] Check IPv4-mapped IPv6 addresses with --stop-rebind.
---
CHANGELOG | 3 +++
src/rfc1035.c | 21 +++++++++++++++++----
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index d8fc57a..94a521f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -115,6 +115,9 @@ version 2.73
header to 1280 bytes. If it then answers, make that
change permanent.
+ Check IPv4-mapped IPv6 addresses when --stop-rebind
+ is active. Thanks to Jordan Milne for spotting this.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 8b1709d..5e3f566 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1117,10 +1117,23 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
memcpy(&addr, p1, addrlen);
/* check for returned address in private space */
- if (check_rebind &&
- (flags & F_IPV4) &&
- private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
- return 1;
+ if (check_rebind)
+ {
+ if ((flags & F_IPV4) &&
+ private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
+ return 1;
+
+#ifdef HAVE_IPV6
+ if ((flags & F_IPV6) &&
+ IN6_IS_ADDR_V4MAPPED(&addr.addr.addr6))
+ {
+ struct in_addr v4;
+ v4.s_addr = ((const uint32_t *) (&addr.addr.addr6))[3];
+ if (private_net(v4, !option_bool(OPT_LOCAL_REBIND)))
+ return 1;
+ }
+#endif
+ }
#ifdef HAVE_IPSET
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
--
1.7.10.4

View File

@@ -1,59 +0,0 @@
From b059c96dc69dfe3055c5b32b078a05c53b11ebb3 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 8 May 2015 20:25:51 +0100
Subject: [PATCH 089/113] Check IPv4-mapped IPv6 addresses with --stop-rebind.
---
CHANGELOG | 3 +++
src/rfc1035.c | 21 +++++++++++++++++----
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index d8fc57a418bb..94a521f996e2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -115,6 +115,9 @@ version 2.73
header to 1280 bytes. If it then answers, make that
change permanent.
+ Check IPv4-mapped IPv6 addresses when --stop-rebind
+ is active. Thanks to Jordan Milne for spotting this.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 8b1709dd3495..5e3f566fdbc5 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1117,10 +1117,23 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
memcpy(&addr, p1, addrlen);
/* check for returned address in private space */
- if (check_rebind &&
- (flags & F_IPV4) &&
- private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
- return 1;
+ if (check_rebind)
+ {
+ if ((flags & F_IPV4) &&
+ private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
+ return 1;
+
+#ifdef HAVE_IPV6
+ if ((flags & F_IPV6) &&
+ IN6_IS_ADDR_V4MAPPED(&addr.addr.addr6))
+ {
+ struct in_addr v4;
+ v4.s_addr = ((const uint32_t *) (&addr.addr.addr6))[3];
+ if (private_net(v4, !option_bool(OPT_LOCAL_REBIND)))
+ return 1;
+ }
+#endif
+ }
#ifdef HAVE_IPSET
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
--
2.1.0

View File

@@ -1,28 +0,0 @@
From 86fa1046920dedc8134136a6244ca96e8a37e9d8 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 10 May 2015 13:50:59 +0100
Subject: [PATCH 090/113] Tweak EDNS timeout code.
---
src/forward.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/forward.c b/src/forward.c
index 592243fd4d35..74e5ab66c423 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -799,8 +799,10 @@ void reply_query(int fd, int family, time_t now)
}
/* We tried resending to this server with a smaller maximum size and got an answer.
- Make that permanent. */
- if (server && (forward->flags & FREC_TEST_PKTSZ))
+ Make that permanent. To avoid reduxing the packet size for an single dropped packet,
+ only do this when we get a truncated answer, or one larger than the safe size. */
+ if (server && (forward->flags & FREC_TEST_PKTSZ) &&
+ ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
server->edns_pktsz = SAFE_PKTSZ;
/* If the answer is an error, keep the forward record in place in case
--
2.1.0

View File

@@ -1,27 +0,0 @@
From 585840b03365372679907f175b07a01c9d621ae0 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 13 May 2015 12:35:57 +0100
Subject: [PATCH] Pointer to mail-archive mailing list mirror in doc.html.
---
doc.html | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/doc.html b/doc.html
index 92c9d0d..54f59bb 100644
--- a/doc.html
+++ b/doc.html
@@ -74,7 +74,9 @@ for details.
There is a dnsmasq mailing list at <A
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
-first location for queries, bugreports, suggestions etc.
+first location for queries, bugreports, suggestions etc. The list is mirrored, with a
+search facility, at <A HREF="https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/">
+https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/</A>.
You can contact me at <A
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
--
1.7.10.4

View File

@@ -1,28 +0,0 @@
From 585840b03365372679907f175b07a01c9d621ae0 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 13 May 2015 12:35:57 +0100
Subject: [PATCH 091/113] Pointer to mail-archive mailing list mirror in
doc.html.
---
doc.html | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/doc.html b/doc.html
index 92c9d0d6f34c..54f59bbbd4d0 100644
--- a/doc.html
+++ b/doc.html
@@ -74,7 +74,9 @@ for details.
There is a dnsmasq mailing list at <A
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
-first location for queries, bugreports, suggestions etc.
+first location for queries, bugreports, suggestions etc. The list is mirrored, with a
+search facility, at <A HREF="https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/">
+https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/</A>.
You can contact me at <A
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
--
2.1.0

View File

@@ -1,199 +0,0 @@
From ca85a28241ef87919d68d52c843b6964b7070e11 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 13 May 2015 22:33:04 +0100
Subject: [PATCH 092/113] Allow T1 and T2 DHCPv4 options to be set.
---
CHANGELOG | 3 +++
dnsmasq.conf.example | 8 ++++++
src/dhcp-common.c | 4 +--
src/rfc2131.c | 71 ++++++++++++++++++++++++++++++++++++----------------
4 files changed, 63 insertions(+), 23 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 94a521f996e2..ef39a415788b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -118,6 +118,9 @@ version 2.73
Check IPv4-mapped IPv6 addresses when --stop-rebind
is active. Thanks to Jordan Milne for spotting this.
+ Allow DHCPv4 options T1 and T2 to be set using --dhcp-option.
+ Thanks to Kevin Benton for patches and work on this.
+
version 2.72
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example
index 67be99acb028..1ae11dfb5358 100644
--- a/dnsmasq.conf.example
+++ b/dnsmasq.conf.example
@@ -345,6 +345,14 @@
# Ask client to poll for option changes every six hours. (RFC4242)
#dhcp-option=option6:information-refresh-time,6h
+# Set option 58 client renewal time (T1). Defaults to half of the
+# lease time if not specified. (RFC2132)
+#dhcp-option=option:T1:1m
+
+# Set option 59 rebinding time (T2). Defaults to 7/8 of the
+# lease time if not specified. (RFC2132)
+#dhcp-option=option:T2:2m
+
# Set the NTP time server address to be the same machine as
# is running dnsmasq
#dhcp-option=42,0.0.0.0
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index ce115202a646..bc48f41a14d7 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -545,8 +545,8 @@ static const struct opttab_t {
{ "parameter-request", 55, OT_INTERNAL },
{ "message", 56, OT_INTERNAL },
{ "max-message-size", 57, OT_INTERNAL },
- { "T1", 58, OT_INTERNAL | OT_TIME},
- { "T2", 59, OT_INTERNAL | OT_TIME},
+ { "T1", 58, OT_TIME},
+ { "T2", 59, OT_TIME},
{ "vendor-class", 60, 0 },
{ "client-id", 61, OT_INTERNAL },
{ "nis+-domain", 64, OT_NAME },
diff --git a/src/rfc2131.c b/src/rfc2131.c
index 55526443dc84..a10e499ef768 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -52,7 +52,9 @@ static void do_options(struct dhcp_context *context,
int null_term, int pxearch,
unsigned char *uuid,
int vendor_class_len,
- time_t now);
+ time_t now,
+ unsigned int lease_time,
+ unsigned short fuzz);
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
@@ -610,7 +612,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clear_packet(mess, end);
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
- netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
+ netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0);
}
}
@@ -1042,13 +1044,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
- if (time != 0xffffffff)
- {
- option_put(mess, end, OPTION_T1, 4, (time/2));
- option_put(mess, end, OPTION_T2, 4, (time*7)/8);
- }
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
- netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
+ netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1367,15 +1364,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
- if (time != 0xffffffff)
- {
- while (fuzz > (time/16))
- fuzz = fuzz/2;
- option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
- option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
- }
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
- netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
+ netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
}
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1440,7 +1430,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
- netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
+ netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0);
*is_inform = 1; /* handle reply differently */
return dhcp_packet_size(mess, agent_id, real_end);
@@ -2137,7 +2127,9 @@ static void do_options(struct dhcp_context *context,
int null_term, int pxe_arch,
unsigned char *uuid,
int vendor_class_len,
- time_t now)
+ time_t now,
+ unsigned int lease_time,
+ unsigned short fuzz)
{
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
struct dhcp_boot *boot;
@@ -2261,7 +2253,42 @@ static void do_options(struct dhcp_context *context,
/* rfc3011 says this doesn't need to be in the requested options list. */
if (subnet_addr.s_addr)
option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
-
+
+ if (lease_time != 0xffffffff)
+ {
+ unsigned int t1val = lease_time/2;
+ unsigned int t2val = (lease_time*7)/8;
+ unsigned int hval;
+
+ /* If set by user, sanity check, so not longer than lease. */
+ if ((opt = option_find2(OPTION_T1)))
+ {
+ hval = ntohl(*((unsigned int *)opt->val));
+ if (hval < lease_time && hval > 2)
+ t1val = hval;
+ }
+
+ if ((opt = option_find2(OPTION_T2)))
+ {
+ hval = ntohl(*((unsigned int *)opt->val));
+ if (hval < lease_time && hval > 2)
+ t2val = hval;
+ }
+
+ while (fuzz > (t1val/8))
+ fuzz = fuzz/2;
+
+ t1val -= fuzz;
+ t2val -= fuzz;
+
+ /* ensure T1 is still < T2 */
+ if (t2val <= t1val)
+ t1val = t2val - 1;
+
+ option_put(mess, end, OPTION_T1, 4, t1val);
+ option_put(mess, end, OPTION_T2, 4, t2val);
+ }
+
/* replies to DHCPINFORM may not have a valid context */
if (context)
{
@@ -2356,12 +2383,14 @@ static void do_options(struct dhcp_context *context,
if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
continue;
- /* prohibit some used-internally options */
+ /* prohibit some used-internally options. T1 and T2 already handled. */
if (optno == OPTION_CLIENT_FQDN ||
optno == OPTION_MAXMESSAGE ||
optno == OPTION_OVERLOAD ||
optno == OPTION_PAD ||
- optno == OPTION_END)
+ optno == OPTION_END ||
+ optno == OPTION_T1 ||
+ optno == OPTION_T2)
continue;
if (optno == OPTION_SNAME && done_server)
--
2.1.0

View File

@@ -1,37 +0,0 @@
From 7c0f2543a7e761d1ec82738374556beeb8a35bef Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 14 May 2015 21:16:18 +0100
Subject: [PATCH 093/113] Tweak last commit.
---
src/rfc2131.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/rfc2131.c b/src/rfc2131.c
index a10e499ef768..b95f9beadf59 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -2275,16 +2275,16 @@ static void do_options(struct dhcp_context *context,
t2val = hval;
}
+ /* ensure T1 is still < T2 */
+ if (t2val <= t1val)
+ t1val = t2val - 1;
+
while (fuzz > (t1val/8))
fuzz = fuzz/2;
t1val -= fuzz;
t2val -= fuzz;
- /* ensure T1 is still < T2 */
- if (t2val <= t1val)
- t1val = t2val - 1;
-
option_put(mess, end, OPTION_T1, 4, t1val);
option_put(mess, end, OPTION_T2, 4, t2val);
}
--
2.1.0

View File

@@ -1,29 +0,0 @@
From 62018e1f720fa11e83879111a4b1b3753b5c25bb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 14 May 2015 21:30:00 +0100
Subject: [PATCH] Use correct DHCP context for PXE-proxy server-id.
---
src/rfc2131.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/rfc2131.c b/src/rfc2131.c
index b95f9be..70d1e59 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -888,10 +888,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
- option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
+ option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
pxe_misc(mess, end, uuid);
prune_vendor_opts(tagif_netid);
- do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
+ do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
log_tags(tagif_netid, ntohl(mess->xid));
--
1.7.10.4

View File

@@ -1,49 +0,0 @@
From 5d07d77e75e0f02bc0a8f6029ffbc8b371fa804e Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 15 May 2015 18:13:06 +0100
Subject: [PATCH] Fix buffer overflow introduced in 2.73rc6.
Fix off-by-one in code which checks for over-long domain names
in received DNS packets. This enables buffer overflow attacks
which can certainly crash dnsmasq and may allow for arbitrary
code execution. The problem was introduced in commit b8f16556d,
release 2.73rc6, so has not escaped into any stable release.
Note that the off-by-one was in the label length determination,
so the buffer can be overflowed by as many bytes as there are
labels in the name - ie, many.
Thanks to Ron Bowes, who used lcmatuf's afl-fuzz tool to find
the problem.
---
src/rfc1035.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 5e3f566..a95241f 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -94,8 +94,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
count = 256;
digs = ((count-1)>>2)+1;
- /* output is \[x<hex>/siz]. which is digs+6/7/8 chars */
- namelen += digs+6;
+ /* output is \[x<hex>/siz]. which is digs+7/8/9 chars */
+ namelen += digs+7;
if (count > 9)
namelen++;
if (count > 99)
@@ -125,8 +125,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
}
else
{ /* label_type = 0 -> label. */
- namelen += l;
- if (namelen+1 >= MAXDNAME)
+ namelen += l + 1; /* include period */
+ if (namelen >= MAXDNAME)
return 0;
if (!CHECK_LEN(header, p, plen, l))
return 0;
--
1.7.10.4

View File

@@ -1,29 +0,0 @@
From 62018e1f720fa11e83879111a4b1b3753b5c25bb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 14 May 2015 21:30:00 +0100
Subject: [PATCH 094/113] Use correct DHCP context for PXE-proxy server-id.
---
src/rfc2131.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/rfc2131.c b/src/rfc2131.c
index b95f9beadf59..70d1e59530ad 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -888,10 +888,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
- option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
+ option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
pxe_misc(mess, end, uuid);
prune_vendor_opts(tagif_netid);
- do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
+ do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
log_tags(tagif_netid, ntohl(mess->xid));
--
2.1.0

View File

@@ -1,49 +0,0 @@
From 5d07d77e75e0f02bc0a8f6029ffbc8b371fa804e Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 15 May 2015 18:13:06 +0100
Subject: [PATCH 095/113] Fix buffer overflow introduced in 2.73rc6.
Fix off-by-one in code which checks for over-long domain names
in received DNS packets. This enables buffer overflow attacks
which can certainly crash dnsmasq and may allow for arbitrary
code execution. The problem was introduced in commit b8f16556d,
release 2.73rc6, so has not escaped into any stable release.
Note that the off-by-one was in the label length determination,
so the buffer can be overflowed by as many bytes as there are
labels in the name - ie, many.
Thanks to Ron Bowes, who used lcmatuf's afl-fuzz tool to find
the problem.
---
src/rfc1035.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 5e3f566fdbc5..a95241f83523 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -94,8 +94,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
count = 256;
digs = ((count-1)>>2)+1;
- /* output is \[x<hex>/siz]. which is digs+6/7/8 chars */
- namelen += digs+6;
+ /* output is \[x<hex>/siz]. which is digs+7/8/9 chars */
+ namelen += digs+7;
if (count > 9)
namelen++;
if (count > 99)
@@ -125,8 +125,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
}
else
{ /* label_type = 0 -> label. */
- namelen += l;
- if (namelen+1 >= MAXDNAME)
+ namelen += l + 1; /* include period */
+ if (namelen >= MAXDNAME)
return 0;
if (!CHECK_LEN(header, p, plen, l))
return 0;
--
2.1.0

Some files were not shown because too many files have changed in this diff Show More