summaryrefslogtreecommitdiff
path: root/dnsmasq-2.79-server-domain-rh1919894.patch
diff options
context:
space:
mode:
Diffstat (limited to 'dnsmasq-2.79-server-domain-rh1919894.patch')
-rw-r--r--dnsmasq-2.79-server-domain-rh1919894.patch471
1 files changed, 471 insertions, 0 deletions
diff --git a/dnsmasq-2.79-server-domain-rh1919894.patch b/dnsmasq-2.79-server-domain-rh1919894.patch
new file mode 100644
index 0000000..b8869a8
--- /dev/null
+++ b/dnsmasq-2.79-server-domain-rh1919894.patch
@@ -0,0 +1,471 @@
+From 5747d7b3dffdcd45d4410bb380e466818734cb27 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
+Date: Mon, 19 Apr 2021 13:56:23 +0200
+Subject: [PATCH] Use load-balancing also for --server=/domains/
+
+Do not (yet) move servers to server_domain structure. Instead use
+separate server_domains to store just last_server and requests count and
+time.
+
+Introduces domain information duplicity, but minimizes required changes
+to daemon->servers usage.
+
+Optimize server domain record
+
+Set pointer to domain record when struct server is created. When
+searching for domain pointer, use this pointer to make it quick.
+---
+ src/dnsmasq.h | 18 +++++++--
+ src/forward.c | 52 ++++++++++++++++----------
+ src/network.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++----
+ src/option.c | 5 +++
+ 4 files changed, 146 insertions(+), 30 deletions(-)
+
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index 1e21005..b6dcc50 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -559,6 +559,17 @@ struct randfd_list {
+ struct randfd_list *next;
+ };
+
++/* contains domain specific set of servers.
++ * If domain is NULL, just normal servers. */
++struct server_domain {
++ char *domain;
++ struct server *last_server;
++ time_t forwardtime;
++ int forwardcount;
++ unsigned int flags; /* server.flags alternative */
++ struct server_domain *next;
++};
++
+ struct server {
+ union mysockaddr addr, source_addr;
+ char interface[IF_NAMESIZE+1];
+@@ -571,6 +582,7 @@ struct server {
+ #ifdef HAVE_LOOP
+ u32 uid;
+ #endif
++ struct server_domain *serv_domain;
+ struct server *next;
+ };
+
+@@ -1053,6 +1065,7 @@ extern struct daemon {
+ struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
+ struct bogus_addr *bogus_addr, *ignore_addr;
+ struct server *servers;
++ struct server_domain *server_domains;
+ struct ipsets *ipsets;
+ int log_fac; /* log facility */
+ char *log_file; /* optional log file */
+@@ -1121,9 +1134,6 @@ extern struct daemon {
+ struct serverfd *sfds;
+ struct irec *interfaces;
+ struct listener *listeners;
+- struct server *last_server;
+- time_t forwardtime;
+- int forwardcount;
+ struct server *srv_save; /* Used for resend on DoD */
+ size_t packet_len; /* " " */
+ int fd_save; /* " " */
+@@ -1394,6 +1404,8 @@ int label_exception(int index, int family, union all_addr *addr);
+ int fix_fd(int fd);
+ int tcp_interface(int fd, int af);
+ int set_ipv6pktinfo(int fd);
++struct server_domain *server_domain_find_domain(const char *domain);
++struct server_domain *server_domain_new(struct server *serv);
+ #ifdef HAVE_DHCP6
+ void join_multicast(int dienow);
+ #endif
+diff --git a/src/forward.c b/src/forward.c
+index 9322b6a..b09dc96 100644
+--- a/src/forward.c
++++ b/src/forward.c
+@@ -107,7 +107,8 @@ int send_from(int fd, int nowild, char *packet, size_t len,
+ }
+
+ static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned int qtype,
+- char *qdomain, int *type, char **domain, int *norebind)
++ char *qdomain, int *type, char **domain, int *norebind,
++ struct server_domain **serv_domain)
+
+ {
+ /* If the query ends in the domain in one of our servers, set
+@@ -120,6 +121,9 @@ static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned
+ unsigned int flags = 0;
+ static union all_addr zero;
+
++ if (serv_domain)
++ *serv_domain = NULL;
++
+ for (serv = daemon->servers; serv; serv=serv->next)
+ if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
+ continue;
+@@ -187,6 +191,8 @@ static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned
+ {
+ *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
+ *domain = serv->domain;
++ if (serv_domain)
++ *serv_domain = serv->serv_domain;
+ matchlen = domainlen;
+ if (serv->flags & SERV_NO_ADDR)
+ flags = F_NXDOMAIN;
+@@ -243,6 +249,8 @@ static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned
+ *type = 0; /* use normal servers for this domain */
+ *domain = NULL;
+ }
++ if (serv_domain && !*serv_domain)
++ *serv_domain = server_domain_find_domain(*domain);
+ return flags;
+ }
+
+@@ -304,6 +312,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
+ unsigned int flags = 0;
+ unsigned int fwd_flags = 0;
+ struct server *start = NULL;
++ struct server_domain *sd = NULL;
+ void *hash = hash_questions(header, plen, daemon->namebuff);
+ #ifdef HAVE_DNSSEC
+ int do_dnssec = 0;
+@@ -422,8 +431,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
+ forward->sentto->failed_queries++;
+ if (!option_bool(OPT_ORDER) && old_src)
+ {
++ sd = forward->sentto->serv_domain;
+ forward->forwardall = 1;
+- daemon->last_server = NULL;
++ if (sd)
++ sd->last_server = NULL;
+ }
+ type = forward->sentto->flags & SERV_TYPE;
+ #ifdef HAVE_DNSSEC
+@@ -439,8 +450,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
+ /* new query */
+
+ if (gotname)
+- flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
+-
++ flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind, &sd);
++
+ #ifdef HAVE_DNSSEC
+ do_dnssec = type & SERV_DO_DNSSEC;
+ #endif
+@@ -482,18 +493,18 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
+ always try all the available servers,
+ otherwise, use the one last known to work. */
+
+- if (type == 0)
++ if (sd)
+ {
+ if (option_bool(OPT_ORDER))
+ start = daemon->servers;
+- else if (!(start = daemon->last_server) ||
+- daemon->forwardcount++ > FORWARD_TEST ||
+- difftime(now, daemon->forwardtime) > FORWARD_TIME)
++ else if (!(start = sd->last_server) ||
++ sd->forwardcount++ > FORWARD_TEST ||
++ difftime(now, sd->forwardtime) > FORWARD_TIME)
+ {
+ start = daemon->servers;
+ forward->forwardall = 1;
+- daemon->forwardcount = 0;
+- daemon->forwardtime = now;
++ sd->forwardcount = 0;
++ sd->forwardtime = now;
+ }
+ }
+ else
+@@ -844,6 +855,7 @@ void reply_query(int fd, time_t now)
+ size_t nn;
+ struct server *server;
+ void *hash;
++ struct server_domain *sd;
+
+ /* packet buffer overwritten */
+ daemon->srv_save = NULL;
+@@ -968,7 +980,8 @@ void reply_query(int fd, time_t now)
+ }
+
+ server = forward->sentto;
+- if ((forward->sentto->flags & SERV_TYPE) == 0)
++ sd = server->serv_domain;
++ if (sd)
+ {
+ if (RCODE(header) == REFUSED)
+ server = NULL;
+@@ -986,7 +999,7 @@ void reply_query(int fd, time_t now)
+ }
+ }
+ if (!option_bool(OPT_ALL_SERVERS))
+- daemon->last_server = server;
++ sd->last_server = server;
+ }
+
+ /* We tried resending to this server with a smaller maximum size and got an answer.
+@@ -1093,7 +1106,7 @@ void reply_query(int fd, time_t now)
+ /* Find server to forward to. This will normally be the
+ same as for the original query, but may be another if
+ servers for domains are involved. */
+- if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
++ if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL, &sd) == 0)
+ {
+ struct server *start, *new_server = NULL;
+ start = server = forward->sentto;
+@@ -1664,7 +1677,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
+ /* Find server to forward to. This will normally be the
+ same as for the original query, but may be another if
+ servers for domains are involved. */
+- if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
++ if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL, NULL) != 0)
+ {
+ new_status = STAT_ABANDONED;
+ break;
+@@ -1944,12 +1957,13 @@ unsigned char *tcp_request(int confd, time_t now,
+ union all_addr *addrp = NULL;
+ int type = SERV_DO_DNSSEC;
+ char *domain = NULL;
++ struct server_domain *sd = NULL;
+ unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
+
+ size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet, &cacheable);
+
+ if (gotname)
+- flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
++ flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind, &sd);
+
+ #ifdef HAVE_DNSSEC
+ if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
+@@ -1970,10 +1984,10 @@ unsigned char *tcp_request(int confd, time_t now,
+
+ type &= ~SERV_DO_DNSSEC;
+
+- if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
++ if (!sd || option_bool(OPT_ORDER) || !sd->last_server)
+ last_server = daemon->servers;
+ else
+- last_server = daemon->last_server;
++ last_server = sd->last_server;
+
+ if (!flags && last_server)
+ {
+@@ -2567,9 +2581,7 @@ void server_gone(struct server *server)
+ if (daemon->randomsocks[i].refcount != 0 && daemon->randomsocks[i].serv == server)
+ daemon->randomsocks[i].serv = NULL;
+
+- if (daemon->last_server == server)
+- daemon->last_server = NULL;
+-
++ /* last_server cleared by server_domains_cleanup */
+ if (daemon->srv_save == server)
+ daemon->srv_save = NULL;
+ }
+diff --git a/src/network.c b/src/network.c
+index 3600250..1fa81ff 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -1537,6 +1537,29 @@ void cleanup_servers(void)
+ #endif
+ }
+
++static void server_domains_cleanup(void)
++{
++ struct server_domain *sd, *tmp, **up;
++
++ /* unlink and free anything still marked. */
++ for (up = &daemon->server_domains, sd=*up; sd; sd = tmp)
++ {
++ tmp = sd->next;
++ if (sd->flags & SERV_MARK)
++ {
++ *up = sd->next;
++ if (sd->domain)
++ free(sd->domain);
++ free(sd);
++ }
++ else {
++ up = &sd->next;
++ if (sd->last_server && (sd->last_server->flags & SERV_MARK))
++ sd->last_server = NULL;
++ }
++ }
++}
++
+ void add_update_server(int flags,
+ union mysockaddr *addr,
+ union mysockaddr *source_addr,
+@@ -1616,10 +1639,72 @@ void add_update_server(int flags,
+ }
+ }
+
++static const char *server_get_domain(const struct server *serv)
++{
++ const char *domain = serv->domain;
++
++ if (serv->flags & SERV_HAS_DOMAIN)
++ /* .example.com is valid */
++ while (*domain == '.')
++ domain++;
++
++ return domain;
++}
++
++struct server_domain *server_domain_find_domain(const char *domain)
++{
++ struct server_domain *sd;
++ for (sd = daemon->server_domains; sd; sd = sd->next)
++ if ((!domain && sd->domain == domain) || (domain && sd->domain && hostname_isequal(domain, sd->domain)))
++ return sd;
++ return NULL;
++}
++
++/**< Test structure has already set domain pointer.
++ *
++ * If not, create a new record. */
++struct server_domain *server_domain_new(struct server *serv)
++{
++ struct server_domain *sd;
++
++ if ((sd = whine_malloc(sizeof(struct server_domain))))
++ {
++ const char *domain = server_get_domain(serv);
++
++ /* Ensure all serv->domain values have own record in server_domain.
++ * Add a new record. */
++ if (domain)
++ {
++ size_t len = strlen(domain)+1;
++ sd->domain = whine_malloc(len);
++ if (sd->domain)
++ memcpy(sd->domain, domain, len);
++ }
++ sd->next = daemon->server_domains;
++ serv->serv_domain = sd;
++ daemon->server_domains = sd;
++ }
++ return sd;
++}
++
++/**< Test structure has already set domain pointer.
++ *
++ * If not, create a new record. */
++static void server_domain_check(struct server *serv)
++{
++ struct server_domain *sd = serv->serv_domain;
++
++ if (sd)
++ sd->flags &= (~SERV_MARK); /* found domain, mark active */
++ else
++ server_domain_new(serv);
++}
++
+ void check_servers(void)
+ {
+ struct irec *iface;
+ struct server *serv;
++ struct server_domain *sd;
+ struct serverfd *sfd, *tmp, **up;
+ int port = 0, count;
+ int locals = 0;
+@@ -1632,10 +1717,14 @@ void check_servers(void)
+ for (sfd = daemon->sfds; sfd; sfd = sfd->next)
+ sfd->used = sfd->preallocated;
+
++ for (sd = daemon->server_domains; sd; sd = sd->next)
++ sd->flags |= SERV_MARK;
++
+ for (count = 0, serv = daemon->servers; serv; serv = serv->next)
+ {
+ if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
+ {
++
+ /* Init edns_pktsz for newly created server records. */
+ if (serv->edns_pktsz == 0)
+ serv->edns_pktsz = daemon->edns_pktsz;
+@@ -1651,12 +1740,8 @@ void check_servers(void)
+ if (serv->flags & SERV_HAS_DOMAIN)
+ {
+ struct ds_config *ds;
+- char *domain = serv->domain;
+-
+- /* .example.com is valid */
+- while (*domain == '.')
+- domain++;
+-
++ const char *domain = server_get_domain(serv);
++
+ for (ds = daemon->ds; ds; ds = ds->next)
+ if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
+ break;
+@@ -1666,7 +1751,6 @@ void check_servers(void)
+ }
+ }
+ #endif
+-
+ port = prettyprint_addr(&serv->addr, daemon->namebuff);
+
+ /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
+@@ -1701,6 +1785,8 @@ void check_servers(void)
+
+ if (serv->sfd)
+ serv->sfd->used = 1;
++
++ server_domain_check(serv);
+ }
+
+ if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
+@@ -1763,6 +1849,7 @@ void check_servers(void)
+ up = &sfd->next;
+ }
+
++ server_domains_cleanup();
+ cleanup_servers();
+ }
+
+diff --git a/src/option.c b/src/option.c
+index 6de5914..e4e3182 100644
+--- a/src/option.c
++++ b/src/option.c
+@@ -928,6 +928,7 @@ static struct server *add_rev4(struct in_addr addr, int msize)
+ p += sprintf(p, "in-addr.arpa");
+
+ serv->flags = SERV_HAS_DOMAIN;
++ server_domain_new(serv);
+ serv->next = daemon->servers;
+ daemon->servers = serv;
+
+@@ -952,6 +953,7 @@ static struct server *add_rev6(struct in6_addr *addr, int msize)
+ p += sprintf(p, "ip6.arpa");
+
+ serv->flags = SERV_HAS_DOMAIN;
++ server_domain_new(serv);
+ serv->next = daemon->servers;
+ daemon->servers = serv;
+
+@@ -2292,6 +2294,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
+ memset(serv, 0, sizeof(struct server));
+ serv->domain = d;
+ serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
++ server_domain_new(serv);
+ serv->next = daemon->servers;
+ daemon->servers = serv;
+ }
+@@ -2335,6 +2338,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
+ memset(serv, 0, sizeof(struct server));
+ serv->domain = d;
+ serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
++ server_domain_new(serv);
+ serv->next = daemon->servers;
+ daemon->servers = serv;
+ }
+@@ -2587,6 +2591,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
+ newlist = serv;
+ serv->domain = domain;
+ serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
++ server_domain_new(serv);
+ arg = end;
+ if (rebind)
+ break;
+--
+2.34.1
+