dnsmasq: backport latest patches

Backport upstream patches pre 2.81rc for testing purposes.

Let's see what falls out!

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
This commit is contained in:
Kevin Darbyshire-Bryant 2019-03-09 08:40:57 +00:00
parent 7d684b7673
commit e9eec39aac
52 changed files with 1988 additions and 32 deletions

View File

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=dnsmasq
PKG_UPSTREAM_VERSION:=2.80
PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION)))
PKG_RELEASE:=13
PKG_RELEASE:=14
PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq

View File

@ -1,7 +1,7 @@
From a799ca0c6314ad73a97bc6c89382d2712a9c0b0e Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 18 Oct 2018 19:35:29 +0100
Subject: [PATCH 01/32] Impove cache behaviour for TCP connections.
Subject: [PATCH 01/57] Impove cache behaviour for TCP connections.
For ease of implementaion, dnsmasq has always forked a new process to
handle each incoming TCP connection. A side-effect of this is that any

View File

@ -1,7 +1,7 @@
From a220545c4277cba534be5ef4638b5076fc7d2cf4 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 22 Oct 2018 18:21:48 +0100
Subject: [PATCH 02/32] Ensure that AD bit is reset on answers from
Subject: [PATCH 02/57] Ensure that AD bit is reset on answers from
--address=/<domain>/<address>.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>

View File

@ -1,7 +1,7 @@
From ee8750451b49d27b180517a4e35b636be0fae575 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 23 Oct 2018 22:10:17 +0100
Subject: [PATCH 03/32] Remove ability to compile without IPv6 support.
Subject: [PATCH 03/57] Remove ability to compile without IPv6 support.
This was the source of a large number of #ifdefs, originally
included for use with old embedded libc versions. I'm

View File

@ -1,7 +1,7 @@
From cf5984367bc6a949e3803a576512c5a7bc48ebab Mon Sep 17 00:00:00 2001
From: Vladislav Grishenko <themiron@mail.ru>
Date: Thu, 18 Oct 2018 04:55:21 +0500
Subject: [PATCH 04/32] Don't forward *.bind/*.server queries upstream
Subject: [PATCH 04/57] Don't forward *.bind/*.server queries upstream
Chaos .bind and .server (RFC4892) zones are local, therefore
don't forward queries upstream to avoid mixing with supported

View File

@ -1,7 +1,7 @@
From cbb5b17ad8e03e08ade62376a4f6a2066e55960d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 23 Oct 2018 23:45:57 +0100
Subject: [PATCH 05/32] Fix logging in cf5984367bc6a949e3803a576512c5a7bc48ebab
Subject: [PATCH 05/57] Fix logging in cf5984367bc6a949e3803a576512c5a7bc48ebab
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---

View File

@ -1,7 +1,7 @@
From 6f7812d97bc8f87004c0a5069c6c94c64af78106 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 23 Oct 2018 23:54:44 +0100
Subject: [PATCH 06/32] Fix spurious AD flags in some DNS replies from local
Subject: [PATCH 06/57] Fix spurious AD flags in some DNS replies from local
config.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>

View File

@ -1,7 +1,7 @@
From 24b87607c1353e94689e8a2190571ab3f3b36f31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
Date: Wed, 24 Oct 2018 22:30:18 +0100
Subject: [PATCH 07/32] Do not rely on dead code elimination, use array
Subject: [PATCH 07/57] Do not rely on dead code elimination, use array
instead. Make options bits derived from size and count. Use size of option
bits and last supported bit in computation. No new change would be required
when new options are added. Just change OPT_LAST constant.

View File

@ -1,7 +1,7 @@
From 3a5a84cdd1488bad118eeac72d09a60299bca744 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 31 Oct 2018 21:30:13 +0000
Subject: [PATCH 08/32] Fix Makefile lines generating UBUS linker config.
Subject: [PATCH 08/57] Fix Makefile lines generating UBUS linker config.
If arg2 of pkg-wrapper is "--copy", then arg1 is NOT the name of
the package manager (--copy doesn't invoke it) it's a secondary

View File

@ -1,7 +1,7 @@
From 122392e0b352507cabb9e982208d35d2e56902e0 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 31 Oct 2018 22:24:02 +0000
Subject: [PATCH 09/32] Revert 68f6312d4bae30b78daafcd6f51dc441b8685b1e
Subject: [PATCH 09/57] Revert 68f6312d4bae30b78daafcd6f51dc441b8685b1e
The above is intended to increase robustness, but actually does the
opposite. The problem is that by ignoring SERVFAIL messages and hoping

View File

@ -1,7 +1,7 @@
From 48d12f14c9c0fc8cf943b52774c3892517dd72d4 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 2 Nov 2018 21:55:04 +0000
Subject: [PATCH 10/32] Remove the NO_FORK compile-time option, and support for
Subject: [PATCH 10/57] Remove the NO_FORK compile-time option, and support for
uclinux.
In an era where everything has an MMU, this looks like

View File

@ -1,7 +1,7 @@
From 59e470381f84f2fdf0640c7bc67827f3f0c64784 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
Date: Fri, 2 Nov 2018 22:39:39 +0000
Subject: [PATCH 11/32] Free config file values on parsing errors.
Subject: [PATCH 11/57] Free config file values on parsing errors.
This time I have a little bit more controversal patches. But I think
still useful. They fixes memory leaks that might occur in some cases.

View File

@ -1,7 +1,7 @@
From 07e25da5bf26d46aad4f1d2eb19b260789182004 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 16 Dec 2018 18:21:58 +0000
Subject: [PATCH 13/32] Treat DS and DNSKEY queries being forwarded the same as
Subject: [PATCH 13/57] Treat DS and DNSKEY queries being forwarded the same as
those locally originated.
The queries will not be forwarded to a server for a domain, unless

View File

@ -1,7 +1,7 @@
From 137e9f878fafb38369eab7d9dfe84e4228ff5f89 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
Date: Sun, 16 Dec 2018 21:25:29 +0000
Subject: [PATCH 14/32] Fix option parsing errors introduced in
Subject: [PATCH 14/57] Fix option parsing errors introduced in
59e470381f84f2fdf0640c7bc67827f3f0c64784
Thanks to Kevin Darbyshire-Bryant for spotting this.

View File

@ -1,7 +1,7 @@
From 3becf468bad699bfdcb2d18d553bc72d4c79e23c Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
Date: Wed, 12 Dec 2018 12:00:19 +0000
Subject: [PATCH 15/32] fix ipv6 ipset bug in master
Subject: [PATCH 15/57] fix ipv6 ipset bug in master
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

View File

@ -1,7 +1,7 @@
From b683cf37f9f3dd3dc5d95d621ee75850d559b2e4 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
Date: Mon, 10 Dec 2018 10:34:35 +0000
Subject: [PATCH 16/32] build failure on master with NO_DHCPv6 and fix....
Subject: [PATCH 16/57] build failure on master with NO_DHCPv6 and fix....
Hi Simon,

View File

@ -1,7 +1,7 @@
From e7bfd556c079c8b5e7425aed44abc35925b24043 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 31 Dec 2018 20:51:15 +0000
Subject: [PATCH 17/32] Alter DHCP address selection after DECLINE in
Subject: [PATCH 17/57] Alter DHCP address selection after DECLINE in
consec-addr mode. Avoid offering the same address after a recieving a DECLINE
message to stop an infinite protocol loop. This has long been done in default
address allocation mode: this adds similar behaviour when allocaing addresses

View File

@ -1,7 +1,7 @@
From bde46476ee06c96e821653dfdb8fa11fe7326998 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 31 Dec 2018 23:28:24 +0000
Subject: [PATCH 18/32] Tidy all_addr union, merge log and rcode fields.
Subject: [PATCH 18/57] Tidy all_addr union, merge log and rcode fields.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---

View File

@ -1,7 +1,7 @@
From 65a01b71bb433c9466e4c78a73a8d8ed218ed4e8 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 31 Dec 2018 23:56:33 +0000
Subject: [PATCH 19/32] Tidy address-union handling: move class into explicit
Subject: [PATCH 19/57] Tidy address-union handling: move class into explicit
argument.
This moves the class argument to cache-insert into an argument,

View File

@ -1,7 +1,7 @@
From ab194ed7ca433e4e2e8b2ec338bfa4e6aa886a4b Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 1 Jan 2019 01:35:30 +0000
Subject: [PATCH 20/32] Futher address union tidying.
Subject: [PATCH 20/57] Futher address union tidying.
Pass DNSKEY and DS data into cache_insert via the address argument,
now these data types are included in struct all_addr.

View File

@ -1,7 +1,7 @@
From cc921df9ceac79acf9f1c477d015a3d88275422d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 2 Jan 2019 22:48:59 +0000
Subject: [PATCH 21/32] Remove nested struct/union in cache records and
Subject: [PATCH 21/57] Remove nested struct/union in cache records and
all_addr.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>

View File

@ -1,7 +1,7 @@
From 2c594732eb7391e7cfa817598e33e61cab71131f Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 3 Jan 2019 13:42:03 +0000
Subject: [PATCH 22/32] File logic bug in cache-marshalling code. Introduced a
Subject: [PATCH 22/57] File logic bug in cache-marshalling code. Introduced a
couple of commits back.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>

View File

@ -1,7 +1,7 @@
From 2daca52b80afdc92e7c976629a2bf8182335a626 Mon Sep 17 00:00:00 2001
From: Christian Weiske <cweiske@cweiske.de>
Date: Thu, 3 Jan 2019 20:10:14 +0000
Subject: [PATCH 23/32] Fix typo in ra-param man page section.
Subject: [PATCH 23/57] Fix typo in ra-param man page section.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---

View File

@ -1,7 +1,7 @@
From 5b99eae59d59a8e34a7e512059b98bbd803312f2 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 6 Jan 2019 23:09:50 +0000
Subject: [PATCH 24/32] Cache SRV records.
Subject: [PATCH 24/57] Cache SRV records.
Inpsired by a patch from Jeremy Allison, but completely re-rolled
by srk. All bugs are mine.

View File

@ -1,7 +1,7 @@
From a90f09db4cc635941a32b973b57e58c662569625 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 9 Jan 2019 15:08:16 +0000
Subject: [PATCH 25/32] Fix crash freeing negative SRV cache entries.
Subject: [PATCH 25/57] Fix crash freeing negative SRV cache entries.
Thanks to Daniel for finding this one.

View File

@ -1,7 +1,7 @@
From 2896e2485e44c04e73a0b7c9f7cbc9c8515d0800 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 9 Jan 2019 15:12:34 +0000
Subject: [PATCH 26/32] Check for not(DS or DNSKEY) in
Subject: [PATCH 26/57] Check for not(DS or DNSKEY) in
is_outdated_cname_pointer()
Previous check was _for_ IPV4, IPv6 CNAME, and I missed adding SRV.

View File

@ -1,7 +1,7 @@
From 9c0d445ef4abffa2b9342ad65e85ef425c1f83bb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 9 Jan 2019 17:57:56 +0000
Subject: [PATCH 27/32] Fix e7bfd556c079c8b5e7425aed44abc35925b24043 to
Subject: [PATCH 27/57] Fix e7bfd556c079c8b5e7425aed44abc35925b24043 to
actually work.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>

View File

@ -1,7 +1,7 @@
From 4bf62f616b82fad7a7f91195b0204dd64d79a35c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 10 Jan 2019 21:54:22 +0000
Subject: [PATCH 28/32] Tidy cache_blockdata_free()
Subject: [PATCH 28/57] Tidy cache_blockdata_free()
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---

View File

@ -1,7 +1,7 @@
From f8c77edbdffb8ada7753ea9fa104f0f6da70cfe3 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 10 Jan 2019 21:58:18 +0000
Subject: [PATCH 29/32] Fix removal of DHCP_CLIENT_MAC options from DHCPv6
Subject: [PATCH 29/57] Fix removal of DHCP_CLIENT_MAC options from DHCPv6
relay replies.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>

View File

@ -1,7 +1,7 @@
From 18eac67c0a15b673c8d27002c248651b308093e4 Mon Sep 17 00:00:00 2001
From: Steven Siloti <ssiloti@gmail.com>
Date: Sun, 13 Jan 2019 22:56:36 +0000
Subject: [PATCH 30/32] Fix entries in /etc/hosts disabling static leases.
Subject: [PATCH 30/57] Fix entries in /etc/hosts disabling static leases.
It is possible for a config entry to have one address family specified by a
dhcp-host directive and the other added from /etc/hosts. This is especially

View File

@ -1,7 +1,7 @@
From d2d49907435433001ab00698a3e9ca2a7b5b3236 Mon Sep 17 00:00:00 2001
From: Steven Siloti <ssiloti@gmail.com>
Date: Thu, 17 Jan 2019 22:52:13 +0000
Subject: [PATCH 31/32] Fix missing braces in
Subject: [PATCH 31/57] Fix missing braces in
8eac67c0a15b673c8d27002c248651b308093e4
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>

View File

@ -1,7 +1,7 @@
From 28cfe36e1eee9d2c234e0256ad459956b415a3bb Mon Sep 17 00:00:00 2001
From: Brian Haley <haleyb.dev@gmail.com>
Date: Thu, 17 Jan 2019 23:21:23 +0000
Subject: [PATCH 32/32] Change read_leases() to skip invalid entries.
Subject: [PATCH 32/57] Change read_leases() to skip invalid entries.
There's no reason to stop reading the existing lease file
when dnsmasq is started and an invalid entry is found, it

View File

@ -0,0 +1,86 @@
From 4219adeeef8a3d5447af4c9bd1e4e7c05b3112fd Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 27 Feb 2019 20:30:21 +0000
Subject: [PATCH 33/57] Fix line counting when reading /etc/hosts.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
CHANGELOG | 4 ++++
src/cache.c | 16 ++++++++--------
2 files changed, 12 insertions(+), 8 deletions(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,6 +17,10 @@ version 2.81
combinatorial explosion of compile-time options. Thanks to
Kevin Darbyshire-Bryant for the patch.
+ Fix line-counting when reading /etc/hosts and friends; for
+ correct error messages. Thanks to Christian Rosentreter
+ for reporting this.
+
version 2.80
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
--- a/src/cache.c
+++ b/src/cache.c
@@ -1062,7 +1062,7 @@ static int eatspace(FILE *f)
}
if (c == '\n')
- nl = 1;
+ nl++;
}
}
@@ -1073,7 +1073,7 @@ static int gettok(FILE *f, char *token)
while (1)
{
if ((c = getc(f)) == EOF)
- return (count == 0) ? EOF : 1;
+ return (count == 0) ? -1 : 1;
if (isspace(c) || c == '#')
{
@@ -1093,7 +1093,7 @@ int read_hostsfile(char *filename, unsig
{
FILE *f = fopen(filename, "r");
char *token = daemon->namebuff, *domain_suffix = NULL;
- int addr_count = 0, name_count = cache_size, lineno = 0;
+ int addr_count = 0, name_count = cache_size, lineno = 1;
unsigned int flags = 0;
union all_addr addr;
int atnl, addrlen = 0;
@@ -1104,12 +1104,10 @@ int read_hostsfile(char *filename, unsig
return cache_size;
}
- eatspace(f);
+ lineno += eatspace(f);
- while ((atnl = gettok(f, token)) != EOF)
+ while ((atnl = gettok(f, token)) != -1)
{
- lineno++;
-
if (inet_pton(AF_INET, token, &addr) > 0)
{
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
@@ -1145,7 +1143,7 @@ int read_hostsfile(char *filename, unsig
int fqdn, nomem;
char *canon;
- if ((atnl = gettok(f, token)) == EOF)
+ if ((atnl = gettok(f, token)) == -1)
break;
fqdn = !!strchr(token, '.');
@@ -1178,6 +1176,8 @@ int read_hostsfile(char *filename, unsig
else if (!nomem)
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
}
+
+ lineno += atnl;
}
fclose(f);

View File

@ -0,0 +1,42 @@
From 162e5e0062ce923c494cc64282f293f0ed64fc10 Mon Sep 17 00:00:00 2001
From: Sven Mueller <smu@google.com>
Date: Wed, 27 Feb 2019 21:17:37 +0000
Subject: [PATCH 34/57] Fix bug added in 2.80 non-terminal code which returns
NODATA instead of NXDOMAIN.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Thanks to Sven Muleller and Maciej Żenczykowski for work on this.
https://bugzilla.redhat.com/show_bug.cgi?id=1674067 refers.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
CHANGELOG | 5 +++++
src/cache.c | 1 +
2 files changed, 6 insertions(+)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -21,6 +21,11 @@ version 2.81
correct error messages. Thanks to Christian Rosentreter
for reporting this.
+ Fix bug in DNS non-terminal code, added in 2.80, which could
+ sometimes cause a NODATA rather than an NXDOMAIN reply.
+ Thanks to Sven Mueller and Maciej Żenczykowski for spotting
+ and diagnosing the bug and providing patches.
+
version 2.80
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
--- a/src/cache.c
+++ b/src/cache.c
@@ -790,6 +790,7 @@ int cache_find_non_terminal(char *name,
if (!is_outdated_cname_pointer(crecp) &&
!is_expired(now, crecp) &&
(crecp->flags & F_FORWARD) &&
+ !(crecp->flags & F_NXDOMAIN) &&
hostname_isequal(name, cache_get_name(crecp)))
return 1;

View File

@ -0,0 +1,42 @@
From df6636bff61aa53ed7ad4b34d940805193c0bc74 Mon Sep 17 00:00:00 2001
From: Florent Fourcot <florent.fourcot@wifirst.fr>
Date: Mon, 11 Feb 2019 17:04:44 +0100
Subject: [PATCH 35/57] lease: prune lease as soon as expired
We detected a performance issue on a dnsmasq running many dhcp sessions
(more than 10 000). At the end of the day, the server was only releasing
old DHCP leases but was consuming a lot of CPU.
It looks like curent dhcp pruning:
1) it's pruning old sessions (iterate on all current leases). It's
important to note that it's only pruning session expired since more
than one second
2) it's looking for next lease to expire (iterate on all current leases
again)
3) it launchs an alarm to catch next expiration found in step 2). This
value can be zero for leases just expired (but not pruned).
So, for a second, dnsmasq could fall in a "prune loop" by doing:
* Not pruning anything, since difftime() is not > 0
* Run alarm again with zero as argument
On a server with very large number of leases and releasing often
sessions, that can waste a very big CPU time.
Signed-off-by: Florent Fourcot <florent.fourcot@wifirst.fr>
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/lease.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/lease.c
+++ b/src/lease.c
@@ -558,7 +558,7 @@ void lease_prune(struct dhcp_lease *targ
for (lease = leases, up = &leases; lease; lease = tmp)
{
tmp = lease->next;
- if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target)
+ if ((lease->expires != 0 && difftime(now, lease->expires) >= 0) || lease == target)
{
file_dirty = 1;
if (lease->hostname)

View File

@ -0,0 +1,20 @@
From 065e5bb0b1c5b9b4ce124ecf35cb2c51feda70e6 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 1 Mar 2019 14:38:51 +0000
Subject: [PATCH 36/57] More /etc/hosts linecount fixing.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/cache.c | 1 +
1 file changed, 1 insertion(+)
--- a/src/cache.c
+++ b/src/cache.c
@@ -1126,6 +1126,7 @@ int read_hostsfile(char *filename, unsig
my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
while (atnl == 0)
atnl = gettok(f, token);
+ lineno += atnl;
continue;
}

View File

@ -0,0 +1,21 @@
From 8bd28a87a241cbdfafd56d1c952656bde53dfa7b Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 1 Mar 2019 15:00:12 +0000
Subject: [PATCH 37/57] Small error-message tweak, for clarity.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/network.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/network.c
+++ b/src/network.c
@@ -1535,7 +1535,7 @@ void check_servers(void)
{
count--;
if (++locals <= LOCALS_LOGGED)
- my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
+ my_syslog(LOG_INFO, _("using only locally-known addresses for %s %s"), s1, s2);
}
else if (serv->flags & SERV_USE_RESOLV)
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);

View File

@ -0,0 +1,24 @@
From a066aac332dcddbdfb8325d50a4baeb67f67c793 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 1 Mar 2019 16:18:07 +0000
Subject: [PATCH 38/57] Fix to credits in
162e5e0062ce923c494cc64282f293f0ed64fc10
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
CHANGELOG | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -23,8 +23,8 @@ version 2.81
Fix bug in DNS non-terminal code, added in 2.80, which could
sometimes cause a NODATA rather than an NXDOMAIN reply.
- Thanks to Sven Mueller and Maciej Żenczykowski for spotting
- and diagnosing the bug and providing patches.
+ Thanks to Norman Rasmussen, Sven Mueller and Maciej Żenczykowski
+ for spotting and diagnosing the bug and providing patches.
version 2.80

View File

@ -0,0 +1,42 @@
From 6799320edb9f8465659259721e01e15f9d263aeb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 4 Mar 2019 22:59:42 +0000
Subject: [PATCH 41/57] Don't attempt to parse a sequence of hex digits without
any colons as IPv6 address.
Another confusion in the heuristic dhcp-option parsing. Sigh.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/option.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/src/option.c
+++ b/src/option.c
@@ -1181,7 +1181,7 @@ static int parse_dhcp_opt(char *errstr,
{
/* characterise the value */
char c;
- int found_dig = 0;
+ int found_dig = 0, found_colon = 0;
is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
addrs = digs = 1;
dots = 0;
@@ -1195,6 +1195,7 @@ static int parse_dhcp_opt(char *errstr,
{
digs++;
is_dec = is_addr = 0;
+ found_colon = 1;
}
else if (c == '/')
{
@@ -1236,6 +1237,9 @@ static int parse_dhcp_opt(char *errstr,
if (!found_dig)
is_dec = is_addr = 0;
+
+ if (!found_colon)
+ is_addr6 = 0;
/* We know that some options take addresses */
if (opt_len & OT_ADDR_LIST)

View File

@ -0,0 +1,21 @@
From 5ed82ae5f2946367b62f17fa4c48e9703f189c72 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 5 Mar 2019 16:38:34 +0000
Subject: [PATCH 42/57] Remove unclear gcc-ism in conditional expression.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/radv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/radv.c
+++ b/src/radv.c
@@ -412,7 +412,7 @@ static void send_ra_alias(time_t now, in
if (mtu == 0)
{
char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
- sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? : iface_name);
+ sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? mtu_name : iface_name);
if ((f = fopen(daemon->namebuff, "r")))
{
if (fgets(daemon->namebuff, MAXDNAME, f))

View File

@ -0,0 +1,44 @@
From c61c7bb2257059fe1e14851289594415eb0659d7 Mon Sep 17 00:00:00 2001
From: Dominik DL6ER <dl6er@dl6er.de>
Date: Sun, 10 Mar 2019 19:37:57 +0100
Subject: [PATCH 43/57] Remove redundant prototypes from dnsmasq.h
Dear Simon,
the attached patch removes three redundant prototypes from dnsmasq.h. There is no functional change.
Best regards,
Dominik
From c0b2ccfd20c4eec9d09468fdfe9b4ca8a8f8591e Mon Sep 17 00:00:00 2001
From: DL6ER <dl6er@dl6er.de>
Date: Sun, 10 Mar 2019 19:34:07 +0100
Subject: [PATCH] Remove redundant prototypes from dnsmasq.h
Signed-off-by: DL6ER <dl6er@dl6er.de>
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/dnsmasq.h | 5 -----
1 file changed, 5 deletions(-)
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1205,9 +1205,6 @@ size_t resize_packet(struct dns_header *
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, ...);
-unsigned char *skip_questions(struct dns_header *header, size_t plen);
-int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
- char *name, int isExtract, int extrabytes);
int in_arpa_name_2_addr(char *namein, union all_addr *addrp);
int private_net(struct in_addr addr, int ban_localhost);
@@ -1545,8 +1542,6 @@ void dhcp_update_configs(struct dhcp_con
void display_opts(void);
int lookup_dhcp_opt(int prot, char *name);
int lookup_dhcp_len(int prot, int val);
-char *option_string(int prot, unsigned int opt, unsigned char *val,
- int opt_len, char *buf, int buf_len);
struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context,
unsigned char *clid, int clid_len,

View File

@ -0,0 +1,158 @@
From 608aa9fcfca2ffeba40d78c7c4e0dcb50e0d5704 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 10 Mar 2019 22:44:15 +0000
Subject: [PATCH 44/57] Support TCP fastopen on incoming and outgoing
connections.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
CHANGELOG | 5 ++++-
src/dnsmasq.h | 1 +
src/forward.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
src/network.c | 5 +++++
4 files changed, 51 insertions(+), 10 deletions(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -26,7 +26,10 @@ version 2.81
Thanks to Norman Rasmussen, Sven Mueller and Maciej Żenczykowski
for spotting and diagnosing the bug and providing patches.
-
+ Support TCP-fastopen (RFC-7413) on both incoming and
+ outgoing TCP connections, if supported and enabled in the OS.
+
+
version 2.80
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
for the initial patch and motivation.
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -128,6 +128,7 @@ typedef unsigned long long u64;
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
#include <sys/uio.h>
#include <syslog.h>
#include <dirent.h>
--- a/src/forward.c
+++ b/src/forward.c
@@ -1635,6 +1635,8 @@ static int tcp_key_recurse(time_t now, i
while (1)
{
+ int data_sent = 0;
+
if (!firstsendto)
firstsendto = server;
else
@@ -1667,8 +1669,22 @@ static int tcp_key_recurse(time_t now, i
setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
#endif
- if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1) ||
- connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
+ if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1))
+ {
+ close(server->tcpfd);
+ server->tcpfd = -1;
+ continue; /* No good, next server */
+ }
+
+#ifdef MSG_FASTOPEN
+ while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
+ MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
+
+ if (errno == 0)
+ data_sent = 1;
+#endif
+
+ if (!data_sent && connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
{
close(server->tcpfd);
server->tcpfd = -1;
@@ -1678,7 +1694,7 @@ static int tcp_key_recurse(time_t now, i
server->flags &= ~SERV_GOT_TCP;
}
- if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
+ if ((!data_sent && !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))
@@ -1951,6 +1967,8 @@ unsigned char *tcp_request(int confd, ti
which can go to the same server, do so. */
while (1)
{
+ int data_sent = 0;
+
if (!firstsendto)
firstsendto = last_server;
else
@@ -1969,6 +1987,8 @@ unsigned char *tcp_request(int confd, ti
continue;
retry:
+ *length = htons(size);
+
if (last_server->tcpfd == -1)
{
if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
@@ -1978,10 +1998,24 @@ unsigned char *tcp_request(int confd, ti
/* Copy connection mark of incoming query to outgoing connection. */
if (have_mark)
setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
-#endif
+#endif
- if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1) ||
- connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
+ if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1)))
+ {
+ close(last_server->tcpfd);
+ last_server->tcpfd = -1;
+ continue;
+ }
+
+#ifdef MSG_FASTOPEN
+ while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
+ MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
+
+ if (errno == 0)
+ data_sent = 1;
+#endif
+
+ if (!data_sent && connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
{
close(last_server->tcpfd);
last_server->tcpfd = -1;
@@ -1991,13 +2025,11 @@ unsigned char *tcp_request(int confd, ti
last_server->flags &= ~SERV_GOT_TCP;
}
- *length = htons(size);
-
/* get query name again for logging - may have been overwritten */
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
strcpy(daemon->namebuff, "query");
- if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
+ if ((!data_sent && !read_write(last_server->tcpfd, packet, size + sizeof(u16), 0)) ||
!read_write(last_server->tcpfd, &c1, 1, 1) ||
!read_write(last_server->tcpfd, &c2, 1, 1) ||
!read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
--- a/src/network.c
+++ b/src/network.c
@@ -726,6 +726,11 @@ static int make_sock(union mysockaddr *a
if (type == SOCK_STREAM)
{
+#ifdef TCP_FASTOPEN
+ int qlen = 5;
+ setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
+#endif
+
if (listen(fd, TCP_BACKLOG) == -1)
goto err;
}

View File

@ -0,0 +1,203 @@
From 305ffb5ef0ba5ab1df32ef80f266a4c9e395ca13 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 16 Mar 2019 18:17:17 +0000
Subject: [PATCH 45/57] Improve kernel-capability manipulation code under
Linux.
Dnsmasq now fails early if a required capability is not available,
and tries not to request capabilities not required by its
configuration.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
CHANGELOG | 7 ++-
src/dnsmasq.c | 119 +++++++++++++++++++++++++++++++++-----------------
2 files changed, 84 insertions(+), 42 deletions(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -28,7 +28,12 @@ version 2.81
Support TCP-fastopen (RFC-7413) on both incoming and
outgoing TCP connections, if supported and enabled in the OS.
-
+
+ Improve kernel-capability manipulation code under Linux. Dnsmasq
+ now fails early if a required capability is not available, and
+ tries not to request capabilities not required by its
+ configuration.
+
version 2.80
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -52,6 +52,9 @@ int main (int argc, char **argv)
#if defined(HAVE_LINUX_NETWORK)
cap_user_header_t hdr = NULL;
cap_user_data_t data = NULL;
+ int need_cap_net_admin = 0;
+ int need_cap_net_raw = 0;
+ int need_cap_net_bind_service = 0;
char *bound_device = NULL;
int did_bind = 0;
#endif
@@ -285,11 +288,24 @@ int main (int argc, char **argv)
}
if (daemon->dhcp || daemon->relay4)
- dhcp_init();
+ {
+ dhcp_init();
+# ifdef HAVE_LINUX_NETWORK
+ if (!option_bool(OPT_NO_PING))
+ need_cap_net_raw = 1;
+ need_cap_net_admin = 1;
+# endif
+ }
# ifdef HAVE_DHCP6
if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
- ra_init(now);
+ {
+ ra_init(now);
+# ifdef HAVE_LINUX_NETWORK
+ need_cap_net_raw = 1;
+ need_cap_net_admin = 1;
+# endif
+ }
if (daemon->doing_dhcp6 || daemon->relay6)
dhcp6_init();
@@ -299,7 +315,12 @@ int main (int argc, char **argv)
#ifdef HAVE_IPSET
if (daemon->ipsets)
- ipset_init();
+ {
+ ipset_init();
+# ifdef HAVE_LINUX_NETWORK
+ need_cap_net_admin = 1;
+# endif
+ }
#endif
#if defined(HAVE_LINUX_NETWORK)
@@ -440,28 +461,58 @@ int main (int argc, char **argv)
}
#if defined(HAVE_LINUX_NETWORK)
+ /* We keep CAP_NETADMIN (for ARP-injection) and
+ CAP_NET_RAW (for icmp) if we're doing dhcp,
+ if we have yet to bind ports because of DAD,
+ or we're doing it dynamically,
+ we need CAP_NET_BIND_SERVICE. */
+ if ((is_dad_listeners() || option_bool(OPT_CLEVERBIND)) &&
+ (option_bool(OPT_TFTP) || (daemon->port != 0 && daemon->port <= 1024)))
+ need_cap_net_bind_service = 1;
+
/* determine capability API version here, while we can still
call safe_malloc */
- if (ent_pw && ent_pw->pw_uid != 0)
+ int capsize = 1; /* for header version 1 */
+ char *fail = NULL;
+
+ hdr = safe_malloc(sizeof(*hdr));
+
+ /* find version supported by kernel */
+ memset(hdr, 0, sizeof(*hdr));
+ capget(hdr, NULL);
+
+ if (hdr->version != LINUX_CAPABILITY_VERSION_1)
{
- int capsize = 1; /* for header version 1 */
- hdr = safe_malloc(sizeof(*hdr));
-
- /* find version supported by kernel */
- memset(hdr, 0, sizeof(*hdr));
- capget(hdr, NULL);
-
- if (hdr->version != LINUX_CAPABILITY_VERSION_1)
- {
- /* if unknown version, use largest supported version (3) */
- if (hdr->version != LINUX_CAPABILITY_VERSION_2)
- hdr->version = LINUX_CAPABILITY_VERSION_3;
- capsize = 2;
- }
-
- data = safe_malloc(sizeof(*data) * capsize);
- memset(data, 0, sizeof(*data) * capsize);
+ /* if unknown version, use largest supported version (3) */
+ if (hdr->version != LINUX_CAPABILITY_VERSION_2)
+ hdr->version = LINUX_CAPABILITY_VERSION_3;
+ capsize = 2;
}
+
+ data = safe_malloc(sizeof(*data) * capsize);
+ capget(hdr, data); /* Get current values, for verification */
+
+ if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
+ fail = "NET_ADMIN";
+ else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
+ fail = "NET_RAW";
+ else if (need_cap_net_bind_service && !(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
+ fail = "NET_BIND_SERVICE";
+
+ if (fail)
+ die(_("process is missing required capability %s"), fail, EC_MISC);
+
+ /* Now set bitmaps to set caps after daemonising */
+ memset(data, 0, sizeof(*data) * capsize);
+
+ if (need_cap_net_admin)
+ data->effective |= (1 << CAP_NET_ADMIN);
+ if (need_cap_net_raw)
+ data->effective |= (1 << CAP_NET_RAW);
+ if (need_cap_net_bind_service)
+ data->effective |= (1 << CAP_NET_BIND_SERVICE);
+
+ data->permitted = data->effective;
#endif
/* Use a pipe to carry signals and other events back to the event loop
@@ -626,18 +677,9 @@ int main (int argc, char **argv)
if (ent_pw && ent_pw->pw_uid != 0)
{
#if defined(HAVE_LINUX_NETWORK)
- /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
- CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
- ports because of DAD, or we're doing it dynamically,
- we need CAP_NET_BIND_SERVICE too. */
- if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
- data->effective = data->permitted = data->inheritable =
- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
- (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
- else
- data->effective = data->permitted = data->inheritable =
- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
-
+ /* Need to be able to drop root. */
+ data->effective |= (1 << CAP_SETUID);
+ data->permitted |= (1 << CAP_SETUID);
/* Tell kernel to not clear capabilities when dropping root */
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
bad_capabilities = errno;
@@ -678,15 +720,10 @@ int main (int argc, char **argv)
}
#ifdef HAVE_LINUX_NETWORK
- if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
- data->effective = data->permitted =
- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
- else
- data->effective = data->permitted =
- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
- data->inheritable = 0;
+ data->effective &= ~(1 << CAP_SETUID);
+ data->permitted &= ~(1 << CAP_SETUID);
- /* lose the setuid and setgid capabilities */
+ /* lose the setuid capability */
if (capset(hdr, data) == -1)
{
send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);

View File

@ -0,0 +1,626 @@
From ae5b7e04a1025167f1b80840e61432a3cea9625c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 27 Mar 2019 22:33:28 +0000
Subject: [PATCH 46/57] Add --shared-network DHCP configuration.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
CHANGELOG | 5 ++
man/dnsmasq.8 | 21 ++++++
src/dhcp.c | 76 ++++++++++++++++++----
src/dhcp6.c | 175 ++++++++++++++++++++++++++++----------------------
src/dnsmasq.h | 11 ++++
src/option.c | 41 ++++++++++++
src/rfc2131.c | 97 +++++++++++++++++-----------
src/rfc3315.c | 40 +++++++++---
8 files changed, 332 insertions(+), 134 deletions(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -34,6 +34,11 @@ version 2.81
tries not to request capabilities not required by its
configuration.
+ Add --shared-network config. This enables allocation of addresses
+ the DHCP server in subnets where the server (or relay) doesn't
+ have an interface on the network in that subnet. Many thanks to
+ plank.de for sponsoring this feature.
+
version 2.80
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -1741,6 +1741,27 @@ It is permissible to add more than one a
\fB--bridge-interface=int1,alias1,alias2\fP is exactly equivalent to
\fB--bridge-interface=int1,alias1 --bridge-interface=int1,alias2\fP
.TP
+.B --shared-network=<interface>|<addr>,<addr>
+The DHCP server determines which dhcp ranges are useable for allocating and
+address to a DHCP client based on the network from which the DHCP request arrives,
+and the IP configuration of the server's interface on that network. The shared-network
+option extends the available subnets (and therefore dhcp ranges) beyond the
+subnets configured on the arrival interface. The first argument is either the
+name of an interface or an address which is configured on a local interface, and the
+second argument is an address which defines another subnet on which addresses can be allocated.
+To be useful, there must be suitable dhcp-range which allows address allocation on this subnet
+and this dhcp-range MUST include the netmask. Use shared-network also needs extra
+consideration of routing. Dnsmasq doesn't have the usual information which it uses to
+determine the default route, so the default route option (or other routing) MUST be
+manually configured. The client must have a route to the server: if the two-address form
+of shared-network is used, this will be to the first specified address. If the interface,address
+form is used, there must be a route to all of the addresses configured on the interface.
+
+The two-address form of shared-network is also usable with a DHCP relay: the first address
+is the address of the relay and the second, as before, specifies an extra subnet which
+may be allocated.
+
+.TP
.B \-s, --domain=<domain>[,<address range>[,local]]
Specifies DNS domains for the DHCP server. Domains may be be given
unconditionally (without the IP range) or for limited IP ranges. This has two effects;
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -507,33 +507,83 @@ static int check_listen_addrs(struct in_
Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
-static int complete_context(struct in_addr local, int if_index, char *label,
- struct in_addr netmask, struct in_addr broadcast, void *vparam)
+static void guess_range_netmask(struct in_addr addr, struct in_addr netmask)
{
struct dhcp_context *context;
- struct dhcp_relay *relay;
- struct iface_param *param = vparam;
- (void)label;
-
for (context = daemon->dhcp; context; context = context->next)
- {
- if (!(context->flags & CONTEXT_NETMASK) &&
- (is_same_net(local, context->start, netmask) ||
- is_same_net(local, context->end, netmask)))
+ if (!(context->flags & CONTEXT_NETMASK) &&
+ (is_same_net(addr, context->start, netmask) ||
+ is_same_net(addr, context->end, netmask)))
{
if (context->netmask.s_addr != netmask.s_addr &&
- !(is_same_net(local, context->start, netmask) &&
- is_same_net(local, context->end, netmask)))
+ !(is_same_net(addr, context->start, netmask) &&
+ is_same_net(addr, context->end, netmask)))
{
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
}
- context->netmask = netmask;
+ context->netmask = netmask;
}
+}
+
+static int complete_context(struct in_addr local, int if_index, char *label,
+ struct in_addr netmask, struct in_addr broadcast, void *vparam)
+{
+ struct dhcp_context *context;
+ struct dhcp_relay *relay;
+ struct iface_param *param = vparam;
+ struct shared_network *share;
+
+ (void)label;
+
+ for (share = daemon->shared_networks; share; share = share->next)
+ {
+#ifdef HAVE_DHCP6
+ if (share->shared_addr.s_addr == 0)
+ continue;
+#endif
+
+ if (share->if_index != 0)
+ {
+ if (share->if_index != if_index)
+ continue;
+ }
+ else
+ {
+ if (share->match_addr.s_addr != local.s_addr)
+ continue;
+ }
+
+ for (context = daemon->dhcp; context; context = context->next)
+ {
+ if (context->netmask.s_addr != 0 &&
+ is_same_net(share->shared_addr, context->start, context->netmask) &&
+ is_same_net(share->shared_addr, context->end, context->netmask))
+ {
+ /* link it onto the current chain if we've not seen it before */
+ if (context->current == context)
+ {
+ /* For a shared network, we have no way to guess what the default route should be. */
+ context->router.s_addr = 0;
+ context->local = local; /* Use configured address for Server Identifier */
+ context->current = param->current;
+ param->current = context;
+ }
+
+ if (!(context->flags & CONTEXT_BRDCAST))
+ context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
+ }
+ }
+ }
+
+ guess_range_netmask(local, netmask);
+
+ for (context = daemon->dhcp; context; context = context->next)
+ {
if (context->netmask.s_addr != 0 &&
is_same_net(local, context->start, context->netmask) &&
is_same_net(local, context->end, context->netmask))
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -299,89 +299,114 @@ static int complete_context6(struct in6_
unsigned int valid, void *vparam)
{
struct dhcp_context *context;
+ struct shared_network *share;
struct dhcp_relay *relay;
struct iface_param *param = vparam;
struct iname *tmp;
(void)scope; /* warning */
- if (if_index == param->ind)
- {
- if (IN6_IS_ADDR_LINKLOCAL(local))
- param->ll_addr = *local;
- else if (IN6_IS_ADDR_ULA(local))
- param->ula_addr = *local;
-
- if (!IN6_IS_ADDR_LOOPBACK(local) &&
- !IN6_IS_ADDR_LINKLOCAL(local) &&
- !IN6_IS_ADDR_MULTICAST(local))
- {
- /* if we have --listen-address config, see if the
- arrival interface has a matching address. */
- for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
- if (tmp->addr.sa.sa_family == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
- param->addr_match = 1;
-
- /* Determine a globally address on the arrival interface, even
- if we have no matching dhcp-context, because we're only
- allocating on remote subnets via relays. This
- is used as a default for the DNS server option. */
- param->fallback = *local;
-
- for (context = daemon->dhcp6; context; context = context->next)
- {
- if ((context->flags & CONTEXT_DHCP) &&
- !(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
- prefix <= context->prefix &&
- is_same_net6(local, &context->start6, context->prefix) &&
- is_same_net6(local, &context->end6, context->prefix))
- {
-
-
- /* link it onto the current chain if we've not seen it before */
- if (context->current == context)
- {
- struct dhcp_context *tmp, **up;
-
- /* use interface values only for constructed contexts */
- if (!(context->flags & CONTEXT_CONSTRUCTED))
- preferred = valid = 0xffffffff;
- else if (flags & IFACE_DEPRECATED)
- preferred = 0;
-
- if (context->flags & CONTEXT_DEPRECATE)
- preferred = 0;
-
- /* order chain, longest preferred time first */
- for (up = &param->current, tmp = param->current; tmp; tmp = tmp->current)
- if (tmp->preferred <= preferred)
- break;
- else
- up = &tmp->current;
-
- context->current = *up;
- *up = context;
- context->local6 = *local;
- context->preferred = preferred;
- context->valid = valid;
- }
- }
- }
- }
-
- for (relay = daemon->relay6; relay; relay = relay->next)
- if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay &&
- (IN6_IS_ADDR_UNSPECIFIED(&param->relay_local) || IN6_ARE_ADDR_EQUAL(local, &param->relay_local)))
+ if (if_index != param->ind)
+ return 1;
+
+ if (IN6_IS_ADDR_LINKLOCAL(local))
+ param->ll_addr = *local;
+ else if (IN6_IS_ADDR_ULA(local))
+ param->ula_addr = *local;
+
+ if (IN6_IS_ADDR_LOOPBACK(local) ||
+ IN6_IS_ADDR_LINKLOCAL(local) ||
+ IN6_IS_ADDR_MULTICAST(local))
+ return 1;
+
+ /* if we have --listen-address config, see if the
+ arrival interface has a matching address. */
+ for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
+ if (tmp->addr.sa.sa_family == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
+ param->addr_match = 1;
+
+ /* Determine a globally address on the arrival interface, even
+ if we have no matching dhcp-context, because we're only
+ allocating on remote subnets via relays. This
+ is used as a default for the DNS server option. */
+ param->fallback = *local;
+
+ for (context = daemon->dhcp6; context; context = context->next)
+ if ((context->flags & CONTEXT_DHCP) &&
+ !(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
+ prefix <= context->prefix &&
+ context->current == context)
+ {
+ if (is_same_net6(local, &context->start6, context->prefix) &&
+ is_same_net6(local, &context->end6, context->prefix))
{
- relay->current = param->relay;
- param->relay = relay;
- param->relay_local = *local;
+ struct dhcp_context *tmp, **up;
+
+ /* use interface values only for constructed contexts */
+ if (!(context->flags & CONTEXT_CONSTRUCTED))
+ preferred = valid = 0xffffffff;
+ else if (flags & IFACE_DEPRECATED)
+ preferred = 0;
+
+ if (context->flags & CONTEXT_DEPRECATE)
+ preferred = 0;
+
+ /* order chain, longest preferred time first */
+ for (up = &param->current, tmp = param->current; tmp; tmp = tmp->current)
+ if (tmp->preferred <= preferred)
+ break;
+ else
+ up = &tmp->current;
+
+ context->current = *up;
+ *up = context;
+ context->local6 = *local;
+ context->preferred = preferred;
+ context->valid = valid;
}
-
- }
-
- return 1;
+ else
+ {
+ for (share = daemon->shared_networks; share; share = share->next)
+ {
+ /* IPv4 shared_address - ignore */
+ if (share->shared_addr.s_addr != 0)
+ continue;
+
+ if (share->if_index != 0)
+ {
+ if (share->if_index != if_index)
+ continue;
+ }
+ else
+ {
+ if (!IN6_ARE_ADDR_EQUAL(&share->match_addr6, local))
+ continue;
+ }
+
+ if (is_same_net6(&share->shared_addr6, &context->start6, context->prefix) &&
+ is_same_net6(&share->shared_addr6, &context->end6, context->prefix))
+ {
+ context->current = param->current;
+ param->current = context;
+ context->local6 = *local;
+ context->preferred = context->flags & CONTEXT_DEPRECATE ? 0 :0xffffffff;
+ context->valid = 0xffffffff;
+ }
+ }
+ }
+ }
+
+ for (relay = daemon->relay6; relay; relay = relay->next)
+ if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay &&
+ (IN6_IS_ADDR_UNSPECIFIED(&param->relay_local) || IN6_ARE_ADDR_EQUAL(local, &param->relay_local)))
+ {
+ relay->current = param->relay;
+ param->relay = relay;
+ param->relay_local = *local;
+ }
+
+ return 1;
}
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, u64 addr)
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -910,6 +910,16 @@ struct dhcp_context {
struct dhcp_context *next, *current;
};
+struct shared_network {
+ int if_index;
+ struct in_addr match_addr, shared_addr;
+#ifdef HAVE_DHCP6
+ /* shared_addr == 0 for IP6 entries. */
+ struct in6_addr match_addr6, shared_addr6;
+#endif
+ struct shared_network *next;
+};
+
#define CONTEXT_STATIC (1u<<0)
#define CONTEXT_NETMASK (1u<<1)
#define CONTEXT_BRDCAST (1u<<2)
@@ -1107,6 +1117,7 @@ extern struct daemon {
struct ping_result *ping_results;
FILE *lease_stream;
struct dhcp_bridge *bridges;
+ struct shared_network *shared_networks;
#ifdef HAVE_DHCP6
int duid_len;
unsigned char *duid;
--- a/src/option.c
+++ b/src/option.c
@@ -166,6 +166,7 @@ struct myoption {
#define LOPT_UBUS 354
#define LOPT_NAME_MATCH 355
#define LOPT_CAA 356
+#define LOPT_SHARED_NET 357
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -259,6 +260,7 @@ static const struct myoption opts[] =
{ "ptr-record", 1, 0, LOPT_PTR },
{ "naptr-record", 1, 0, LOPT_NAPTR },
{ "bridge-interface", 1, 0 , LOPT_BRIDGE },
+ { "shared-network", 1, 0, LOPT_SHARED_NET },
{ "dhcp-option-force", 1, 0, LOPT_FORCE },
{ "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
{ "log-dhcp", 0, 0, LOPT_LOG_OPTS },
@@ -431,6 +433,7 @@ static struct {
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
{ LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
+ { LOPT_SHARED_NET, ARG_DUP, "<iface>|<addr>,<addr>", gettext_noop("Specify extra networks sharing a broadcast domain for DHCP"), NULL},
{ '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
{ '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
{ LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
@@ -2873,6 +2876,44 @@ static int one_opt(int option, char *arg
}
#ifdef HAVE_DHCP
+ case LOPT_SHARED_NET: /* --shared-network */
+ {
+ struct shared_network *new = opt_malloc(sizeof(struct shared_network));
+
+#ifdef HAVE_DHCP6
+ new->shared_addr.s_addr = 0;
+#endif
+ new->if_index = 0;
+
+ if (!(comma = split(arg)))
+ {
+ snerr:
+ free(new);
+ ret_err(_("bad shared-network"));
+ }
+
+ if (inet_pton(AF_INET, comma, &new->shared_addr))
+ {
+ if (!inet_pton(AF_INET, arg, &new->match_addr) &&
+ !(new->if_index = if_nametoindex(arg)))
+ goto snerr;
+ }
+#ifdef HAVE_DHCP6
+ else if (inet_pton(AF_INET6, comma, &new->shared_addr6))
+ {
+ if (!inet_pton(AF_INET6, arg, &new->match_addr6) &&
+ !(new->if_index = if_nametoindex(arg)))
+ goto snerr;
+ }
+#endif
+ else
+ goto snerr;
+
+ new->next = daemon->shared_networks;
+ daemon->shared_networks = new;
+ break;
+ }
+
case 'F': /* --dhcp-range */
{
int k, leasepos = 2;
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -274,8 +274,9 @@ size_t dhcp_reply(struct dhcp_context *c
if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
{
struct dhcp_context *context_tmp, *context_new = NULL;
+ struct shared_network *share = NULL;
struct in_addr addr;
- int force = 0;
+ int force = 0, via_relay = 0;
if (subnet_addr.s_addr)
{
@@ -286,6 +287,7 @@ size_t dhcp_reply(struct dhcp_context *c
{
addr = mess->giaddr;
force = 1;
+ via_relay = 1;
}
else
{
@@ -302,42 +304,65 @@ size_t dhcp_reply(struct dhcp_context *c
}
if (!context_new)
- for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
- {
- struct in_addr netmask = context_tmp->netmask;
+ {
+ for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
+ {
+ struct in_addr netmask = context_tmp->netmask;
+
+ /* guess the netmask for relayed networks */
+ if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
+ {
+ if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
+ netmask.s_addr = htonl(0xff000000);
+ else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
+ netmask.s_addr = htonl(0xffff0000);
+ else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
+ netmask.s_addr = htonl(0xffffff00);
+ }
- /* guess the netmask for relayed networks */
- if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
- {
- if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
- netmask.s_addr = htonl(0xff000000);
- else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
- netmask.s_addr = htonl(0xffff0000);
- else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
- netmask.s_addr = htonl(0xffffff00);
- }
-
- /* This section fills in context mainly when a client which is on a remote (relayed)
- network renews a lease without using the relay, after dnsmasq has restarted. */
- if (netmask.s_addr != 0 &&
- is_same_net(addr, context_tmp->start, netmask) &&
- is_same_net(addr, context_tmp->end, netmask))
- {
- context_tmp->netmask = netmask;
- if (context_tmp->local.s_addr == 0)
- context_tmp->local = fallback;
- if (context_tmp->router.s_addr == 0)
- context_tmp->router = mess->giaddr;
-
- /* fill in missing broadcast addresses for relayed ranges */
- if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
- context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
-
- context_tmp->current = context_new;
- context_new = context_tmp;
- }
- }
-
+ /* check to see is a context is OK because of a shared address on
+ the relayed subnet. */
+ if (via_relay)
+ for (share = daemon->shared_networks; share; share = share->next)
+ {
+#ifdef HAVE_DHCP6
+ if (share->shared_addr.s_addr == 0)
+ continue;
+#endif
+ if (share->if_index != 0 ||
+ share->match_addr.s_addr != mess->giaddr.s_addr)
+ continue;
+
+ if (netmask.s_addr != 0 &&
+ is_same_net(share->shared_addr, context_tmp->start, netmask) &&
+ is_same_net(share->shared_addr, context_tmp->end, netmask))
+ break;
+ }
+
+ /* This section fills in context mainly when a client which is on a remote (relayed)
+ network renews a lease without using the relay, after dnsmasq has restarted. */
+ if (share ||
+ (netmask.s_addr != 0 &&
+ is_same_net(addr, context_tmp->start, netmask) &&
+ is_same_net(addr, context_tmp->end, netmask)))
+ {
+ context_tmp->netmask = netmask;
+ if (context_tmp->local.s_addr == 0)
+ context_tmp->local = fallback;
+ if (context_tmp->router.s_addr == 0 && !share)
+ context_tmp->router = mess->giaddr;
+
+ /* fill in missing broadcast addresses for relayed ranges */
+ if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
+ context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
+
+ context_tmp->current = context_new;
+ context_new = context_tmp;
+ }
+
+ }
+ }
+
if (context_new || force)
context = context_new;
}
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -134,21 +134,41 @@ static int dhcp6_maybe_relay(struct stat
else
{
struct dhcp_context *c;
+ struct shared_network *share = NULL;
state->context = NULL;
-
+
if (!IN6_IS_ADDR_LOOPBACK(state->link_address) &&
!IN6_IS_ADDR_LINKLOCAL(state->link_address) &&
!IN6_IS_ADDR_MULTICAST(state->link_address))
for (c = daemon->dhcp6; c; c = c->next)
- if ((c->flags & CONTEXT_DHCP) &&
- !(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
- is_same_net6(state->link_address, &c->start6, c->prefix) &&
- is_same_net6(state->link_address, &c->end6, c->prefix))
- {
- c->preferred = c->valid = 0xffffffff;
- c->current = state->context;
- state->context = c;
- }
+ {
+ for (share = daemon->shared_networks; share; share = share->next)
+ {
+ if (share->shared_addr.s_addr != 0)
+ continue;
+
+ if (share->if_index != 0 ||
+ !IN6_ARE_ADDR_EQUAL(state->link_address, &share->match_addr6))
+ continue;
+
+ if ((c->flags & CONTEXT_DHCP) &&
+ !(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
+ is_same_net6(&share->shared_addr6, &c->start6, c->prefix) &&
+ is_same_net6(&share->shared_addr6, &c->end6, c->prefix))
+ break;
+ }
+
+ if (share ||
+ ((c->flags & CONTEXT_DHCP) &&
+ !(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
+ is_same_net6(state->link_address, &c->start6, c->prefix) &&
+ is_same_net6(state->link_address, &c->end6, c->prefix)))
+ {
+ c->preferred = c->valid = 0xffffffff;
+ c->current = state->context;
+ state->context = c;
+ }
+ }
if (!state->context)
{

View File

@ -0,0 +1,21 @@
From 1da81f7e23962e160b3b776479631d2a6e7f4e49 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 28 Mar 2019 13:51:11 +0000
Subject: [PATCH 47/57] CHANGELOG typo fix.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
CHANGELOG | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -37,7 +37,7 @@ version 2.81
Add --shared-network config. This enables allocation of addresses
the DHCP server in subnets where the server (or relay) doesn't
have an interface on the network in that subnet. Many thanks to
- plank.de for sponsoring this feature.
+ kamp.de for sponsoring this feature.
version 2.80

View File

@ -0,0 +1,52 @@
From c6cc455dd191fbea56ee14a0ef88a7d655a6fe9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= <jca@wxcvbn.org>
Date: Fri, 22 Mar 2019 10:56:13 +0100
Subject: [PATCH 48/57] Fix cmsg(3) API usage on OpenBSD
msg_controllen should be set using CMSG_SPACE() to account for padding.
RFC3542 provides more details:
While sending an application may or may not include padding at the end
of last ancillary data in msg_controllen and implementations must
accept both as valid.
At least OpenBSD rejects control messages if msg_controllen doesn't
account for padding, so use CMSG_SPACE() for maximal portability. This
is consistent with the example provided in the Linux cmsg(3) manpage.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/forward.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/src/forward.c
+++ b/src/forward.c
@@ -65,13 +65,15 @@ int send_from(int fd, int nowild, char *
struct in_pktinfo p;
p.ipi_ifindex = 0;
p.ipi_spec_dst = source->addr4;
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
- msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
cmptr->cmsg_level = IPPROTO_IP;
cmptr->cmsg_type = IP_PKTINFO;
#elif defined(IP_SENDSRCADDR)
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
memcpy(CMSG_DATA(cmptr), &(source->addr4), sizeof(source->addr4));
- msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+ cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
cmptr->cmsg_level = IPPROTO_IP;
cmptr->cmsg_type = IP_SENDSRCADDR;
#endif
@@ -81,8 +83,9 @@ int send_from(int fd, int nowild, char *
struct in6_pktinfo p;
p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
p.ipi6_addr = source->addr6;
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
- msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmptr->cmsg_type = daemon->v6pktinfo;
cmptr->cmsg_level = IPPROTO_IPV6;
}

View File

@ -0,0 +1,23 @@
From 7673013d2323834b555052ddbd87381bb5cd7bac Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 28 Mar 2019 22:04:10 +0000
Subject: [PATCH 49/57] Apply fix from c6cc455dd191fbea56ee14a0ef88a7d655a6fe9a
in DHCP code.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/dhcp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -401,7 +401,8 @@ void dhcp_packet(time_t now, int pxe_fd)
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
pkt->ipi_ifindex = rcvd_iface_index;
pkt->ipi_spec_dst.s_addr = 0;
- msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
+ cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
cmptr->cmsg_level = IPPROTO_IP;
cmptr->cmsg_type = IP_PKTINFO;

View File

@ -0,0 +1,113 @@
From 5fc639cf9a9aafd3a2b50570808a74a4ee5cd12a Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 29 Mar 2019 21:29:43 +0000
Subject: [PATCH 50/57] Don't retry close() syscalls after an EINTR errors.
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2019q1/012953.html
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/dnsmasq.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -552,7 +552,7 @@ int main (int argc, char **argv)
char *msg;
/* close our copy of write-end */
- while (retry_send(close(err_pipe[1])));
+ close(err_pipe[1]);
/* check for errors after the fork */
if (read_event(err_pipe[0], &ev, &msg))
@@ -561,7 +561,7 @@ int main (int argc, char **argv)
_exit(EC_GOOD);
}
- while (retry_send(close(err_pipe[0])));
+ close(err_pipe[0]);
/* NO calls to die() from here on. */
@@ -623,8 +623,7 @@ int main (int argc, char **argv)
err = 1;
else
{
- while (retry_send(close(fd)));
- if (errno != 0)
+ if (close(fd) == -1)
err = 1;
}
}
@@ -957,7 +956,7 @@ int main (int argc, char **argv)
/* finished start-up - release original process */
if (err_pipe[1] != -1)
- while (retry_send(close(err_pipe[1])));
+ close(err_pipe[1]);
if (daemon->port != 0)
check_servers();
@@ -1483,7 +1482,7 @@ static void async_event(int pipe, time_t
do {
helper_write();
} while (!helper_buf_empty() || do_script_run(now));
- while (retry_send(close(daemon->helperfd)));
+ close(daemon->helperfd);
}
#endif
@@ -1728,7 +1727,7 @@ static void check_dns_listeners(time_t n
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
{
- while (retry_send(close(confd)));
+ close(confd);
continue;
}
@@ -1793,7 +1792,7 @@ static void check_dns_listeners(time_t n
if (!client_ok)
{
shutdown(confd, SHUT_RDWR);
- while (retry_send(close(confd)));
+ close(confd);
}
else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
{
@@ -1812,7 +1811,7 @@ static void check_dns_listeners(time_t n
break;
}
}
- while (retry_send(close(confd)));
+ close(confd);
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
daemon->log_id += TCP_MAX_QUERIES;
@@ -1858,7 +1857,7 @@ static void check_dns_listeners(time_t n
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
shutdown(confd, SHUT_RDWR);
- while (retry_send(close(confd)));
+ close(confd);
if (buff)
free(buff);
@@ -1867,7 +1866,7 @@ static void check_dns_listeners(time_t n
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
- while (retry_send(close(s->tcpfd)));
+ close(s->tcpfd);
}
if (!option_bool(OPT_DEBUG))
{
@@ -1943,7 +1942,7 @@ int icmp_ping(struct in_addr addr)
gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
- while (retry_send(close(fd)));
+ close(fd);
#else
opt = 1;
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));

View File

@ -0,0 +1,45 @@
From 5c464ef62e02dea96f830425cf43da7f6a272b4c Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 29 Mar 2019 23:11:05 +0000
Subject: [PATCH 51/57] Allow more then one --conf-file on the command line.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
man/dnsmasq.8 | 5 +++--
src/option.c | 11 ++++++++---
2 files changed, 11 insertions(+), 5 deletions(-)
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -1942,8 +1942,9 @@ cannot be lower than 1025 unless dnsmasq
of concurrent TFTP connections is limited by the size of the port range.
.TP
.B \-C, --conf-file=<file>
-Specify a different configuration file. The \fB--conf-file\fP option is also allowed in
-configuration files, to include multiple configuration files. A
+Specify a configuration file. The presence of this option stops dnsmasq from reading the default configuration
+file (normally /etc/dnsmasq.conf). Multiple files may be specified by repeating the option
+either on the command line or in configuration files. A
filename of "-" causes dnsmasq to read configuration from stdin.
.TP
.B \-7, --conf-dir=<directory>[,<file-extension>......],
--- a/src/option.c
+++ b/src/option.c
@@ -5012,9 +5012,14 @@ void read_opts(int argc, char **argv, ch
}
else if (option == 'C')
{
- if (conffile)
- free(conffile);
- conffile = opt_string_alloc(arg);
+ if (!conffile)
+ conffile = opt_string_alloc(arg);
+ else
+ {
+ char *extra = opt_string_alloc(arg);
+ one_file(extra, 0);
+ free(extra);
+ }
}
else
{

View File

@ -0,0 +1,320 @@
From a2b8220f4e82e454bbc0013ee83ea3220111d92e Mon Sep 17 00:00:00 2001
From: Jan Willem Janssen <j.w.janssen@lxtreme.nl>
Date: Mon, 25 Mar 2019 12:42:23 +0100
Subject: [PATCH 52/57] Improved UBus supported
- aligned the handling of UBus connections with the DBus code as it
makes it a bit easier to comprehend;
- added logging to the various UBus calls to aid debugging from an
enduser point of view, but be careful to not flood the logs;
- show the (lack of) support for UBus in the configuration string.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/config.h | 4 ++
src/dnsmasq.c | 32 +++++++++++-
src/dnsmasq.h | 6 +++
src/ubus.c | 138 ++++++++++++++++++++++++++++++++++++++++++--------
4 files changed, 157 insertions(+), 23 deletions(-)
--- a/src/config.h
+++ b/src/config.h
@@ -362,6 +362,10 @@ static char *compile_opts =
"no-"
#endif
"DBus "
+#ifndef HAVE_UBUS
+"no-"
+#endif
+"UBus "
#ifndef LOCALEDIR
"no-"
#endif
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -420,6 +420,16 @@ int main (int argc, char **argv)
die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
#endif
+ if (option_bool(OPT_UBUS))
+#ifdef HAVE_UBUS
+ {
+ daemon->ubus = NULL;
+ ubus_init();
+ }
+#else
+ die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
+#endif
+
if (daemon->port != 0)
pre_allocate_sfds();
@@ -811,6 +821,16 @@ int main (int argc, char **argv)
}
#endif
+#ifdef HAVE_UBUS
+ if (option_bool(OPT_UBUS))
+ {
+ if (daemon->ubus)
+ my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
+ else
+ my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
+ }
+#endif
+
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
@@ -999,7 +1019,7 @@ int main (int argc, char **argv)
#ifdef HAVE_UBUS
if (option_bool(OPT_UBUS))
- set_ubus_listeners();
+ set_ubus_listeners();
#endif
#ifdef HAVE_DHCP
@@ -1134,7 +1154,15 @@ int main (int argc, char **argv)
#ifdef HAVE_UBUS
if (option_bool(OPT_UBUS))
- check_ubus_listeners();
+ {
+ /* if we didn't create a UBus connection, retry now. */
+ if (!daemon->ubus)
+ {
+ ubus_init();
+ }
+
+ check_ubus_listeners();
+ }
#endif
check_dns_listeners(now);
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1130,6 +1130,11 @@ extern struct daemon {
#ifdef HAVE_DBUS
struct watch *watches;
#endif
+ /* UBus stuff */
+#ifdef HAVE_UBUS
+ /* void * here to avoid depending on ubus headers outside ubus.c */
+ void *ubus;
+#endif
/* TFTP stuff */
struct tftp_transfer *tftp_trans, *tftp_done_trans;
@@ -1467,6 +1472,7 @@ void emit_dbus_signal(int action, struct
/* ubus.c */
#ifdef HAVE_UBUS
+void ubus_init(void);
void set_ubus_listeners(void);
void check_ubus_listeners(void);
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
--- a/src/ubus.c
+++ b/src/ubus.c
@@ -20,29 +20,112 @@
#include <libubus.h>
-static struct ubus_context *ubus = NULL;
static struct blob_buf b;
+static int notify;
+static int error_logged = 0;
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg);
-static struct ubus_method ubus_object_methods[] = {
- {.name = "metrics", .handler = ubus_handle_metrics},
+
+static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj);
+
+static const struct ubus_method ubus_object_methods[] = {
+ UBUS_METHOD_NOARG("metrics", ubus_handle_metrics),
};
-static struct ubus_object_type ubus_object_type = UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
+static struct ubus_object_type ubus_object_type =
+ UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
static struct ubus_object ubus_object = {
.name = "dnsmasq",
.type = &ubus_object_type,
.methods = ubus_object_methods,
.n_methods = ARRAY_SIZE(ubus_object_methods),
+ .subscribe_cb = ubus_subscribe_cb,
};
+static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
+{
+ (void)ctx;
+
+ my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
+ notify = obj->has_subscribers;
+}
+
+static void ubus_destroy(struct ubus_context *ubus)
+{
+ // Forces re-initialization when we're reusing the same definitions later on.
+ ubus_object.id = 0;
+ ubus_object_type.id = 0;
+
+ ubus_free(ubus);
+ daemon->ubus = NULL;
+}
+
+static void ubus_disconnect_cb(struct ubus_context *ubus)
+{
+ int ret;
+
+ ret = ubus_reconnect(ubus, NULL);
+ if (ret)
+ {
+ my_syslog(LOG_ERR, _("Cannot reconnect to UBus: %s"), ubus_strerror(ret));
+
+ ubus_destroy(ubus);
+ }
+}
+
+void ubus_init()
+{
+ struct ubus_context *ubus = NULL;
+ int ret = 0;
+
+ ubus = ubus_connect(NULL);
+ if (!ubus)
+ {
+ if (!error_logged)
+ {
+ my_syslog(LOG_ERR, _("Cannot initialize UBus: connection failed"));
+ error_logged = 1;
+ }
+
+ ubus_destroy(ubus);
+ return;
+ }
+
+ ret = ubus_add_object(ubus, &ubus_object);
+ if (ret)
+ {
+ if (!error_logged)
+ {
+ my_syslog(LOG_ERR, _("Cannot add object to UBus: %s"), ubus_strerror(ret));
+ error_logged = 1;
+ }
+ return;
+ }
+
+ ubus->connection_lost = ubus_disconnect_cb;
+ daemon->ubus = ubus;
+ error_logged = 0;
+
+ my_syslog(LOG_INFO, _("Connected to system UBus"));
+}
+
void set_ubus_listeners()
{
+ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
if (!ubus)
- return;
+ {
+ if (!error_logged)
+ {
+ my_syslog(LOG_ERR, _("Cannot set UBus listeners: no connection"));
+ error_logged = 1;
+ }
+ return;
+ }
+
+ error_logged = 0;
poll_listen(ubus->sock.fd, POLLIN);
poll_listen(ubus->sock.fd, POLLERR);
@@ -51,46 +134,57 @@ void set_ubus_listeners()
void check_ubus_listeners()
{
+ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
if (!ubus)
{
- ubus = ubus_connect(NULL);
- if (!ubus)
- return;
- ubus_add_object(ubus, &ubus_object);
+ if (!error_logged)
+ {
+ my_syslog(LOG_ERR, _("Cannot poll UBus listeners: no connection"));
+ error_logged = 1;
+ }
+ return;
}
+ error_logged = 0;
+
if (poll_check(ubus->sock.fd, POLLIN))
ubus_handle_event(ubus);
- if (poll_check(ubus->sock.fd, POLLHUP))
+ if (poll_check(ubus->sock.fd, POLLHUP | POLLERR))
{
- ubus_free(ubus);
- ubus = NULL;
+ my_syslog(LOG_INFO, _("Disconnecting from UBus"));
+
+ ubus_destroy(ubus);
}
}
-
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int i;
- blob_buf_init(&b, 0);
- for(i=0; i < __METRIC_MAX; i++)
+ (void)obj;
+ (void)method;
+ (void)msg;
+
+ blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
+
+ for (i=0; i < __METRIC_MAX; i++)
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
- ubus_send_reply(ctx, req, b.head);
-
- return 0;
+ return ubus_send_reply(ctx, req, b.head);
}
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
{
- if (!ubus || !ubus_object.has_subscribers)
+ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
+ int ret;
+
+ if (!ubus || !notify)
return;
- blob_buf_init(&b, 0);
+ blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
if (mac)
blobmsg_add_string(&b, "mac", mac);
if (ip)
@@ -100,7 +194,9 @@ void ubus_event_bcast(const char *type,
if (interface)
blobmsg_add_string(&b, "interface", interface);
- ubus_notify(ubus, &ubus_object, type, b.head, -1);
+ ret = ubus_notify(ubus, &ubus_object, type, b.head, -1);
+ if (!ret)
+ my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
}

View File

@ -0,0 +1,31 @@
From 05299fdd5a3b6ace43224c7d27d06a57b175639f Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 15 Jul 2019 22:04:20 +0100
Subject: [PATCH 56/57] Fix wrong return code from explore_rrset() with some
errors.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/dnssec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -374,7 +374,7 @@ static int explore_rrset(struct dns_head
int gotkey = 0;
if (!(p = skip_questions(header, plen)))
- return STAT_BOGUS;
+ return 0;
/* look for RRSIGs for this RRset and get pointers to each RR in the set. */
for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount);
@@ -386,7 +386,7 @@ static int explore_rrset(struct dns_head
pstart = p;
if (!(res = extract_name(header, plen, &p, name, 0, 10)))
- return STAT_BOGUS; /* bad packet */
+ return 0; /* bad packet */
GETSHORT(stype, p);
GETSHORT(sclass, p);

View File

@ -0,0 +1,22 @@
From 3052ce208acf602f0163166dcefb7330d537cedb Mon Sep 17 00:00:00 2001
From: Jiri Slaby <jslaby@suse.cz>
Date: Wed, 24 Jul 2019 17:34:48 +0100
Subject: [PATCH 57/57] Fix build after y2038 changes in glib.
SIOCGSTAMP is defined in linux/sockios.h, not asm/sockios.h now.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/dnsmasq.h | 1 +
1 file changed, 1 insertion(+)
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -137,6 +137,7 @@ typedef unsigned long long u64;
#endif
#if defined(HAVE_LINUX_NETWORK)
+#include <linux/sockios.h>
#include <linux/capability.h>
/* There doesn't seem to be a universally-available
userspace header for these. */