mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-19 23:43:00 +02:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user