diff --git a/dnsmasq-2.87-resolv.conf-reread.patch b/dnsmasq-2.87-resolv.conf-reread.patch new file mode 100644 index 0000000..129de93 --- /dev/null +++ b/dnsmasq-2.87-resolv.conf-reread.patch @@ -0,0 +1,247 @@ +From e816d085585b95c5f27ceaa5ea74d42f943375f7 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +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 + diff --git a/dnsmasq.spec b/dnsmasq.spec index af72839..bf6163f 100644 --- a/dnsmasq.spec +++ b/dnsmasq.spec @@ -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 - 2.86-6 +- Fix errors on server reload + * Thu Jan 20 2022 Fedora Release Engineering - 2.86-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild