Add the flag --max-tcp-connections overwriting the former MAX_PROCS constant limiting the number of concurrent TCP requests handled. --- man/dnsmasq.8 | 4 ++++ src/config.h | 2 +- src/dnsmasq.c | 23 ++++++++++++++++------- src/dnsmasq.h | 5 +++-- src/option.c | 16 +++++++++++++++- 5 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 30429df..6d37360 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -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 diff --git a/src/config.h b/src/config.h index 88cf72e..cc1c465 100644 --- a/src/config.h +++ b/src/config.h @@ -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 */ diff --git a/src/dnsmasq.c b/src/dnsmasq.c index bc6644c..112dbe5 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -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)); +} diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 2f95c12..67c083b 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -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 { diff --git a/src/option.c b/src/option.c index 286f06b..9423582 100644 --- a/src/option.c +++ b/src/option.c @@ -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 } }; @@ -5313,7 +5316,17 @@ err: break; } #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); -- 2.42.0.655.g421f12c284-goog _______________________________________________ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss