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

Reply via email to