From ea28d0ef8a4451cb3b95ca71b7081cf2bbefc2e0 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Fri, 26 Mar 2021 22:02:04 +0000 Subject: [PATCH] Scale the DNS random scket pool on the value of dns-forward-max. --- CHANGELOG | 3 +++ src/config.h | 1 - src/dnsmasq.c | 14 +++++++++++--- src/dnsmasq.h | 3 ++- src/forward.c | 10 +++++----- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6072921..d45ef1f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -62,6 +62,9 @@ version 2.85 behaviour can be restored using the min-port and max-port config switches should that be a concern. + Scale the size of the DNS random-port pool based on the + value of the --dns-forward-max configuration. + version 2.84 Fix a problem, introduced in 2.83, which could see DNS replies diff --git a/src/config.h b/src/config.h index 9f69ce3..8c41943 100644 --- a/src/config.h +++ b/src/config.h @@ -29,7 +29,6 @@ #define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */ #define SERVERS_LOGGED 30 /* Only log this many servers when logging state */ #define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */ -#define RANDOM_SOCKS 64 /* max simultaneous random ports */ #define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */ #define CACHESIZ 150 /* default cache size */ #define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */ diff --git a/src/dnsmasq.c b/src/dnsmasq.c index fa9ae15..256d2bc 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -399,6 +399,14 @@ int main (int argc, char **argv) cache_init(); blockdata_init(); hash_questions_init(); + + /* Scale random socket pool by ftabsize, but + limit it based on available fds. */ + daemon->numrrand = daemon->ftabsize/2; + if (daemon->numrrand > max_fd/3) + daemon->numrrand = max_fd/3; + /* safe_malloc returns zero'd memory */ + daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd)); } #ifdef HAVE_INOTIFY @@ -987,7 +995,7 @@ int main (int argc, char **argv) a single file will be sent to may clients (the file only needs one fd). */ - max_fd -= 30; /* use other than TFTP */ + max_fd -= 30 + daemon->numrrand; /* use other than TFTP */ if (max_fd < 0) max_fd = 5; @@ -1700,7 +1708,7 @@ static int set_dns_listeners(time_t now) for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) poll_listen(serverfdp->fd, POLLIN); - for (i = 0; i < RANDOM_SOCKS; i++) + for (i = 0; i < daemon->numrrand; i++) if (daemon->randomsocks[i].refcount != 0) poll_listen(daemon->randomsocks[i].fd, POLLIN); @@ -1752,7 +1760,7 @@ static void check_dns_listeners(time_t now) if (poll_check(serverfdp->fd, POLLIN)) reply_query(serverfdp->fd, now); - for (i = 0; i < RANDOM_SOCKS; i++) + for (i = 0; i < daemon->numrrand; i++) if (daemon->randomsocks[i].refcount != 0 && poll_check(daemon->randomsocks[i].fd, POLLIN)) reply_query(daemon->randomsocks[i].fd, now); diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 47c7bb8..1e21005 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1130,7 +1130,8 @@ extern struct daemon { pid_t tcp_pids[MAX_PROCS]; int tcp_pipes[MAX_PROCS]; int pipe_to_parent; - struct randfd randomsocks[RANDOM_SOCKS]; + int numrrand; + struct randfd *randomsocks; struct randfd_list *rfl_spare, *rfl_poll; int v6pktinfo; struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */ diff --git a/src/forward.c b/src/forward.c index c691b9b..1ce91a2 100644 --- a/src/forward.c +++ b/src/forward.c @@ -2218,7 +2218,7 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv) /* limit the number of sockets we have open to avoid starvation of (eg) TFTP. Once we have a reasonable number, randomness should be OK */ - for (i = 0; i < RANDOM_SOCKS; i++) + for (i = 0; i < daemon->numrrand; i++) if (daemon->randomsocks[i].refcount == 0) { if ((fd = random_sock(serv)) != -1) @@ -2233,9 +2233,9 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv) /* No free ones or cannot get new socket, grab an existing one */ if (!rfd) - for (j = 0; j < RANDOM_SOCKS; j++) + for (j = 0; j < daemon->numrrand; j++) { - i = (j + finger) % RANDOM_SOCKS; + i = (j + finger) % daemon->numrrand; if (daemon->randomsocks[i].refcount != 0 && server_isequal(serv, daemon->randomsocks[i].serv) && daemon->randomsocks[i].refcount != 0xfffe) @@ -2247,7 +2247,7 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv) } } - if (j == RANDOM_SOCKS) + if (j == daemon->numrrand) { struct randfd_list *rfl_poll; @@ -2538,7 +2538,7 @@ void server_gone(struct server *server) /* If any random socket refers to this server, NULL the reference. No more references to the socket will be created in the future. */ - for (i = 0; i < RANDOM_SOCKS; i++) + for (i = 0; i < daemon->numrrand; i++) if (daemon->randomsocks[i].refcount != 0 && daemon->randomsocks[i].serv == server) daemon->randomsocks[i].serv = NULL;