Fix massive confusion on server reload

The 2.86 upstream server rewrite severely broke re-reading
of server configuration. It would get everyting right the first
time, but on re-reading /etc/resolv.conf or --servers-file
or setting things with DBUS, the results were just wrong.

This should put things right again.

No fedora bug reference, reported upstream:
https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2022q1/016166.html
This commit is contained in:
Petr Menšík 2022-02-23 15:54:53 +01:00
parent 4cfebfcd18
commit 1c5ebdc65d
2 changed files with 254 additions and 1 deletions

View File

@ -0,0 +1,247 @@
From e816d085585b95c5f27ceaa5ea74d42f943375f7 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 3 Jan 2022 23:32:30 +0000
Subject: [PATCH] Fix massive confusion on server reload.
The 2.86 upstream server rewrite severely broke re-reading
of server configuration. It would get everyting right the first
time, but on re-reading /etc/resolv.conf or --servers-file
or setting things with DBUS, the results were just wrong.
This should put things right again.
---
src/domain-match.c | 154 +++++++++++++++++++++++++--------------------
1 file changed, 85 insertions(+), 69 deletions(-)
diff --git a/src/domain-match.c b/src/domain-match.c
index 3a69aa1..f4fd093 100644
--- a/src/domain-match.c
+++ b/src/domain-match.c
@@ -37,7 +37,7 @@ static void build_server_array(void)
if (serv->flags & SERV_WILDCARD)
daemon->server_has_wildcard = 1;
}
-
+
for (serv = daemon->local_domains; serv; serv = serv->next)
{
count++;
@@ -543,22 +543,35 @@ static int order_qsort(const void *a, const void *b)
return rc;
}
+/* Must be called before add_update_server() to set daemon->servers_tail */
void mark_servers(int flag)
{
- struct server *serv;
+ struct server *serv, **up;
/* mark everything with argument flag */
for (serv = daemon->servers; serv; serv = serv->next)
- if (serv->flags & flag)
- serv->flags |= SERV_MARK;
- else
- serv->flags &= ~SERV_MARK;
-
- for (serv = daemon->local_domains; serv; serv = serv->next)
- if (serv->flags & flag)
- serv->flags |= SERV_MARK;
- else
- serv->flags &= ~SERV_MARK;
+ {
+ if (serv->flags & flag)
+ serv->flags |= SERV_MARK;
+ else
+ serv->flags &= ~SERV_MARK;
+ }
+
+ /* --address etc is different: since they are expected to be
+ 1) numerous and 2) not reloaded often. We just delete
+ and recreate. */
+ if (flag)
+ for (serv = daemon->local_domains, up = &daemon->local_domains; serv; serv = serv->next)
+ {
+ if (serv->flags & flag)
+ {
+ *up = serv->next;
+ free(serv->domain);
+ free(serv);
+ }
+ else
+ up = &serv->next;
+ }
}
void cleanup_servers(void)
@@ -566,7 +579,7 @@ void cleanup_servers(void)
struct server *serv, *tmp, **up;
/* unlink and free anything still marked. */
- for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
+ for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
{
tmp = serv->next;
if (serv->flags & SERV_MARK)
@@ -580,19 +593,6 @@ void cleanup_servers(void)
up = &serv->next;
}
- for (serv = daemon->local_domains, up = &daemon->local_domains; serv; serv = tmp)
- {
- tmp = serv->next;
- if (serv->flags & SERV_MARK)
- {
- *up = serv->next;
- free(serv->domain);
- free(serv);
- }
- else
- up = &serv->next;
- }
-
/* If we're delaying things, we don't call check_servers(), but
reload_servers() may have deleted some servers, rendering the server_array
invalid, so just rebuild that here. Once reload_servers() succeeds,
@@ -630,56 +630,71 @@ int add_update_server(int flags,
if (!alloc_domain)
return 0;
- /* See if there is a suitable candidate, and unmark
- only do this for forwarding servers, not
- address or local, to avoid delays on large numbers. */
+
if (flags & SERV_IS_LOCAL)
- for (serv = daemon->servers; serv; serv = serv->next)
- if ((serv->flags & SERV_MARK) &&
- hostname_isequal(alloc_domain, serv->domain))
- break;
-
- if (serv)
- {
- free(alloc_domain);
- alloc_domain = serv->domain;
- }
- else
{
size_t size;
- if (flags & SERV_IS_LOCAL)
- {
- if (flags & SERV_6ADDR)
- size = sizeof(struct serv_addr6);
- else if (flags & SERV_4ADDR)
- size = sizeof(struct serv_addr4);
- else
- size = sizeof(struct serv_local);
- }
+ if (flags & SERV_6ADDR)
+ size = sizeof(struct serv_addr6);
+ else if (flags & SERV_4ADDR)
+ size = sizeof(struct serv_addr4);
else
- size = sizeof(struct server);
+ size = sizeof(struct serv_local);
if (!(serv = whine_malloc(size)))
{
free(alloc_domain);
return 0;
}
-
- if (flags & SERV_IS_LOCAL)
+
+ serv->next = daemon->local_domains;
+ daemon->local_domains = serv;
+
+ if (flags & SERV_4ADDR)
+ ((struct serv_addr4*)serv)->addr = local_addr->addr4;
+
+ if (flags & SERV_6ADDR)
+ ((struct serv_addr6*)serv)->addr = local_addr->addr6;
+ }
+ else
+ {
+ /* Upstream servers. See if there is a suitable candidate, if so unmark
+ and move to the end of the list, for order. The entry found may already
+ be at the end. */
+ struct server **up, *tmp;
+
+ for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
{
- serv->next = daemon->local_domains;
- daemon->local_domains = serv;
+ tmp = serv->next;
+ if ((serv->flags & SERV_MARK) &&
+ hostname_isequal(alloc_domain, serv->domain))
+ {
+ /* Need to move down? */
+ if (serv->next)
+ {
+ struct server *s;
+ *up = serv->next;
+ for (s = daemon->servers; s->next; s = s->next);
+ s->next = serv;
+ serv->next = NULL;
+ }
+ break;
+ }
+ }
- if (flags & SERV_4ADDR)
- ((struct serv_addr4*)serv)->addr = local_addr->addr4;
-
- if (flags & SERV_6ADDR)
- ((struct serv_addr6*)serv)->addr = local_addr->addr6;
+ if (serv)
+ {
+ free(alloc_domain);
+ alloc_domain = serv->domain;
}
else
{
- struct server *s;
+ if (!(serv = whine_malloc(sizeof(struct server))))
+ {
+ free(alloc_domain);
+ return 0;
+ }
memset(serv, 0, sizeof(struct server));
@@ -688,23 +703,24 @@ int add_update_server(int flags,
daemon->servers = serv;
else
{
+ struct server *s;
for (s = daemon->servers; s->next; s = s->next);
s->next = serv;
}
+ }
#ifdef HAVE_LOOP
- serv->uid = rand32();
+ serv->uid = rand32();
#endif
- if (interface)
- safe_strncpy(serv->interface, interface, sizeof(serv->interface));
- if (addr)
- serv->addr = *addr;
- if (source_addr)
- serv->source_addr = *source_addr;
- }
+ if (interface)
+ safe_strncpy(serv->interface, interface, sizeof(serv->interface));
+ if (addr)
+ serv->addr = *addr;
+ if (source_addr)
+ serv->source_addr = *source_addr;
}
-
+
serv->flags = flags;
serv->domain = alloc_domain;
serv->domain_len = strlen(alloc_domain);
--
2.34.1

View File

@ -20,7 +20,7 @@
Name: dnsmasq
Version: 2.86
Release: 5%{?extraversion:.%{extraversion}}%{?dist}
Release: 6%{?extraversion:.%{extraversion}}%{?dist}
Summary: A lightweight DHCP/caching DNS server
License: GPLv2 or GPLv3
@ -67,6 +67,9 @@ Patch28: dnsmasq-2.87-tcp-strcasecmp.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2024166
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=1f8f78a49b8fd6b2862a3882053b1c6e6e111e5c
Patch29: dnsmasq-2.87-root-log-writeable.patch
# https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2022q1/016166.html
# https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=553c4c99cca173e9964d0edbd0676ed96c30f62b
Patch30: https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=patch;h=553c4c99cca173e9964d0edbd0676ed96c30f62b#/dnsmasq-2.87-resolv.conf-reread.patch
@ -210,6 +213,9 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/%{name}.conf
%{_mandir}/man1/dhcp_*
%changelog
* Wed Feb 23 2022 Petr Menšík <pemensik@redhat.com> - 2.86-6
- Fix errors on server reload
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 2.86-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild