diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 10d25c1..2023cfb 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -140,6 +140,9 @@ int main (int argc, char **argv) /* one char flag per possible RR in answer section (may get extended). */ daemon->rr_status_sz = 64; daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * daemon->rr_status_sz); + /* Increase TCP process slots by half, and reserve the extra for validation-to-tcp use only. */ + daemon->dnssec_tcp_slot_reserved = daemon->max_procs/2; + daemon->max_procs += daemon->dnssec_tcp_slot_reserved; } #endif @@ -427,7 +430,8 @@ int main (int argc, char **argv) daemon->tcp_pids = safe_malloc(daemon->max_procs*sizeof(pid_t)); daemon->tcp_pipes = safe_malloc(daemon->max_procs*sizeof(int)); - + daemon->tcp_type = safe_malloc(daemon->max_procs); + for (i = 0; i < daemon->max_procs; i++) daemon->tcp_pipes[i] = -1; } @@ -1652,7 +1656,11 @@ static void async_event(int pipe, time_t now) /* tcp_pipes == -1 && tcp_pids == 0 required to free slot */ if (daemon->tcp_pipes[i] == -1) - daemon->metrics[METRIC_TCP_CONNECTIONS]--; + { + if (daemon->tcp_type[i]) + daemon->dnssec_tcp_slot_reserved++; + daemon->metrics[METRIC_TCP_CONNECTIONS]--; + } } break; @@ -1888,7 +1896,7 @@ static void set_dns_listeners(void) struct serverfd *serverfdp; struct listener *listener; struct randfd_list *rfl; - int i; + int i, j; for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) poll_listen(serverfdp->fd, POLLIN); @@ -1902,8 +1910,8 @@ static void set_dns_listeners(void) poll_listen(rfl->rfd->fd, POLLIN); /* check to see if we have free tcp process slots. */ - for (i = daemon->max_procs - 1; i >= 0; i--) - if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) + for (j = 0, i = daemon->max_procs - 1; i >= 0; i--) + if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1 && ++j > daemon->dnssec_tcp_slot_reserved) break; for (listener = daemon->listeners; listener; listener = listener->next) @@ -1930,7 +1938,7 @@ static void check_dns_listeners(time_t now) struct serverfd *serverfdp; struct listener *listener; struct randfd_list *rfl; - int i; + int i, j; /* Note that handling events here can create or destroy fds and render the result of the last poll() call invalid. Once @@ -1955,7 +1963,11 @@ static void check_dns_listeners(time_t now) daemon->tcp_pipes[i] = -1; /* tcp_pipes == -1 && tcp_pids == 0 required to free slot */ if (daemon->tcp_pids[i] == 0) - daemon->metrics[METRIC_TCP_CONNECTIONS]--; + { + daemon->metrics[METRIC_TCP_CONNECTIONS]--; + if (daemon->tcp_type[i]) + daemon->dnssec_tcp_slot_reserved++; + } } return; } @@ -1995,8 +2007,8 @@ 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 = daemon->max_procs - 1; i >= 0; i--) - if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) + for (j = 0,i = daemon->max_procs - 1; i >= 0; i--) + if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1 && ++j > daemon->dnssec_tcp_slot_reserved) break; if (i >= 0) @@ -2165,6 +2177,7 @@ static void do_tcp_connection(struct listener *listener, time_t now, int slot) daemon->tcp_pids[slot] = p; daemon->tcp_pipes[slot] = pipefd[0]; + daemon->tcp_type[slot] = 0; daemon->metrics[METRIC_TCP_CONNECTIONS]++; if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used) daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS]; @@ -2306,6 +2319,8 @@ int swap_to_tcp(struct frec *forward, time_t now, int status, struct dns_header /* i holds index of free slot */ daemon->tcp_pids[i] = p; daemon->tcp_pipes[i] = pipefd[0]; + daemon->tcp_type[i] = 1; + daemon->dnssec_tcp_slot_reserved--; daemon->metrics[METRIC_TCP_CONNECTIONS]++; if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used) daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS]; diff --git a/src/dnsmasq.h b/src/dnsmasq.h index ecff18d..5a1527a 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1296,6 +1296,7 @@ extern struct daemon { int fd_save; /* " " */ pid_t *tcp_pids; int *tcp_pipes; + char *tcp_type; int pipe_to_parent; int numrrand; struct randfd *randomsocks; @@ -1355,7 +1356,7 @@ extern struct daemon { /* file for packet dumps. */ int dumpfd; #endif - int max_procs; + int max_procs, dnssec_tcp_slot_reserved; uint max_procs_used; } *daemon;