Add --max-tcp-connections option to make this dynamically configurable.

This commit is contained in:
Damian Sawicki
2023-11-04 23:33:28 +00:00
committed by Simon Kelley
parent 24804b7431
commit 416390f996
5 changed files with 39 additions and 11 deletions

View File

@@ -2254,6 +2254,10 @@ example command to query this, using the
utility would be
dig +short chaos txt cachesize.bind
.TP
.B --max-tcp-connections=<number>
The maximum number of concurrent TCP connections. The application forks to
handle each TCP request. The default maximum is 20.
.SH CONFIG FILE
At startup, dnsmasq reads

View File

@@ -15,7 +15,7 @@
*/
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
#define MAX_PROCS 20 /* default max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */

View File

@@ -36,6 +36,7 @@ static void async_event(int pipe, time_t now);
static void fatal_event(struct event_desc *ev, char *msg);
static int read_event(int fd, struct event_desc *evp, char **msg);
static void poll_resolv(int force, int do_reload, time_t now);
static void tcp_init(void);
int main (int argc, char **argv)
{
@@ -415,6 +416,8 @@ int main (int argc, char **argv)
daemon->numrrand = max_fd/3;
/* safe_malloc returns zero'd memory */
daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd));
tcp_init();
}
#ifdef HAVE_INOTIFY
@@ -1043,7 +1046,7 @@ int main (int argc, char **argv)
pid = getpid();
daemon->pipe_to_parent = -1;
for (i = 0; i < MAX_PROCS; i++)
for (i = 0; i < daemon->max_procs; i++)
daemon->tcp_pipes[i] = -1;
#ifdef HAVE_INOTIFY
@@ -1520,7 +1523,7 @@ static void async_event(int pipe, time_t now)
break;
}
else
for (i = 0 ; i < MAX_PROCS; i++)
for (i = 0 ; i < daemon->max_procs; i++)
if (daemon->tcp_pids[i] == p)
daemon->tcp_pids[i] = 0;
break;
@@ -1584,7 +1587,7 @@ static void async_event(int pipe, time_t now)
case EVENT_TERM:
/* Knock all our children on the head. */
for (i = 0; i < MAX_PROCS; i++)
for (i = 0; i < daemon->max_procs; i++)
if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGALRM);
@@ -1761,7 +1764,7 @@ static void set_dns_listeners(void)
poll_listen(rfl->rfd->fd, POLLIN);
/* check to see if we have free tcp process slots. */
for (i = MAX_PROCS - 1; i >= 0; i--)
for (i = daemon->max_procs - 1; i >= 0; i--)
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
break;
@@ -1785,7 +1788,7 @@ static void set_dns_listeners(void)
}
if (!option_bool(OPT_DEBUG))
for (i = 0; i < MAX_PROCS; i++)
for (i = 0; i < daemon->max_procs; i++)
if (daemon->tcp_pipes[i] != -1)
poll_listen(daemon->tcp_pipes[i], POLLIN);
}
@@ -1820,7 +1823,7 @@ static void check_dns_listeners(time_t now)
to free the process slot. Once the child process has gone, poll()
returns POLLHUP, not POLLIN, so have to check for both here. */
if (!option_bool(OPT_DEBUG))
for (i = 0; i < MAX_PROCS; i++)
for (i = 0; i < daemon->max_procs; i++)
if (daemon->tcp_pipes[i] != -1 &&
poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
!cache_recv_insert(now, daemon->tcp_pipes[i]))
@@ -1844,7 +1847,7 @@ static void check_dns_listeners(time_t now)
at least one a poll() time, that we still do.
There may be more waiting connections after
poll() returns then free process slots. */
for (i = MAX_PROCS - 1; i >= 0; i--)
for (i = daemon->max_procs - 1; i >= 0; i--)
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
break;
@@ -2186,3 +2189,9 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
return 0;
}
#endif /* HAVE_DHCP */
void tcp_init(void)
{
daemon->tcp_pids = safe_malloc(daemon->max_procs*sizeof(pid_t));
daemon->tcp_pipes = safe_malloc(daemon->max_procs*sizeof(int));
}

View File

@@ -1252,8 +1252,8 @@ extern struct daemon {
struct server *srv_save; /* Used for resend on DoD */
size_t packet_len; /* " " */
int fd_save; /* " " */
pid_t tcp_pids[MAX_PROCS];
int tcp_pipes[MAX_PROCS];
pid_t *tcp_pids;
int *tcp_pipes;
int pipe_to_parent;
int numrrand;
struct randfd *randomsocks;
@@ -1313,6 +1313,7 @@ extern struct daemon {
/* file for packet dumps. */
int dumpfd;
#endif
int max_procs;
} *daemon;
struct server_details {

View File

@@ -190,6 +190,7 @@ struct myoption {
#define LOPT_FILTER_RR 381
#define LOPT_NO_DHCP6 382
#define LOPT_NO_DHCP4 383
#define LOPT_MAX_PROCS 384
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -384,6 +385,7 @@ static const struct myoption opts[] =
{ "fast-dns-retry", 2, 0, LOPT_FAST_RETRY },
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
{ "no-ident", 0, 0, LOPT_NO_IDENT },
{ "max-tcp-connections", 1, 0, LOPT_MAX_PROCS },
{ NULL, 0, 0, 0 }
};
@@ -585,6 +587,7 @@ static struct {
{ LOPT_NORR, OPT_NORR, NULL, gettext_noop("Suppress round-robin ordering of DNS records."), NULL },
{ LOPT_NO_IDENT, OPT_NO_IDENT, NULL, gettext_noop("Do not add CHAOS TXT records."), NULL },
{ LOPT_CACHE_RR, ARG_DUP, "<RR-type>", gettext_noop("Cache this DNS resource record type."), NULL },
{ LOPT_MAX_PROCS, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent tcp connections."), NULL },
{ 0, 0, NULL, NULL, NULL }
};
@@ -5314,6 +5317,16 @@ err:
}
#endif
case LOPT_MAX_PROCS: /* --max-tcp-connections */
{
int max_procs;
/* Don't accept numbers less than 1. */
if (!atoi_check(arg, &max_procs) || max_procs < 1)
ret_err(gen_err);
daemon->max_procs = max_procs;
break;
}
default:
ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"));
@@ -5841,6 +5854,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
daemon->soa_expiry = SOA_EXPIRY;
daemon->randport_limit = 1;
daemon->host_index = SRC_AH;
daemon->max_procs = MAX_PROCS;
/* See comment above make_servers(). Optimises server-read code. */
mark_servers(0);