248 lines
6.4 KiB
Diff
248 lines
6.4 KiB
Diff
|
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
|
||
|
|