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 utility would be
dig +short chaos txt cachesize.bind 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 .SH CONFIG FILE
At startup, dnsmasq reads At startup, dnsmasq reads

View File

@@ -15,7 +15,7 @@
*/ */
#define FTABSIZ 150 /* max number of outstanding requests (default) */ #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 CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */ #define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */ #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 void fatal_event(struct event_desc *ev, char *msg);
static int read_event(int fd, struct event_desc *evp, 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 poll_resolv(int force, int do_reload, time_t now);
static void tcp_init(void);
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
@@ -415,6 +416,8 @@ int main (int argc, char **argv)
daemon->numrrand = max_fd/3; daemon->numrrand = max_fd/3;
/* safe_malloc returns zero'd memory */ /* safe_malloc returns zero'd memory */
daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd)); daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd));
tcp_init();
} }
#ifdef HAVE_INOTIFY #ifdef HAVE_INOTIFY
@@ -1043,7 +1046,7 @@ int main (int argc, char **argv)
pid = getpid(); pid = getpid();
daemon->pipe_to_parent = -1; 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; daemon->tcp_pipes[i] = -1;
#ifdef HAVE_INOTIFY #ifdef HAVE_INOTIFY
@@ -1520,7 +1523,7 @@ static void async_event(int pipe, time_t now)
break; break;
} }
else else
for (i = 0 ; i < MAX_PROCS; i++) for (i = 0 ; i < daemon->max_procs; i++)
if (daemon->tcp_pids[i] == p) if (daemon->tcp_pids[i] == p)
daemon->tcp_pids[i] = 0; daemon->tcp_pids[i] = 0;
break; break;
@@ -1584,7 +1587,7 @@ static void async_event(int pipe, time_t now)
case EVENT_TERM: case EVENT_TERM:
/* Knock all our children on the head. */ /* 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) if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGALRM); kill(daemon->tcp_pids[i], SIGALRM);
@@ -1761,7 +1764,7 @@ static void set_dns_listeners(void)
poll_listen(rfl->rfd->fd, POLLIN); poll_listen(rfl->rfd->fd, POLLIN);
/* check to see if we have free tcp process slots. */ /* 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) if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
break; break;
@@ -1785,7 +1788,7 @@ static void set_dns_listeners(void)
} }
if (!option_bool(OPT_DEBUG)) 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) if (daemon->tcp_pipes[i] != -1)
poll_listen(daemon->tcp_pipes[i], POLLIN); 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() to free the process slot. Once the child process has gone, poll()
returns POLLHUP, not POLLIN, so have to check for both here. */ returns POLLHUP, not POLLIN, so have to check for both here. */
if (!option_bool(OPT_DEBUG)) 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 && if (daemon->tcp_pipes[i] != -1 &&
poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) && poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
!cache_recv_insert(now, daemon->tcp_pipes[i])) !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. at least one a poll() time, that we still do.
There may be more waiting connections after There may be more waiting connections after
poll() returns then free process slots. */ 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) if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
break; break;
@@ -2186,3 +2189,9 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
return 0; return 0;
} }
#endif /* HAVE_DHCP */ #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 */ struct server *srv_save; /* Used for resend on DoD */
size_t packet_len; /* " " */ size_t packet_len; /* " " */
int fd_save; /* " " */ int fd_save; /* " " */
pid_t tcp_pids[MAX_PROCS]; pid_t *tcp_pids;
int tcp_pipes[MAX_PROCS]; int *tcp_pipes;
int pipe_to_parent; int pipe_to_parent;
int numrrand; int numrrand;
struct randfd *randomsocks; struct randfd *randomsocks;
@@ -1313,6 +1313,7 @@ extern struct daemon {
/* file for packet dumps. */ /* file for packet dumps. */
int dumpfd; int dumpfd;
#endif #endif
int max_procs;
} *daemon; } *daemon;
struct server_details { struct server_details {

View File

@@ -190,6 +190,7 @@ struct myoption {
#define LOPT_FILTER_RR 381 #define LOPT_FILTER_RR 381
#define LOPT_NO_DHCP6 382 #define LOPT_NO_DHCP6 382
#define LOPT_NO_DHCP4 383 #define LOPT_NO_DHCP4 383
#define LOPT_MAX_PROCS 384
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -384,6 +385,7 @@ static const struct myoption opts[] =
{ "fast-dns-retry", 2, 0, LOPT_FAST_RETRY }, { "fast-dns-retry", 2, 0, LOPT_FAST_RETRY },
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE }, { "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
{ "no-ident", 0, 0, LOPT_NO_IDENT }, { "no-ident", 0, 0, LOPT_NO_IDENT },
{ "max-tcp-connections", 1, 0, LOPT_MAX_PROCS },
{ NULL, 0, 0, 0 } { 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_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_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_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 } { 0, 0, NULL, NULL, NULL }
}; };
@@ -5313,7 +5316,17 @@ err:
break; break;
} }
#endif #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: default:
ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)")); 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->soa_expiry = SOA_EXPIRY;
daemon->randport_limit = 1; daemon->randport_limit = 1;
daemon->host_index = SRC_AH; daemon->host_index = SRC_AH;
daemon->max_procs = MAX_PROCS;
/* See comment above make_servers(). Optimises server-read code. */ /* See comment above make_servers(). Optimises server-read code. */
mark_servers(0); mark_servers(0);