From 92b1d573ebbecb15eb49c476a200519c72d6b340 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 31 Jan 2013 22:52:39 +0100 Subject: [PATCH] set a maximum number of clients --- src/config.c | 1 + src/main.c | 41 ++++++++++++++++++++++++++++++----------- src/sample.config | 4 ++++ src/vpn.h | 1 + 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/config.c b/src/config.c index a67b758a..14d844e5 100644 --- a/src/config.c +++ b/src/config.c @@ -128,6 +128,7 @@ unsigned j; READ_NUMERIC("cookie-validity", config->cookie_validity, 1); READ_NUMERIC("auth-timeout", config->auth_timeout, 0); READ_STRING("cookie-db", config->db_file, 1); + READ_NUMERIC("max-clients", config->max_clients, 0); val = optionGetValue(pov, "run-as-user"); \ if (val != NULL && val->valType == OPARG_TYPE_STRING) { diff --git a/src/main.c b/src/main.c index 84beb98f..367539db 100644 --- a/src/main.c +++ b/src/main.c @@ -315,6 +315,19 @@ static void kill_children(struct proc_list_st* clist) } } +static void remove_proc(struct proc_list_st *ctmp) +{ + /* close the intercomm fd */ + if (ctmp->fd >= 0) + close(ctmp->fd); + ctmp->fd = -1; + + ctmp->pid = -1; + if (ctmp->lease) + ctmp->lease->in_use = 0; + list_del(&ctmp->list); +} + static void handle_term(int signo) { /* kill all children */ @@ -338,6 +351,7 @@ int main(int argc, char** argv) int cmd_fd[2]; struct worker_st ws; struct cfg_st config; + unsigned active_clients = 0; INIT_LIST_HEAD(&clist.list); tun_st_init(&tun); @@ -461,7 +475,7 @@ int main(int argc, char** argv) } tv.tv_usec = 0; - tv.tv_sec = 5; + tv.tv_sec = 10; ret = select(n + 1, &rd, NULL, NULL, &tv); if (ret == -1 && errno == EINTR) continue; @@ -485,12 +499,19 @@ int main(int argc, char** argv) strerror(errno)); continue; } + + if (config.max_clients > 0 && active_clients > config.max_clients) { + close(fd); + syslog(LOG_INFO, "Reached maximum client limit (active: %u)", active_clients); + break; + } /* Create a command socket */ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, cmd_fd); if (ret < 0) { syslog(LOG_ERR, "Error creating command socket"); - exit(1); + close(fd); + break; } pid = fork(); @@ -529,6 +550,7 @@ fork_failed: ctmp->pid = pid; ctmp->fd = cmd_fd[0]; list_add(&(ctmp->list), &(clist.list)); + active_clients++; } close(cmd_fd[1]); close(fd); @@ -542,15 +564,12 @@ fork_failed: if (FD_ISSET(ctmp->fd, &rd)) { ret = handle_commands(&config, &tun, ctmp); if (ret < 0) { - if (ctmp->fd >= 0) - close(ctmp->fd); - ctmp->fd = -1; - - if (ret == -2) kill(ctmp->pid, SIGTERM); - ctmp->pid = -1; - if (ctmp->lease) - ctmp->lease->in_use = 0; - list_del(&ctmp->list); + if (ret == -2) { + /* received a bad command from worker */ + kill(ctmp->pid, SIGTERM); + } + remove_proc(ctmp); + active_clients--; } } } diff --git a/src/sample.config b/src/sample.config index bdf490c2..532447b1 100644 --- a/src/sample.config +++ b/src/sample.config @@ -3,6 +3,10 @@ # Options: certificate, pam. auth = "pam" +# Limit the number of clients. Set to zero for unlimited. +# max-clients = 1024 +max-clients = 4 + # Use listen-host to limit to specific IPs or to the IPs of a provided hostname. # listen-host = [IP|HOSTNAME] diff --git a/src/vpn.h b/src/vpn.h index a34881eb..f894b0f8 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -59,6 +59,7 @@ struct cfg_st { unsigned keepalive; const char *db_file; unsigned foreground; + unsigned max_clients; uid_t uid; gid_t gid;