summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Sławiński2006-04-06 23:34:51 +0200
committerJoshua Judson Rosen2014-07-17 21:15:02 +0200
commit1361f0e88138653d2437f45ddf940206ed0e93b7 (patch)
tree3507c0e145a2674d99e9da65cd8dc7ebcc91bdc1 /src
parentv0.8 (diff)
downloadapf-1361f0e88138653d2437f45ddf940206ed0e93b7.tar.gz
v0.8.1
- Fixed: enableproxy option in server's config file - Added: clients idle time - Added: 'maxidle' option - Modified: task scheduling subsystem has been completely rewritten - Fixed: segmentation fault in http tunnels after multiple simultaneous POST connections from the same source - Fixed: unexpected connection close when http proxy was too slow - Fixed: SIGSEGV in http proxy mode under cygwin - Added: enabled the SO_KEEPALIVE option for all the sockets used by the apf - Added: 60 seconds timeout for SSL_connect
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am19
-rw-r--r--src/activefor.h2
-rw-r--r--src/afclient.c2
-rw-r--r--src/afserver.c233
-rw-r--r--src/afserver.h1
-rw-r--r--src/client_initialization.c5
-rw-r--r--src/client_signals.c20
-rw-r--r--src/client_signals.h1
-rw-r--r--src/connect_client_struct.c71
-rw-r--r--src/connect_client_struct.h7
-rw-r--r--src/file_server.c7
-rw-r--r--src/http_proxy_client.c40
-rw-r--r--src/http_proxy_functions.c19
-rw-r--r--src/http_proxy_functions.h1
-rw-r--r--src/http_proxy_server.c44
-rw-r--r--src/network.c478
-rw-r--r--src/remove_client_task.c134
-rw-r--r--src/remove_client_task.h47
-rw-r--r--src/server_realm_struct.c68
-rw-r--r--src/server_realm_struct.h6
-rw-r--r--src/server_remoteadmin.c8
-rw-r--r--src/server_remove.c26
-rw-r--r--src/server_remove.h5
-rw-r--r--src/task_list_node_struct.c124
-rw-r--r--src/task_list_node_struct.h42
-rw-r--r--src/task_scheduler_struct.c321
-rw-r--r--src/task_scheduler_struct.h47
-rw-r--r--src/task_struct.c122
-rw-r--r--src/task_struct.h39
-rw-r--r--src/timeval_functions.c94
-rw-r--r--src/timeval_functions.h3
-rw-r--r--src/usage.c4
32 files changed, 1654 insertions, 386 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 68e6679..f16461a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,16 +6,15 @@ afserver_SOURCES = afserver.c network.c file.c stats.c buf_list_node_struct.c bu
thread_management.c server_signals.c usage.c logging.c daemon.c ssl_fd_struct.c \
user_stats_struct.c usr_cli_struct.c connect_user_struct.c string_functions.c \
audit_list_node_struct.c audit_list_struct.c connect_client_struct.c timeval_functions.c \
- header_buffer_struct.c server_realm_struct.c server_configuration_struct.c file_server.c
+ header_buffer_struct.c server_realm_struct.c server_configuration_struct.c file_server.c \
+ task_struct.c task_list_node_struct.c task_scheduler_struct.c remove_client_task.c
afclient_LDFLAGS = ${USE_RDYNAMIC} ${LINKED_LDLIB}
afclient_SOURCES = afclient.c network.c file.c stats.c buf_list_node_struct.c buf_list_struct.c \
module_struct.c client_remoteadmin.c make_ssl_handshake.c first_run.c inet_ntop.c \
- realmnames.c usernames.c http_proxy_functions.c http_proxy_client.c \
- http_proxy_options_struct.c thread_management.c client_reverse_udp.c server_check.c \
- client_initialization.c client_shutdown.c client_signals.c usage.c logging.c \
- daemon.c base64.c ssl_routines.c connect_user_struct.c user_stats_struct.c \
- string_functions.c ar_options_struct.c audit_list_node_struct.c audit_list_struct.c \
- ssl_fd_struct.c timeval_functions.c server_realm_struct.c server_configuration_struct.c \
- usr_cli_struct.c connect_client_struct.c header_buffer_struct.c \
- client_configuration_struct.c file_client.c client_realm_struct.c \
- port_list_node_struct.c port_list_struct.c
+ http_proxy_functions.c http_proxy_client.c http_proxy_options_struct.c \
+ thread_management.c client_reverse_udp.c server_check.c client_initialization.c \
+ client_shutdown.c client_signals.c usage.c logging.c daemon.c base64.c ssl_routines.c \
+ connect_user_struct.c user_stats_struct.c string_functions.c ar_options_struct.c \
+ audit_list_node_struct.c audit_list_struct.c ssl_fd_struct.c timeval_functions.c \
+ usr_cli_struct.c header_buffer_struct.c client_configuration_struct.c file_client.c \
+ client_realm_struct.c port_list_node_struct.c port_list_struct.c
diff --git a/src/activefor.h b/src/activefor.h
index 9ce940b..8f127aa 100644
--- a/src/activefor.h
+++ b/src/activefor.h
@@ -53,7 +53,7 @@
#define S_STATE_OPENING_CLOSED 17
#define S_STATE_KICKING 19
-#define AF_VER(info) info" v0.8"
+#define AF_VER(info) info" v0.8.1"
#define TYPE_TCP 1
#define TYPE_UDP 3
diff --git a/src/afclient.c b/src/afclient.c
index ec02e36..7d0ab20 100644
--- a/src/afclient.c
+++ b/src/afclient.c
@@ -155,6 +155,8 @@ main(int argc, char **argv)
act.sa_handler = client_sig_int;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
+ act.sa_handler = client_sig_alrm;
+ sigaction(SIGALRM, &act, NULL);
#ifdef HAVE_LIBPTHREAD
remember_mainthread();
diff --git a/src/afserver.c b/src/afserver.c
index 2ec71d1..bbc115d 100644
--- a/src/afserver.c
+++ b/src/afserver.c
@@ -28,6 +28,7 @@ static struct option long_options[] = {
{"listenport", 1, 0, 'l'},
{"manageport", 1, 0, 'm'},
{"timeout", 1, 0, 't'},
+ {"maxidle", 1, 0, 321},
{"verbose", 0, 0, 'v'},
{"users", 1, 0, 'u'},
{"clients", 1, 0, 'C'},
@@ -71,7 +72,7 @@ main(int argc, char **argv)
unsigned char buff[9000];
int maxfdp1;
fd_set rset, allset, wset, tmpset;
- int manconnecting, numofcon, length;
+ int numofcon, length;
char* name = NULL;
char** listen = NULL;
int listencount = 0;
@@ -85,6 +86,7 @@ main(int argc, char **argv)
char* filenam = NULL;
char* type = NULL;
char* timeout = NULL;
+ char* maxidle = NULL;
char* realmname = NULL;
unsigned char pass[4] = {1, 2, 3, 4};
char verbose = 0;
@@ -97,6 +99,8 @@ main(int argc, char **argv)
char audit = 0;
char dnslookups = 0;
ServerRealm* pointer = NULL;
+ TaskScheduler* scheduler;
+ Task* task;
struct sigaction act;
time_t now;
ServerRealm** scRealmsTable;
@@ -173,6 +177,10 @@ main(int argc, char **argv)
timeout = optarg;
break;
}
+ case 321: {
+ maxidle = optarg;
+ break;
+ }
case 'v': {
++verbose;
break;
@@ -436,6 +444,7 @@ main(int argc, char **argv)
ServerRealm_set_sClientsLimit(pointer, clients);
ServerRealm_set_sRaClientsLimit(pointer, raclients);
ServerRealm_set_sTimeout(pointer, timeout);
+ ServerRealm_set_sMaxIdle(pointer, maxidle);
ServerRealm_set_sUsersPerClient(pointer, usrpcli);
ServerRealm_set_sClientMode(pointer, clim);
ServerRealm_set_basePortOn(pointer, baseport);
@@ -483,7 +492,7 @@ main(int argc, char **argv)
ServerRealm_set_realmType(pointer, temp);
}
- maxfdp1 = manconnecting = 0;
+ maxfdp1 = 0;
SSL_library_init();
method = SSLv3_server_method();
@@ -536,6 +545,13 @@ main(int argc, char **argv)
if (!verbose)
daemon(0, 0);
+ scheduler = TaskScheduler_new();
+ if (scheduler == NULL) {
+ aflog(LOG_T_INIT, LOG_I_CRIT,
+ "Problems with creating task scheduler... exiting");
+ exit(1);
+ }
+
scRealmsTable = ServerConfiguration_get_realmsTable(config);
for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) {
if (ServerRealm_get_userClientPairs(scRealmsTable[i]) == 0) {
@@ -663,6 +679,17 @@ main(int argc, char **argv)
ServerRealm_set_sTimeout(scRealmsTable[i], stemp);
ServerRealm_set_timeout(scRealmsTable[i],
check_value(ServerRealm_get_sTimeout(scRealmsTable[i]), "Invalid timeout value"));
+ /* checking maxidle value */
+ stemp = ServerRealm_get_sMaxIdle(scRealmsTable[i]);
+ set_value(&stemp, maxidle, "0");
+ ServerRealm_set_sMaxIdle(scRealmsTable[i], stemp);
+ temp = check_value_liberal(ServerRealm_get_sMaxIdle(scRealmsTable[i]), "Invalid maxidle value");
+ if (temp < 0) {
+ aflog(LOG_T_INIT, LOG_I_CRIT,
+ "Invalid maxidle value: %d\n", temp);
+ exit(1);
+ }
+ ServerRealm_set_maxIdle(scRealmsTable[i], temp);
/* checking climode value */
stemp = ServerRealm_get_sClientMode(scRealmsTable[i]);
set_value(&stemp, clim, "1");
@@ -899,70 +926,19 @@ main(int argc, char **argv)
ServerConfiguration_set_startTime(config, now);
for ( ; ; ) {
- rset = allset;
- tmpset = wset;
- aflog(LOG_T_MAIN, LOG_I_DDEBUG,
- "select, maxfdp1: %d", maxfdp1);
- if (manconnecting) {
- /* find out, in what realm client is trying to connect */
- l = -1;
- for (k = 0; k < ServerConfiguration_get_realmsNumber(config); ++k) {
- srClientsTable = ServerRealm_get_clientsTable(scRealmsTable[k]);
- for (j=0; j < ServerRealm_get_clientsLimit(scRealmsTable[k]); ++j) {
- if ((ConnectClient_get_state(srClientsTable[j]) == CONNECTCLIENT_STATE_CONNECTING) ||
- (ConnectClient_get_state(srClientsTable[j]) == CONNECTCLIENT_STATE_AUTHORIZING)) {
- i = k;
- k = ServerConfiguration_get_realmsNumber(config);
- l = 0;
- break; /* so i points to first good realm and j to good client */
- }
- }
- if (l == -1) {
- srRaClientsTable = ServerRealm_get_raClientsTable(scRealmsTable[k]);
- for (j=0; j < ServerRealm_get_raClientsLimit(scRealmsTable[k]); ++j) {
- if ((ConnectClient_get_state(srRaClientsTable[j])==CONNECTCLIENT_STATE_CONNECTING) ||
- (ConnectClient_get_state(srRaClientsTable[j])==CONNECTCLIENT_STATE_AUTHORIZING)) {
- i = k;
- k = ServerConfiguration_get_realmsNumber(config);
- l = 1;
- break; /* so i points to first good realm and j to good client */
- }
- }
- }
- }
- if (!l) {
- srClientsTable = ServerRealm_get_clientsTable(scRealmsTable[i]);
- if (select(maxfdp1,&rset,&tmpset,NULL,ConnectClient_get_timerp(srClientsTable[j])) == 0) {
- close(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[j])));
- FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[j])), &allset);
- SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(srClientsTable[j])));
- ConnectClient_set_state(srClientsTable[j], CONNECTCLIENT_STATE_FREE);
- manconnecting--;
- ServerRealm_decrease_connectedClients(scRealmsTable[i]);
- aflog(LOG_T_CLIENT, LOG_I_WARNING,
- "realm[%s]: Client[%s]: SSL_accept failed (timeout)",
- get_realmname(config, i), get_clientname(scRealmsTable[i], j));
- }
- }
- else {
- srRaClientsTable = ServerRealm_get_raClientsTable(scRealmsTable[i]);
- if (select(maxfdp1,&rset,&tmpset,NULL,ConnectClient_get_timerp(srRaClientsTable[j]))==0) {
- close(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[j])));
- FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[j])), &allset);
- SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(srRaClientsTable[j])));
- ConnectClient_set_state(srRaClientsTable[j], CONNECTCLIENT_STATE_FREE);
- manconnecting--;
- ServerRealm_decrease_connectedClients(scRealmsTable[i]);
- aflog(LOG_T_CLIENT, LOG_I_WARNING,
- "realm[%s]: Client[%s] (ra): SSL_accept failed (timeout)",
- get_realmname(config, i), get_raclientname(scRealmsTable[i], j));
- }
- }
- }
- else {
- select(maxfdp1, &rset, &tmpset, NULL, NULL);
- }
- aflog(LOG_T_MAIN, LOG_I_DDEBUG,
+ rset = allset;
+ tmpset = wset;
+ aflog(LOG_T_MAIN, LOG_I_DDEBUG,
+ "select, maxfdp1: %d", maxfdp1);
+ if (TaskScheduler_hasMoreTasks(scheduler)) {
+ TaskScheduler_startWatching(scheduler);
+ select(maxfdp1, &rset, &tmpset, NULL, TaskScheduler_get_actualTimer(scheduler));
+ TaskScheduler_stopWatching(scheduler);
+ }
+ else {
+ select(maxfdp1, &rset, &tmpset, NULL, NULL);
+ }
+ aflog(LOG_T_MAIN, LOG_I_DDEBUG,
"after select...");
for (j = 0; j < ServerConfiguration_get_realmsNumber(config); ++j) {
@@ -1263,6 +1239,7 @@ main(int argc, char **argv)
aflog(LOG_T_USER, LOG_I_DDEBUG,
"realm[%s]: listenfd: FD_ISSET", get_realmname(config, j));
k = find_client(pointer, ServerRealm_get_clientMode(pointer), l);
+
if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_ACCEPTED) {
if (ServerRealm_get_connectedUsers(pointer) == ServerRealm_get_usersLimit(pointer)) {
close(sent);
@@ -1331,6 +1308,7 @@ main(int argc, char **argv)
for (k = 0; k < ServerRealm_get_clientsLimit(pointer); ++k) {
if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_ACCEPTED) {
if (FD_ISSET(ConnectClient_get_listenFd(srClientsTable[k]), &rset)) {
+
len = ServerRealm_get_addressLength(pointer);
sent = accept(ConnectClient_get_listenFd(srClientsTable[k]), ServerRealm_get_clientAddress(pointer), &len);
if (sent == -1) {
@@ -1417,7 +1395,10 @@ main(int argc, char **argv)
FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])), &allset);
SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(srClientsTable[k])));
ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_FREE);
- manconnecting--;
+ if ((task = ConnectClient_get_task(srClientsTable[k]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(srClientsTable[k], NULL);
+ }
ServerRealm_decrease_connectedClients(pointer);
aflog(LOG_T_CLIENT, LOG_I_ERR,
"realm[%s]: new Client[%s]: DENIED by SSL_accept",
@@ -1511,7 +1492,7 @@ main(int argc, char **argv)
AuditList_delete_first(ConnectClient_get_auditList(srClientsTable[k]));
}
}
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
continue;
}
@@ -1536,6 +1517,13 @@ main(int argc, char **argv)
(buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) {
buff[0] = AF_S_WRONG;
}
+
+ time(&now);
+ ConnectClient_set_lastActivity(srClientsTable[k], now);
+ if (ServerRealm_get_maxIdle(pointer)) {
+ ConnectClient_set_timer(srClientsTable[k], timeval_create(ServerRealm_get_maxIdle(pointer), 0));
+ TaskScheduler_update(scheduler);
+ }
switch (buff[0]) {
case AF_S_CONCLOSED : {
@@ -1590,7 +1578,7 @@ main(int argc, char **argv)
}
}
else {
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
}
break;
}
@@ -1626,7 +1614,7 @@ main(int argc, char **argv)
}
}
else {
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
}
break;
}
@@ -1654,14 +1642,14 @@ main(int argc, char **argv)
}
}
else {
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
}
break;
}
case AF_S_MESSAGE : {
if (ConnectClient_get_state(srClientsTable[k]) !=
CONNECTCLIENT_STATE_ACCEPTED) {
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
break;
}
if (TYPE_IS_UDP(ServerRealm_get_realmType(pointer))) { /* udp */
@@ -1833,7 +1821,20 @@ main(int argc, char **argv)
ConnectClient_get_sslFd(
srClientsTable[k]),
buff, 5);
- manconnecting--;
+ if ((task = ConnectClient_get_task(srClientsTable[k]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(srClientsTable[k], NULL);
+ }
+ if (ServerRealm_get_maxIdle(pointer)) {
+ ConnectClient_set_timer(srClientsTable[k],
+ timeval_create(ServerRealm_get_maxIdle(pointer), 0));
+ task = Task_new(ConnectClient_get_timerp(srClientsTable[k]),
+ RCTfunction,
+ RCTdata_new(config, j, k, 0, RCT_REASON_MAXIDLE, &allset, &wset),
+ RCTdata_free);
+ ConnectClient_set_task(srClientsTable[k], task);
+ TaskScheduler_addTask(scheduler, task);
+ }
if (ServerRealm_get_basePortOn(pointer) == 1) {
long tmp_val;
char tmp_tab[6];
@@ -1845,7 +1846,7 @@ main(int argc, char **argv)
aflog(LOG_T_CLIENT, LOG_I_ERR,
"realm[%s]: INVALID listenport - removing Client[%s]",
get_realmname(config, j), get_clientname(pointer, k));
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
break;
}
tmp_val = tmp_val%65536;
@@ -1888,7 +1889,7 @@ main(int argc, char **argv)
ConnectClient_get_sslFd(
srClientsTable[k]),
buff, 5);
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
}
}
else if ((ConnectClient_get_state(srClientsTable[k]) ==
@@ -1912,7 +1913,7 @@ main(int argc, char **argv)
ConnectClient_get_sslFd(
srClientsTable[k]),
buff, 5);
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
}
break;
}
@@ -1950,7 +1951,7 @@ main(int argc, char **argv)
aflog(LOG_T_CLIENT, LOG_I_ERR,
"realm[%s]: Client[%s]: Wrong message - CLOSING",
get_realmname(config, j), get_clientname(pointer, k));
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
break;
}
case AF_S_ADMIN_LOGIN: {
@@ -1971,6 +1972,9 @@ main(int argc, char **argv)
ConnectClient_set_connectTime(
srRaClientsTable[l],
ConnectClient_get_connectTime(srClientsTable[k]));
+ ConnectClient_set_lastActivity(
+ srRaClientsTable[l],
+ ConnectClient_get_lastActivity(srClientsTable[k]));
#ifdef HAVE_LIBPTHREAD
ConnectClient_set_tunnelType(
srRaClientsTable[l],
@@ -2005,7 +2009,10 @@ main(int argc, char **argv)
srRaClientsTable[l],
CONNECTCLIENT_STATE_ACCEPTED);
ServerRealm_increase_connectedRaClients(pointer);
- manconnecting--;
+ if ((task = ConnectClient_get_task(srClientsTable[k]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(srClientsTable[k], NULL);
+ }
sprintf((char*) &buff[5], AF_VER("AFSERVER"));
n = strlen((char*) &buff[5]);
buff[0] = AF_S_ADMIN_LOGIN; /* sending message */
@@ -2027,7 +2034,7 @@ main(int argc, char **argv)
ConnectClient_get_sslFd(
srClientsTable[k]),
buff, 5);
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
}
}
break;
@@ -2049,7 +2056,7 @@ main(int argc, char **argv)
aflog(LOG_T_CLIENT, LOG_I_ERR,
"realm[%s]: Client[%s]: Unrecognized message - CLOSING",
get_realmname(config, j), get_clientname(pointer, k));
- remove_client(pointer, k, &allset, &wset, &manconnecting);
+ remove_client(pointer, k, &allset, &wset, scheduler);
}
}
}
@@ -2068,7 +2075,10 @@ main(int argc, char **argv)
FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])), &allset);
SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(srRaClientsTable[k])));
ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_FREE);
- manconnecting--;
+ if ((task = ConnectClient_get_task(srRaClientsTable[k]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(srRaClientsTable[k], NULL);
+ }
ServerRealm_decrease_connectedClients(pointer);
aflog(LOG_T_MANAGE, LOG_I_ERR,
"realm[%s]: new Client[%s] (ra): DENIED by SSL_accept",
@@ -2123,7 +2133,7 @@ main(int argc, char **argv)
}
}
if (n==0) {
- remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ remove_raclient(pointer, k, &allset, &wset, scheduler);
aflog(LOG_T_MANAGE, LOG_I_INFO,
"realm[%s]: Client[%s] (ra): commfd: CLOSED",
get_realmname(config, j), get_raclientname(pointer, k));
@@ -2147,6 +2157,9 @@ main(int argc, char **argv)
(buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) {
buff[0] = AF_S_WRONG;
}
+
+ time(&now);
+ ConnectClient_set_lastActivity(srRaClientsTable[k], now);
switch (buff[0]) {
case AF_S_LOGIN : {
@@ -2169,6 +2182,9 @@ main(int argc, char **argv)
ConnectClient_set_connectTime(
srClientsTable[l],
ConnectClient_get_connectTime(srRaClientsTable[k]));
+ ConnectClient_set_lastActivity(
+ srClientsTable[l],
+ ConnectClient_get_lastActivity(srRaClientsTable[k]));
#ifdef HAVE_LIBPTHREAD
ConnectClient_set_tunnelType(
srClientsTable[l],
@@ -2214,7 +2230,20 @@ main(int argc, char **argv)
ConnectClient_get_sslFd(
srClientsTable[l]),
buff, 5);
- manconnecting--;
+ if ((task = ConnectClient_get_task(srRaClientsTable[k]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(srRaClientsTable[k], NULL);
+ }
+ if (ServerRealm_get_maxIdle(pointer)) {
+ ConnectClient_set_timer(srClientsTable[l],
+ timeval_create(ServerRealm_get_maxIdle(pointer), 0));
+ task = Task_new(ConnectClient_get_timerp(srClientsTable[l]),
+ RCTfunction,
+ RCTdata_new(config, j, l, 0, RCT_REASON_MAXIDLE, &allset, &wset),
+ RCTdata_free);
+ ConnectClient_set_task(srClientsTable[l], task);
+ TaskScheduler_addTask(scheduler, task);
+ }
if (ServerRealm_get_basePortOn(pointer) == 1) {
long tmp_val;
char tmp_tab[6];
@@ -2226,7 +2255,7 @@ main(int argc, char **argv)
aflog(LOG_T_CLIENT, LOG_I_ERR,
"realm[%s]: INVALID listenport - removing Client[%s]",
get_realmname(config, j), get_clientname(pointer, l));
- remove_client(pointer, l, &allset, &wset, &manconnecting);
+ remove_client(pointer, l, &allset, &wset, scheduler);
break;
}
tmp_val = tmp_val%65536;
@@ -2269,7 +2298,7 @@ main(int argc, char **argv)
ConnectClient_get_sslFd(
srRaClientsTable[k]),
buff, 5);
- remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ remove_raclient(pointer, k, &allset, &wset, scheduler);
}
}
else if ((ConnectClient_get_state(srRaClientsTable[k]) ==
@@ -2288,7 +2317,7 @@ main(int argc, char **argv)
aflog(LOG_T_MANAGE, LOG_I_ERR,
"realm[%s]: Client[%s] (ra): Wrong password - CLOSING",
get_realmname(config, j), get_raclientname(pointer, k));
- remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ remove_raclient(pointer, k, &allset, &wset, scheduler);
}
break;
}
@@ -2296,7 +2325,7 @@ main(int argc, char **argv)
aflog(LOG_T_MANAGE, LOG_I_ERR,
"realm[%s]: Client[%s] (ra): Wrong message - CLOSING",
get_realmname(config, j), get_raclientname(pointer, k));
- remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ remove_raclient(pointer, k, &allset, &wset, scheduler);
break;
}
case AF_S_ADMIN_LOGIN: {
@@ -2311,7 +2340,10 @@ main(int argc, char **argv)
srRaClientsTable[k],
CONNECTCLIENT_STATE_ACCEPTED);
ServerRealm_increase_connectedRaClients(pointer);
- manconnecting--;
+ if ((task = ConnectClient_get_task(srRaClientsTable[k]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(srRaClientsTable[k], NULL);
+ }
sprintf((char*) &buff[5], AF_VER("AFSERVER"));
n = strlen((char*) &buff[5]);
buff[0] = AF_S_ADMIN_LOGIN; /* sending message */
@@ -2334,7 +2366,7 @@ main(int argc, char **argv)
aflog(LOG_T_MANAGE, LOG_I_NOTICE,
"realm[%s]: Client[%s] (ra): remote admin -- closing",
get_realmname(config, j), get_raclientname(pointer, k));
- remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ remove_raclient(pointer, k, &allset, &wset, scheduler);
}
else {
for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) {
@@ -2394,7 +2426,7 @@ main(int argc, char **argv)
}
}
remove_client(scRealmsTable[i], l,
- &allset, &wset, &manconnecting);
+ &allset, &wset, scheduler);
break;
}
}
@@ -2405,7 +2437,7 @@ main(int argc, char **argv)
aflog(LOG_T_MANAGE, LOG_I_ERR,
"realm[%s]: Client[%s] (ra): remote admin -- security VIOLATION",
get_realmname(config, j), get_raclientname(pointer, k));
- remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ remove_raclient(pointer, k, &allset, &wset, scheduler);
}
break;
}
@@ -2419,13 +2451,14 @@ main(int argc, char **argv)
aflog(LOG_T_MANAGE, LOG_I_ERR,
"realm[%s]: Client[%s] (ra): Unrecognized message - CLOSING",
get_realmname(config, j), get_raclientname(pointer, k));
- remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ remove_raclient(pointer, k, &allset, &wset, scheduler);
}
}
}
/* ------------------------------------ */
for (l = 0; l < ServerRealm_get_userClientPairs(pointer); ++l) {
if (FD_ISSET(UsrCli_get_manageFd(srUsersClientsTable[l]), &rset)) {
+
aflog(LOG_T_CLIENT, LOG_I_DDEBUG,
"realm[%s]: managefd: FD_ISSET", get_realmname(config, j));
len = ServerRealm_get_addressLength(pointer);
@@ -2459,6 +2492,7 @@ main(int argc, char **argv)
ConnectClient_set_usrCliPair(srClientsTable[k], l);
time(&now);
ConnectClient_set_connectTime(srClientsTable[k], now);
+ ConnectClient_set_lastActivity(srClientsTable[k], now);
#ifdef HAVE_LIBPTHREAD
ConnectClient_set_tunnelType(srClientsTable[k], tunneltype);
#endif
@@ -2471,7 +2505,12 @@ main(int argc, char **argv)
maxfdp1 : (SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])) + 1);
ServerRealm_increase_connectedClients(pointer);
ConnectClient_set_timer(srClientsTable[k], timeval_create(ServerRealm_get_timeout(pointer), 0));
- manconnecting++;
+ task = Task_new(ConnectClient_get_timerp(srClientsTable[k]),
+ RCTfunction,
+ RCTdata_new(config, j, k, 0, RCT_REASON_TIMEOUT, &allset, &wset),
+ RCTdata_free);
+ ConnectClient_set_task(srClientsTable[k], task);
+ TaskScheduler_addTask(scheduler, task);
ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_CONNECTING);
break;
}
@@ -2489,6 +2528,7 @@ main(int argc, char **argv)
ConnectClient_set_usrCliPair(srRaClientsTable[k], l);
time(&now);
ConnectClient_set_connectTime(srRaClientsTable[k], now);
+ ConnectClient_set_lastActivity(srRaClientsTable[k], now);
#ifdef HAVE_LIBPTHREAD
ConnectClient_set_tunnelType(srRaClientsTable[k], tunneltype);
#endif
@@ -2505,7 +2545,12 @@ main(int argc, char **argv)
ServerRealm_increase_connectedClients(pointer);
ConnectClient_set_timer(srRaClientsTable[k],
timeval_create(ServerRealm_get_timeout(pointer), 0));
- manconnecting++;
+ task = Task_new(ConnectClient_get_timerp(srRaClientsTable[k]),
+ RCTfunction,
+ RCTdata_new(config, j, k, 1, RCT_REASON_TIMEOUT, &allset, &wset),
+ RCTdata_free);
+ ConnectClient_set_task(srRaClientsTable[k], task);
+ TaskScheduler_addTask(scheduler, task);
ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_CONNECTING);
break;
}
diff --git a/src/afserver.h b/src/afserver.h
index 23e2a2f..229d555 100644
--- a/src/afserver.h
+++ b/src/afserver.h
@@ -41,6 +41,7 @@
#include "logging.h"
#include "daemon.h"
#include "timeval_functions.h"
+#include "remove_client_task.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
diff --git a/src/client_initialization.c b/src/client_initialization.c
index 77c0e48..5dc3717 100644
--- a/src/client_initialization.c
+++ b/src/client_initialization.c
@@ -27,6 +27,7 @@
#include "base64.h"
#include "ssl_routines.h"
#include "client_configuration_struct.h"
+#include "client_signals.h"
int
initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, char wanttoexit,
@@ -126,6 +127,8 @@ initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, cha
}
}
+ alarm(60);
+
aflog(LOG_T_INIT, LOG_I_INFO,
"Trying SSL_connect");
if ((n = SSL_connect(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)))) == 1) {
@@ -201,6 +204,7 @@ initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, cha
"SSL_connect successful");
}
else {
+ alarm(0);
aflog(LOG_T_INIT, LOG_I_CRIT,
"SSL_connect has failed (%d | %d)... exiting", n,
SSL_get_error(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)), n));
@@ -212,6 +216,7 @@ initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, cha
return 3;
}
}
+ alarm(0);
buff[0] = AF_S_LOGIN;
buff[1] = ClientRealm_get_password(cr)[0];
diff --git a/src/client_signals.c b/src/client_signals.c
index 3184275..1202a48 100644
--- a/src/client_signals.c
+++ b/src/client_signals.c
@@ -27,7 +27,13 @@
#include <stdlib.h>
- void
+/*
+ * Function name: client_sig_int
+ * Description: Function responsible for handling SIG_INT.
+ * Arguments: signo - the signal number
+ */
+
+void
client_sig_int(int signo)
{
#ifdef HAVE_LIBPTHREAD
@@ -40,3 +46,15 @@ client_sig_int(int signo)
exit(0);
}
+/*
+ * Function name: client_sig_alrm
+ * Description: Function responsible for handling SIG_ALRM.
+ * Arguments: signo - the signal number
+ */
+
+void
+client_sig_alrm(int signo)
+{
+ aflog(LOG_T_MAIN, LOG_I_DEBUG,
+ "Received SIGALRM");
+}
diff --git a/src/client_signals.h b/src/client_signals.h
index 198e7a5..9082009 100644
--- a/src/client_signals.h
+++ b/src/client_signals.h
@@ -22,6 +22,7 @@
#define _JS_CLIENT_SIGNALS_H
void client_sig_int(int); /* INT signal handler for the afclient */
+void client_sig_alrm(int); /* ALRM signal handler for the afclient */
#endif
diff --git a/src/connect_client_struct.c b/src/connect_client_struct.c
index 3481833..f5e713e 100644
--- a/src/connect_client_struct.c
+++ b/src/connect_client_struct.c
@@ -275,6 +275,23 @@ ConnectClient_set_connectTime(ConnectClient* cc, time_t connectTime)
}
/*
+ * Function name: ConnectClient_set_lastActivity
+ * Description: Sets time of the last client activity (when last packet from afclient has arrived)
+ * Arguments: cc - pointer to ConnectClient structure
+ * lastActivity - time of the last client activity
+ */
+
+void
+ConnectClient_set_lastActivity(ConnectClient* cc, time_t lastActivity)
+{
+ assert(cc != NULL);
+ if (cc == NULL) {
+ return;
+ }
+ cc->lastActivity = lastActivity;
+}
+
+/*
* Function name: ConnectClient_set_sClientId
* Description: Sets client identification string.
* Arguments: cc - pointer to ConnectClient structure
@@ -403,6 +420,26 @@ ConnectClient_set_header(ConnectClient* cc, HeaderBuffer* hb)
}
/*
+ * Function name: ConnectClient_set_task
+ * Description: Sets the client task.
+ * Arguments: cc - pointer to ConnectClient structure
+ * task - the task to set
+ */
+
+void
+ConnectClient_set_task(ConnectClient* cc, Task* task)
+{
+ assert(cc != NULL);
+ if (cc == NULL) {
+ return;
+ }
+ if (cc->task) {
+ Task_free(&(cc->task));
+ }
+ cc->task = task;
+}
+
+/*
* Function name: ConnectClient_get_state
* Description: Gets state of the connected client.
* Arguments: cc - pointer to ConnectClient structure
@@ -573,6 +610,23 @@ ConnectClient_get_connectTime(ConnectClient* cc)
}
/*
+ * Function name: ConnectClient_get_lastActivity
+ * Description: Gets time of the last client activity (when last packet from afclient has arrived)
+ * Arguments: cc - pointer to ConnectClient structure
+ * Returns: Time of the last client activity.
+ */
+
+time_t
+ConnectClient_get_lastActivity(ConnectClient* cc)
+{
+ assert(cc != NULL);
+ if (cc == NULL) {
+ return 0;
+ }
+ return cc->lastActivity;
+}
+
+/*
* Function name: ConnectClient_get_sClientId
* Description: Gets client identification string.
* Arguments: cc - pointer to ConnectClient structure
@@ -693,6 +747,23 @@ ConnectClient_get_header(ConnectClient* cc)
}
/*
+ * Function name: ConnectClient_get_task
+ * Description: Gets the client task.
+ * Arguments: cc - pointer to ConnectClient structure
+ * Returns: The client task.
+ */
+
+Task*
+ConnectClient_get_task(ConnectClient* cc)
+{
+ assert(cc != NULL);
+ if (cc == NULL) {
+ return NULL;
+ }
+ return cc->task;
+}
+
+/*
* Function name: ConnectClient_create_users
* Description: Creates user descriptor table. Memory for the table is allocated according
* to the previously set 'limit' value. All the descriptors are set to -1.
diff --git a/src/connect_client_struct.h b/src/connect_client_struct.h
index 58ce276..322a910 100644
--- a/src/connect_client_struct.h
+++ b/src/connect_client_struct.h
@@ -27,6 +27,7 @@
#include "ssl_fd_struct.h"
#include "audit_list_struct.h"
#include "header_buffer_struct.h"
+#include "task_struct.h"
#define CONNECTCLIENT_STATE_UNKNOWN -1
#define CONNECTCLIENT_STATE_FREE 0
@@ -53,6 +54,7 @@ typedef struct {
int usrCliPair;
int clientId;
time_t connectTime;
+ time_t lastActivity;
char* sClientId;
char nameBuf[128];
char portBuf[7];
@@ -60,6 +62,7 @@ typedef struct {
char multi;
AuditList* auditList;
HeaderBuffer* header;
+ Task* task;
} ConnectClient;
/* 'constructor' */
@@ -77,6 +80,7 @@ void ConnectClient_set_listenFd(ConnectClient* cc, int listenFd);
void ConnectClient_set_usrCliPair(ConnectClient* cc, int usrCliPair);
void ConnectClient_set_clientId(ConnectClient* cc, int clientId);
void ConnectClient_set_connectTime(ConnectClient* cc, time_t connectTime);
+void ConnectClient_set_lastActivity(ConnectClient* cc, time_t lastActivity);
void ConnectClient_set_sClientId(ConnectClient* cc, char* sClientId);
void ConnectClient_set_nameBuf(ConnectClient* cc, char* nameBuf);
void ConnectClient_set_portBuf(ConnectClient* cc, char* portBuf);
@@ -84,6 +88,7 @@ void ConnectClient_set_tunnelType(ConnectClient* cc, char tunnelType);
void ConnectClient_set_multi(ConnectClient* cc, char multi);
void ConnectClient_set_auditList(ConnectClient* cc, AuditList* al);
void ConnectClient_set_header(ConnectClient* cc, HeaderBuffer* hb);
+void ConnectClient_set_task(ConnectClient* cc, Task* task);
/* getters */
char ConnectClient_get_state(ConnectClient* cc);
SslFd* ConnectClient_get_sslFd(ConnectClient* cc);
@@ -95,6 +100,7 @@ int ConnectClient_get_listenFd(ConnectClient* cc);
int ConnectClient_get_usrCliPair(ConnectClient* cc);
int ConnectClient_get_clientId(ConnectClient* cc);
time_t ConnectClient_get_connectTime(ConnectClient* cc);
+time_t ConnectClient_get_lastActivity(ConnectClient* cc);
char* ConnectClient_get_sClientId(ConnectClient* cc);
char* ConnectClient_get_nameBuf(ConnectClient* cc);
char* ConnectClient_get_portBuf(ConnectClient* cc);
@@ -102,6 +108,7 @@ char ConnectClient_get_tunnelType(ConnectClient* cc);
char ConnectClient_get_multi(ConnectClient* cc);
AuditList* ConnectClient_get_auditList(ConnectClient* cc);
HeaderBuffer* ConnectClient_get_header(ConnectClient* cc);
+Task* ConnectClient_get_task(ConnectClient* cc);
/* other */
int ConnectClient_create_users(ConnectClient* cc);
struct timeval* ConnectClient_get_timerp(ConnectClient* cc);
diff --git a/src/file_server.c b/src/file_server.c
index 427fb1b..e495f65 100644
--- a/src/file_server.c
+++ b/src/file_server.c
@@ -169,6 +169,7 @@ parsefile(char* name, int* status)
ServerConfiguration_get_realmsNumber(cfg) - 1]);
TYPE_SET_SSL(temp);
TYPE_SET_ZLIB(temp);
+ TYPE_SET_SUPPORTED_MULTI(temp);
ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[
ServerConfiguration_get_realmsNumber(cfg) - 1], temp);
listencount = managecount = 0;
@@ -257,6 +258,7 @@ parsefile(char* name, int* status)
ServerConfiguration_get_realmsNumber(cfg) - 1]);
TYPE_SET_SSL(temp);
TYPE_SET_ZLIB(temp);
+ TYPE_SET_SUPPORTED_MULTI(temp);
ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[
ServerConfiguration_get_realmsNumber(cfg) - 1], temp);
listencount = managecount = 0;
@@ -320,6 +322,11 @@ parsefile(char* name, int* status)
ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1],
helpbuf2);
}
+ else if (strcmp(helpbuf1, "maxidle")==0) {
+ ServerRealm_set_sMaxIdle(
+ ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1],
+ helpbuf2);
+ }
else if (strcmp(helpbuf1, "clients")==0) {
ServerRealm_set_sClientsLimit(
ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1],
diff --git a/src/http_proxy_client.c b/src/http_proxy_client.c
index e801a73..b488f3d 100644
--- a/src/http_proxy_client.c
+++ b/src/http_proxy_client.c
@@ -258,16 +258,19 @@ http_proxy_client(void *vptr)
}
while (1) {
+ if ((conn.state == C_OPEN) && (!(FD_ISSET(conn.sockfd, &allset)))) {
+ FD_SET(conn.sockfd, &allset);
+ }
rset = allset;
if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) {
aflog(LOG_T_MAIN, LOG_I_DDEBUG,
"http%s proxy: timeout", name);
tv.tv_sec = timeout;
- if (conn.state == C_CLOSED) {
- continue;
- }
if (conn.sent_ptr+1 >= 90000) {
+ if (conn.state == C_CLOSED) {
+ continue;
+ }
aflog(LOG_T_MAIN, LOG_I_DDEBUG,
"http%s proxy: send T", name);
http_write(https, conn.postFd, (unsigned char*) "T", 1);
@@ -319,6 +322,7 @@ http_proxy_client(void *vptr)
conn.sent_ptr = 0;
conn.ptr = 0;
conn.length = 0;
+ conn.state = C_CLOSED;
set_fd(SslFd_get_fd(conn.postFd), &maxfdp1, &allset);
}
@@ -335,28 +339,6 @@ http_proxy_client(void *vptr)
if (FD_ISSET(conn.sockfd, &rset)) {
aflog(LOG_T_MAIN, LOG_I_DDEBUG,
"http%s proxy: FD_ISSET(conn.sockfd)", name);
- if (conn.state == C_CLOSED) {
- /* postfd */
- aflog(LOG_T_MAIN, LOG_I_DEBUG,
- "http%s proxy: connecting (postfd)...", name);
- if (ip_connect(&tmp, proxyname, proxyport, type, NULL, NULL)) {
- clean_return(conn.sockfd);
- }
- SslFd_set_fd(conn.postFd, tmp);
- if (https) {
- if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) {
- aflog(LOG_T_INIT, LOG_I_CRIT,
- "https proxy: Problem with initializing ssl");
- clean_return(conn.sockfd);
- }
- if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) {
- aflog(LOG_T_INIT, LOG_I_CRIT,
- "https proxy: SSL_connect has failed");
- clean_return(conn.sockfd);
- }
- }
- conn.state = C_OPEN;
- }
n = read(conn.sockfd, conn.buf+5, 8995);
if (n <= 0) {
aflog(LOG_T_MAIN, LOG_I_DEBUG,
@@ -364,6 +346,9 @@ http_proxy_client(void *vptr)
http_write(https, conn.postFd, (unsigned char *) "Q", 1);
clean_return(conn.sockfd);
}
+ if ((conn.state == C_CLOSED) && (conn.sent_ptr > 70000)) {
+ FD_CLR(conn.sockfd, &allset);
+ }
conn.buf[0] = 'M';
tmp = htonl(n);
memcpy(&conn.buf[1], &tmp, 4);
@@ -429,6 +414,7 @@ http_proxy_client(void *vptr)
conn.sent_ptr = conn.length;
conn.ptr = 0;
conn.length = 0;
+ conn.state = C_CLOSED;
set_fd(SslFd_get_fd(conn.postFd), &maxfdp1, &allset);
}
@@ -523,9 +509,9 @@ http_proxy_client(void *vptr)
/* postfd */
if (FD_ISSET(SslFd_get_fd(conn.postFd), &rset)) {
aflog(LOG_T_MAIN, LOG_I_DDEBUG,
- "http%s proxy: FD_ISSET(conn.postfd)", name);
+ "http%s proxy: FD_ISSET(conn.postfd) --> clean_return", name);
clear_sslFd(conn.postFd, &allset);
- conn.state = C_CLOSED;
+ clean_return(conn.sockfd);
}
}
clean_return(conn.sockfd);
diff --git a/src/http_proxy_functions.c b/src/http_proxy_functions.c
index 495d7d8..509b0a1 100644
--- a/src/http_proxy_functions.c
+++ b/src/http_proxy_functions.c
@@ -284,9 +284,11 @@ read_message(int fd, int length, connection* client, char* tab, int ptr)
int tmp = 0;
while (j < length) {
if (client->curreceived + length-j > client->toreceive) {
- writen(fd, (unsigned char*) (tab+ptr+j), client->toreceive - client->curreceived);
- j += client->toreceive - client->curreceived;
- client->curreceived += client->toreceive - client->curreceived;
+ if (client->toreceive - client->curreceived > 0) {
+ writen(fd, (unsigned char*) (tab+ptr+j), client->toreceive - client->curreceived);
+ j += client->toreceive - client->curreceived;
+ client->curreceived += client->toreceive - client->curreceived;
+ }
if (client->read_state == 0) {
switch (tab[ptr + j]) {
case 'M': {
@@ -311,6 +313,13 @@ read_message(int fd, int length, connection* client, char* tab, int ptr)
++j;
break;
}
+ case 'A': {
+ ++j;
+ if (client->state == C_CLOSED) {
+ client->state = C_OPEN;
+ }
+ break;
+ }
default: {
return 1;
}
@@ -332,7 +341,7 @@ read_message(int fd, int length, connection* client, char* tab, int ptr)
}
}
}
- else {
+ else if (length-j > 0) {
client->curreceived += length-j;
writen(fd, (unsigned char*) (tab+ptr+j), length-j);
j += length-j;
@@ -342,7 +351,7 @@ read_message(int fd, int length, connection* client, char* tab, int ptr)
}
/*
- * Function name: clear sslFd
+ * Function name: clear_sslFd
* Description: Close the socket encapsulated in SslFd structure, remove this file descriptor
* from fd_set and clear ssl structure.
* Arguments: sf - pointer to SslFd structure
diff --git a/src/http_proxy_functions.h b/src/http_proxy_functions.h
index dac6065..386359c 100644
--- a/src/http_proxy_functions.h
+++ b/src/http_proxy_functions.h
@@ -34,6 +34,7 @@
#define C_POST_WAIT 1
#define C_GET_WAIT 2
#define C_OPEN 4
+#define C_DELAYED_A 8
#define H_TYPE_GET 0
#define H_TYPE_POST 1
diff --git a/src/http_proxy_server.c b/src/http_proxy_server.c
index 6da2c30..2bb2082 100644
--- a/src/http_proxy_server.c
+++ b/src/http_proxy_server.c
@@ -94,6 +94,7 @@ http_proxy_server(void *vptr)
int maxclients, tmp;
int timeout = 5;
socklen_t *addrlenp;
+ socklen_t addrlen;
char type, nothttp, https;
char *host, *serv, *name = "";
SSL_CTX* ctx;
@@ -111,9 +112,6 @@ http_proxy_server(void *vptr)
https = proxy_argptr->https;
ctx = proxy_argptr->ctx;
- broadcast_condition();
- end_critical_section();
-
if (https) {
name = "s";
}
@@ -167,6 +165,11 @@ http_proxy_server(void *vptr)
exit(1);
}
cliaddr = malloc(*addrlenp);
+ addrlen = (*addrlenp);
+ addrlenp = &addrlen;
+
+ broadcast_condition();
+ end_critical_section();
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
@@ -260,6 +263,26 @@ http_proxy_server(void *vptr)
table[i].received = 0;
clear_sslFd(table[i].postFd, &allset);
table[i].state |= C_POST_WAIT;
+
+ if (!(table[i].state & C_GET_WAIT)) {
+ aflog(LOG_T_MAIN, LOG_I_DDEBUG,
+ "http%s proxy: send A to table[%d].getfd", name, i);
+ if (table[i].sent_ptr+1 >= 90000) {
+ http_write(https, table[i].getFd, (unsigned char*) "A", 1);
+ table[i].sent_ptr = 0;
+ clear_sslFd(table[i].getFd, &allset);
+ FD_CLR(table[i].sockfd, &allset);
+ table[i].state |= C_GET_WAIT;
+ }
+ else {
+ http_write(https, table[i].getFd, (unsigned char*) "A", 1);
+ table[i].sent_ptr += 1;
+ }
+ }
+ else {
+ table[i].state |= C_DELAYED_A;
+ }
+
if (table[i].tmpstate == 1) {
aflog(LOG_T_MAIN, LOG_I_DEBUG,
"http%s proxy: get old POST request...", name);
@@ -414,6 +437,13 @@ http_proxy_server(void *vptr)
table[i].sent_ptr = table[i].length;
table[i].ptr = 0;
table[i].length = 0;
+ if (table[i].state & C_DELAYED_A) {
+ aflog(LOG_T_MAIN, LOG_I_DDEBUG,
+ "http%s proxy: send A to table[%d].getfd", name, i);
+ http_write(https, table[i].getFd, (unsigned char*) "A", 1);
+ table[i].sent_ptr += 1;
+ table[i].state &= ~C_DELAYED_A;
+ }
}
else if (hdr.type == H_TYPE_POST) {
aflog(LOG_T_MAIN, LOG_I_DEBUG,
@@ -470,9 +500,11 @@ http_proxy_server(void *vptr)
}
else {
aflog(LOG_T_MAIN, LOG_I_DEBUG,
- "http%s proxy: closing this connection...", name);
+ "http%s proxy: closing this connection... (not POST type)", name);
close_fd((&(connFd->fd)));
- SSL_clear(SslFd_get_ssl(connFd));
+ if (https) {
+ SSL_clear(SslFd_get_ssl(connFd));
+ }
continue;
}
}
@@ -492,7 +524,7 @@ http_proxy_server(void *vptr)
}
else {
aflog(LOG_T_MAIN, LOG_I_DEBUG,
- "http%s proxy: closing this connection...", name);
+ "http%s proxy: closing this connection... (no free slots)", name);
close_fd((&(connFd->fd)));
continue;
}
diff --git a/src/network.c b/src/network.c
index 23b8ee5..6a62a59 100644
--- a/src/network.c
+++ b/src/network.c
@@ -45,67 +45,69 @@
int
ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type)
{
+ const int on = 1;
#if defined(HAVE_GETADDRINFO) && defined(AF_INET6)
- int n;
- const int on = 1;
- struct addrinfo hints, *res, *ressave;
+ int n;
+ struct addrinfo hints, *res, *ressave;
aflog(LOG_T_INIT, LOG_I_DDEBUG,
"ip_listen: host=[%s] serv=[%s], type=[%d]", host, serv, type);
- bzero(&hints, sizeof(struct addrinfo));
- hints.ai_flags = AI_PASSIVE;
- if (type & 0x02) {
- hints.ai_family = AF_INET;
- }
- else if (type & 0x04) {
- hints.ai_family = AF_INET6;
- }
- else {
- hints.ai_family = AF_UNSPEC;
- }
-
- if (type & 0x01) {
- hints.ai_socktype = SOCK_STREAM;
- }
- else {
- hints.ai_socktype = SOCK_DGRAM;
- }
-
- if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
- return n;
- }
- ressave = res;
-
- do {
- (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if ((*sockfd) < 0) {
- continue; /* error, try next one */
- }
-
- if (type & 0x01) { /* tcp_listen */
- setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
- }
- if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) {
- break; /* success */
- }
-
- close((*sockfd)); /* bind error, close and try next one */
- } while ( (res = res->ai_next) != NULL);
-
- if (res == NULL) { /* errno from final socket() or bind() */
- return 1;
- }
-
- if (type & 0x01) { /* tcp_listen */
- listen((*sockfd), 1);
- }
-
- if (addrlenp) {
- *addrlenp = res->ai_addrlen; /* return size of protocol address */
- }
-
- freeaddrinfo(ressave);
+ bzero(&hints, sizeof(struct addrinfo));
+ hints.ai_flags = AI_PASSIVE;
+ if (type & 0x02) {
+ hints.ai_family = AF_INET;
+ }
+ else if (type & 0x04) {
+ hints.ai_family = AF_INET6;
+ }
+ else {
+ hints.ai_family = AF_UNSPEC;
+ }
+
+ if (type & 0x01) {
+ hints.ai_socktype = SOCK_STREAM;
+ }
+ else {
+ hints.ai_socktype = SOCK_DGRAM;
+ }
+
+ if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
+ return n;
+ }
+ ressave = res;
+
+ do {
+ (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if ((*sockfd) < 0) {
+ continue; /* error, try next one */
+ }
+
+ if (type & 0x01) { /* tcp_listen */
+ setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+ }
+
+ if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) {
+ break; /* success */
+ }
+
+ close((*sockfd)); /* bind error, close and try next one */
+ } while ( (res = res->ai_next) != NULL);
+
+ if (res == NULL) { /* errno from final socket() or bind() */
+ return 1;
+ }
+
+ if (type & 0x01) { /* tcp_listen */
+ listen((*sockfd), 1);
+ }
+
+ if (addrlenp) {
+ *addrlenp = res->ai_addrlen; /* return size of protocol address */
+ }
+
+ freeaddrinfo(ressave);
#else
struct sockaddr_in servaddr;
struct hostent* hostaddr = NULL;
@@ -142,6 +144,11 @@ ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp,
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
servaddr.sin_port = htons(port);
+
+ if (type & 0x01) { /* tcp_listen */
+ setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+ }
if (bind((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){
printf("bind failed\n");
@@ -151,6 +158,10 @@ ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp,
if (listen((*sockfd), 5)){
return 5;
}
+
+ if (addrlenp) {
+ *addrlenp = sizeof(servaddr); /* return size of protocol address */
+ }
#endif
return(0);
@@ -173,31 +184,32 @@ int
ip_connect(int* sockfd, const char *host, const char *serv, const char type,
const char *lhost, const char *lserv)
{
+ const int on = 1;
#if defined(HAVE_GETADDRINFO) && defined(AF_INET6)
- int n;
+ int n;
int bindFailed;
- struct addrinfo hints, *res, *ressave;
- struct addrinfo lhints, *lres, *lressave = NULL;
+ struct addrinfo hints, *res, *ressave;
+ struct addrinfo lhints, *lres, *lressave = NULL;
aflog(LOG_T_INIT, LOG_I_DDEBUG,
"ip_connect: host=[%s] serv=[%s], type=[%d], lhost=[%s], lserv=[%s]", host, serv, type, lhost, lserv);
- bzero(&hints, sizeof(struct addrinfo));
- if (type & 0x02) {
- hints.ai_family = AF_INET;
- }
- else if (type & 0x04) {
- hints.ai_family = AF_INET6;
- }
- else {
- hints.ai_family = AF_UNSPEC;
- }
- if (type & 0x01) {
- hints.ai_socktype = SOCK_STREAM;
- }
- else {
- hints.ai_socktype = SOCK_DGRAM;
- }
+ bzero(&hints, sizeof(struct addrinfo));
+ if (type & 0x02) {
+ hints.ai_family = AF_INET;
+ }
+ else if (type & 0x04) {
+ hints.ai_family = AF_INET6;
+ }
+ else {
+ hints.ai_family = AF_UNSPEC;
+ }
+ if (type & 0x01) {
+ hints.ai_socktype = SOCK_STREAM;
+ }
+ else {
+ hints.ai_socktype = SOCK_DGRAM;
+ }
lhints = hints;
@@ -208,16 +220,20 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type,
lressave = lres;
}
- if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
- return n;
- }
- ressave = res;
+ if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
+ return n;
+ }
+ ressave = res;
- do {
- (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if ((*sockfd) < 0) {
- continue; /* ignore this one */
- }
+ do {
+ (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if ((*sockfd) < 0) {
+ continue; /* ignore this one */
+ }
+
+ if (type & 0x01) { /* tcp_connect */
+ setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+ }
bindFailed = 0;
if (lhost || lserv) {
@@ -226,31 +242,31 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type,
do {
if (bind((*sockfd), lres->ai_addr, lres->ai_addrlen) == 0) {
bindFailed = 0;
- break; /* success */
+ break; /* success */
}
} while ( (lres = lres->ai_next) != NULL);
}
if (bindFailed == 1) {
- close((*sockfd)); /* ignore this one */
+ close((*sockfd)); /* ignore this one */
continue;
}
if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) {
- break; /* success */
- }
+ break; /* success */
+ }
- close((*sockfd)); /* ignore this one */
- } while ( (res = res->ai_next) != NULL);
+ close((*sockfd)); /* ignore this one */
+ } while ( (res = res->ai_next) != NULL);
- if (res == NULL) { /* errno set from final connect() */
- return 1;
- }
+ if (res == NULL) { /* errno set from final connect() */
+ return 1;
+ }
if (lhost || lserv) {
- freeaddrinfo(lressave);
+ freeaddrinfo(lressave);
}
- freeaddrinfo(ressave);
+ freeaddrinfo(ressave);
#else
struct sockaddr_in servaddr, lservaddr;
struct hostent* hostaddr;
@@ -282,6 +298,10 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type,
servaddr.sin_port = htons(port);
memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length);
+ if (type & 0x01) { /* tcp_connect */
+ setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+ }
+
if (lhost || lserv) {
memset(&lservaddr, 0, sizeof(lservaddr));
lservaddr.sin_family = AF_INET;
@@ -309,7 +329,7 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type,
}
#endif
- return(0);
+ return(0);
}
/*
@@ -327,96 +347,96 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type,
char *
sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portbuf, char type)
{
- char portstr[7];
- static char str[136]; /* Unix domain is largest */
+ char portstr[7];
+ static char str[136]; /* Unix domain is largest */
- switch (sa->sa_family) {
- case AF_INET: {
- struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ switch (sa->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
- if (type) {
+ if (type) {
#ifdef HAVE_GETNAMEINFO
- if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) {
- return NULL;
- }
+ if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) {
+ return NULL;
+ }
#else
- struct hostent* hostname;
- if ((hostname = gethostbyaddr((void*) &sin->sin_addr, sizeof(struct in_addr), AF_INET))) {
- strncpy(str, hostname->h_name, 127);
- str[127] = 0;
- }
- else {
- if (inet_ntop(AF_INET, (void*) &sin->sin_addr, str, sizeof(str)) == NULL) {
- return NULL;
- }
- }
+ struct hostent* hostname;
+ if ((hostname = gethostbyaddr((void*) &sin->sin_addr, sizeof(struct in_addr), AF_INET))) {
+ strncpy(str, hostname->h_name, 127);
+ str[127] = 0;
+ }
+ else {
+ if (inet_ntop(AF_INET, (void*) &sin->sin_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
#endif
- }
- else {
- if (inet_ntop(AF_INET, (void*) &sin->sin_addr, str, sizeof(str)) == NULL) {
- return NULL;
- }
- }
- if (namebuf) {
- memcpy(namebuf, str, 128);
- }
- if (ntohs(sin->sin_port) != 0) {
- snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port));
- if (portbuf) {
- snprintf(portbuf, 7, "%d", ntohs(sin->sin_port));
- }
- strcat(str, portstr);
- }
- return(str);
- }
+ }
+ else {
+ if (inet_ntop(AF_INET, (void*) &sin->sin_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
+ if (namebuf) {
+ memcpy(namebuf, str, 128);
+ }
+ if (ntohs(sin->sin_port) != 0) {
+ snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port));
+ if (portbuf) {
+ snprintf(portbuf, 7, "%d", ntohs(sin->sin_port));
+ }
+ strcat(str, portstr);
+ }
+ return(str);
+ }
#ifdef AF_INET6
- case AF_INET6: {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
- if (type) {
+ if (type) {
#ifdef HAVE_GETNAMEINFO
- if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) {
- return NULL;
- }
+ if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) {
+ return NULL;
+ }
#else
- struct hostent* hostname;
- if ((hostname = gethostbyaddr(&sin6->sin6_addr, sizeof(struct in6_addr), AF_INET6))) {
- strncpy(str, hostname->h_name, 127);
- str[127] = 0;
- }
- else {
- if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) {
- return NULL;
- }
- }
+ struct hostent* hostname;
+ if ((hostname = gethostbyaddr(&sin6->sin6_addr, sizeof(struct in6_addr), AF_INET6))) {
+ strncpy(str, hostname->h_name, 127);
+ str[127] = 0;
+ }
+ else {
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
#endif
- }
- else {
- if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) {
- return NULL;
- }
- }
- if (namebuf) {
- memcpy(namebuf, str, 128);
- }
- if (ntohs(sin6->sin6_port) != 0) {
- snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port));
- if (portbuf) {
- snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port));
- }
- strcat(str, portstr);
- }
- return(str);
- }
+ }
+ else {
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
+ if (namebuf) {
+ memcpy(namebuf, str, 128);
+ }
+ if (ntohs(sin6->sin6_port) != 0) {
+ snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port));
+ if (portbuf) {
+ snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port));
+ }
+ strcat(str, portstr);
+ }
+ return(str);
+ }
#endif
- default: {
- snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen);
- return(str);
- }
- }
- return NULL;
+ default: {
+ snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen);
+ return(str);
+ }
+ }
+ return NULL;
}
/*
@@ -431,21 +451,21 @@ sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portb
int
SSL_writen(SSL* fd, unsigned char* buf, int amount)
{
- int sent, n;
- sent = 0;
+ int sent, n;
+ sent = 0;
assert(amount > 0);
- while (sent < amount) {
- n = SSL_write(fd, buf+sent, amount - sent);
+ while (sent < amount) {
+ n = SSL_write(fd, buf+sent, amount - sent);
assert(n != 0);
- if (n != -1) {
- sent += n;
- }
- if (n == -1) {
- if (errno != EAGAIN)
- return 0;
- }
- }
- return amount;
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
}
/*
@@ -460,22 +480,22 @@ SSL_writen(SSL* fd, unsigned char* buf, int amount)
int
SSL_readn(SSL* fd, unsigned char* buf, int amount)
{
- int sent, n;
- sent = 0;
+ int sent, n;
+ sent = 0;
assert(amount > 0);
- while (sent < amount) {
- n = SSL_read(fd, buf+sent, amount - sent);
- if (n != -1) {
- sent += n;
- }
- if (n == 0)
- return 0;
- if (n == -1) {
- if (errno != EAGAIN)
- return 0;
- }
- }
- return amount;
+ while (sent < amount) {
+ n = SSL_read(fd, buf+sent, amount - sent);
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == 0)
+ return 0;
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
}
/*
@@ -490,21 +510,21 @@ SSL_readn(SSL* fd, unsigned char* buf, int amount)
int
writen(int fd, unsigned char* buf, int amount)
{
- int sent, n;
- sent = 0;
+ int sent, n;
+ sent = 0;
assert(amount > 0);
- while (sent < amount) {
- n = write(fd, buf+sent, amount - sent);
+ while (sent < amount) {
+ n = write(fd, buf+sent, amount - sent);
assert(n != 0);
- if (n != -1) {
- sent += n;
- }
- if (n == -1) {
- if (errno != EAGAIN)
- return 0;
- }
- }
- return amount;
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
}
/*
@@ -519,21 +539,21 @@ writen(int fd, unsigned char* buf, int amount)
int
readn(int fd, unsigned char* buf, int amount)
{
- int sent, n;
- sent = 0;
+ int sent, n;
+ sent = 0;
assert(amount > 0);
- while (sent < amount) {
- n = read(fd, buf+sent, amount - sent);
- if (n != -1) {
- sent += n;
- }
- if (n == 0)
- return 0;
- if (n == -1) {
- if (errno != EAGAIN)
- return 0;
- }
- }
- return amount;
+ while (sent < amount) {
+ n = read(fd, buf+sent, amount - sent);
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == 0)
+ return 0;
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
}
diff --git a/src/remove_client_task.c b/src/remove_client_task.c
new file mode 100644
index 0000000..b91e071
--- /dev/null
+++ b/src/remove_client_task.c
@@ -0,0 +1,134 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "logging.h"
+#include "realmnames.h"
+#include "clientnames.h"
+#include "server_remove.h"
+#include "remove_client_task.h"
+
+/*
+ * Function name: RCTdata_new
+ * Description: Creates and initializes new data for remove client task.
+ * Arguments: config - server configuration
+ * realm - the realm id
+ * client - the client id
+ * ra - if the client is in remote administration mode
+ * fdset - the descriptor set watched for read
+ * Returns: Pointer to newly created RCTdata structure.
+ */
+
+RCTdata*
+RCTdata_new(ServerConfiguration* config, int realm, int client, char ra, char reason, fd_set* set, fd_set* wset)
+{
+ RCTdata* tmp;
+ assert(config != NULL);
+ if (config == NULL) {
+ return NULL;
+ }
+ tmp = calloc(1, sizeof(RCTdata));
+ assert(tmp != NULL);
+ if (tmp == NULL) {
+ return NULL;
+ }
+ tmp->config = config;
+ tmp->realm = realm;
+ tmp->client = client;
+ tmp->ra = ra;
+ tmp->reason = reason;
+ tmp->set = set;
+ tmp->wset = wset;
+
+ return tmp;
+}
+
+/*
+ * Function name: RCTdata_free
+ * Description: Frees the memory allocated for RCTdata structure.
+ * Arguments: ptr - pointer to pointer to RCTdata structure
+ */
+
+void
+RCTdata_free(void** ptr)
+{
+ RCTdata** data = (RCTdata**) ptr;
+ assert(data != NULL);
+ if (data == NULL) {
+ return;
+ }
+ assert((*data) != NULL);
+ if ((*data) == NULL) {
+ return;
+ }
+ free((*data));
+ (*data) = NULL;
+}
+
+/*
+ * Function name: RCTfunction
+ * Description: Function executed in the task by the task scheduler.
+ * Arguments: Pointer to the memory containing RCTdata structure.
+ */
+
+void
+RCTfunction(void* data)
+{
+ ConnectClient** clientsTable;
+ ServerRealm** realmsTable;
+ RCTdata* ptr;
+ assert(data != NULL);
+ if (data == NULL) {
+ return;
+ }
+ ptr = (RCTdata*) data;
+ realmsTable = ServerConfiguration_get_realmsTable(ptr->config);
+ if (ptr->ra) {
+ clientsTable = ServerRealm_get_raClientsTable(realmsTable[ptr->realm]);
+ }
+ else {
+ clientsTable = ServerRealm_get_clientsTable(realmsTable[ptr->realm]);
+ }
+ switch (ptr->reason) {
+ case RCT_REASON_TIMEOUT:
+ close(SslFd_get_fd(ConnectClient_get_sslFd(clientsTable[ptr->client])));
+ FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(clientsTable[ptr->client])), ptr->set);
+ SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(clientsTable[ptr->client])));
+ ConnectClient_set_state(clientsTable[ptr->client], CONNECTCLIENT_STATE_FREE);
+ ServerRealm_decrease_connectedClients(realmsTable[ptr->realm]);
+ aflog(LOG_T_CLIENT, LOG_I_WARNING,
+ "realm[%s]: Client[%s]%s: SSL_accept failed (timeout)",
+ get_realmname(ptr->config, ptr->realm),
+ ptr->ra ? get_raclientname(realmsTable[ptr->realm], ptr->client) :
+ get_clientname(realmsTable[ptr->realm], ptr->client),
+ ptr->ra ? " (ra)" : "");
+ break;
+ case RCT_REASON_MAXIDLE:
+ aflog(LOG_T_CLIENT, LOG_I_WARNING,
+ "realm[%s]: Client[%s]: too long idle --> DROPPING", get_realmname(ptr->config, ptr->realm),
+ get_clientname(realmsTable[ptr->realm], ptr->client));
+ remove_client(realmsTable[ptr->realm], ptr->client, ptr->set, ptr->wset, NULL);
+ }
+ ConnectClient_set_task(clientsTable[ptr->client], NULL);
+}
diff --git a/src/remove_client_task.h b/src/remove_client_task.h
new file mode 100644
index 0000000..44f98aa
--- /dev/null
+++ b/src/remove_client_task.h
@@ -0,0 +1,47 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _JS_REMOVE_CLIENT_TASK_H
+#define _JS_REMOVE_CLIENT_TASK_H
+
+#define RCT_REASON_TIMEOUT 0
+#define RCT_REASON_MAXIDLE 1
+
+#include "server_configuration_struct.h"
+
+typedef struct {
+ ServerConfiguration* config;
+ int realm;
+ int client;
+ char ra;
+ char reason;
+ fd_set* set;
+ fd_set* wset;
+} RCTdata;
+
+/* 'constructor' */
+RCTdata* RCTdata_new(ServerConfiguration* config, int realm, int client, char ra, char reason,
+ fd_set* set, fd_set* wset);
+/* 'destructor' */
+void RCTdata_free(void** data);
+/* other */
+void RCTfunction(void*);
+
+#endif
diff --git a/src/server_realm_struct.c b/src/server_realm_struct.c
index f3f06c0..4220600 100644
--- a/src/server_realm_struct.c
+++ b/src/server_realm_struct.c
@@ -262,6 +262,23 @@ ServerRealm_set_sTimeout(ServerRealm* sr, char* sTimeout)
}
/*
+ * Function name: ServerRealm_set_sMaxIdle
+ * Description: Sets max idle value description.
+ * Arguments: sr - pointer to ServerRealm structure
+ * sMaxIdle - max idle value description
+ */
+
+void
+ServerRealm_set_sMaxIdle(ServerRealm* sr, char* sMaxIdle)
+{
+ assert(sr != NULL);
+ if (sr == NULL) {
+ return;
+ }
+ string_cp(&(sr->sMaxIdle), sMaxIdle);
+}
+
+/*
* Function name: ServerRealm_set_realmName
* Description: Set realm's name.
* Arguments: sr - pointer to ServerRealm structure
@@ -432,6 +449,23 @@ ServerRealm_set_timeout(ServerRealm* sr, int timeout)
}
/*
+ * Function name: ServerRealm_set_maxIdle
+ * Description: Sets mas idle value.
+ * Arguments: sr - pointer to ServerRealm structure
+ * maxIdle - max idle value
+ */
+
+void
+ServerRealm_set_maxIdle(ServerRealm* sr, int maxIdle)
+{
+ assert(sr != NULL);
+ if (sr == NULL) {
+ return;
+ }
+ sr->maxIdle = maxIdle;
+}
+
+/*
* Function name: ServerRealm_set_clientMode
* Description: Set client mode.
* Arguments: sr - pointer to ServerRealm structure
@@ -850,6 +884,23 @@ ServerRealm_get_sTimeout(ServerRealm* sr)
}
/*
+ * Function name: ServerRealm_get_sMaxIdle
+ * Description: Gets max idle value description.
+ * Arguments: sr - pointer to ServerRealm structure
+ * Returns: Max idle value description.
+ */
+
+char*
+ServerRealm_get_sMaxIdle(ServerRealm* sr)
+{
+ assert(sr != NULL);
+ if (sr == NULL) {
+ return NULL;
+ }
+ return sr->sMaxIdle;
+}
+
+/*
* Function name: ServerRealm_get_realmName
* Description: Get realm's name.
* Arguments: sr - pointer to ServerRealm structure
@@ -1020,6 +1071,23 @@ ServerRealm_get_timeout(ServerRealm* sr)
}
/*
+ * Function name: ServerRealm_get_maxIdle
+ * Description: Gets max idle value.
+ * Arguments: sr - pointer to ServerRealm structure
+ * Returns: Max idle value.
+ */
+
+int
+ServerRealm_get_maxIdle(ServerRealm* sr)
+{
+ assert(sr != NULL);
+ if (sr == NULL) {
+ return 0;
+ }
+ return sr->maxIdle;
+}
+
+/*
* Function name: ServerRealm_get_clientMode
* Description: Get client mode.
* Arguments: sr - pointer to ServerRealm structure
diff --git a/src/server_realm_struct.h b/src/server_realm_struct.h
index 0d61517..4ca21c1 100644
--- a/src/server_realm_struct.h
+++ b/src/server_realm_struct.h
@@ -31,6 +31,7 @@ typedef struct {
char* sUsersPerClient;
char* sClientMode;
char* sTimeout;
+ char* sMaxIdle;
char* realmName;
unsigned char password[4];
int connectedUsers;
@@ -41,6 +42,7 @@ typedef struct {
int raClientsLimit;
int usersPerClient;
int timeout;
+ int maxIdle;
int clientMode;
int userClientPairs;
int clientsCounter;
@@ -70,6 +72,7 @@ void ServerRealm_set_sRaClientsLimit(ServerRealm* sr, char* sRaClientsLimit);
void ServerRealm_set_sUsersPerClient(ServerRealm* sr, char* sUsersPerClient);
void ServerRealm_set_sClientMode(ServerRealm* sr, char* sClientMode);
void ServerRealm_set_sTimeout(ServerRealm* sr, char* sTimeout);
+void ServerRealm_set_sMaxIdle(ServerRealm* sr, char* sMaxIdle);
void ServerRealm_set_realmName(ServerRealm* sr, char* realmName);
void ServerRealm_set_password(ServerRealm* sr, unsigned char* password);
void ServerRealm_set_connectedUsers(ServerRealm* sr, int connectedUsers);
@@ -80,6 +83,7 @@ void ServerRealm_set_connectedRaClients(ServerRealm* sr, int connectedRaClients)
void ServerRealm_set_raClientsLimit(ServerRealm* sr, int raClientsLimit);
void ServerRealm_set_usersPerClient(ServerRealm* sr, int usersPerClient);
void ServerRealm_set_timeout(ServerRealm* sr, int timeout);
+void ServerRealm_set_maxIdle(ServerRealm* sr, int maxIdle);
void ServerRealm_set_clientMode(ServerRealm* sr, int clientMode);
void ServerRealm_set_userClientPairs(ServerRealm* sr, int userClientPairs);
void ServerRealm_set_clientsCounter(ServerRealm* sr, int clientsCounter);
@@ -103,6 +107,7 @@ char* ServerRealm_get_sRaClientsLimit(ServerRealm* sr);
char* ServerRealm_get_sUsersPerClient(ServerRealm* sr);
char* ServerRealm_get_sClientMode(ServerRealm* sr);
char* ServerRealm_get_sTimeout(ServerRealm* sr);
+char* ServerRealm_get_sMaxIdle(ServerRealm* sr);
char* ServerRealm_get_realmName(ServerRealm* sr);
unsigned char* ServerRealm_get_password(ServerRealm* sr);
int ServerRealm_get_connectedUsers(ServerRealm* sr);
@@ -113,6 +118,7 @@ int ServerRealm_get_connectedRaClients(ServerRealm* sr);
int ServerRealm_get_raClientsLimit(ServerRealm* sr);
int ServerRealm_get_usersPerClient(ServerRealm* sr);
int ServerRealm_get_timeout(ServerRealm* sr);
+int ServerRealm_get_maxIdle(ServerRealm* sr);
int ServerRealm_get_clientMode(ServerRealm* sr);
int ServerRealm_get_userClientPairs(ServerRealm* sr);
int ServerRealm_get_clientsCounter(ServerRealm* sr);
diff --git a/src/server_remoteadmin.c b/src/server_remoteadmin.c
index 6c2a4a3..c52bf98 100644
--- a/src/server_remoteadmin.c
+++ b/src/server_remoteadmin.c
@@ -367,6 +367,12 @@ serve_admin(ServerConfiguration* config, int realm, int client, unsigned char* b
}
add_to_message(buff, "climode: %s", ServerRealm_get_sClientMode(pointer));
add_to_message(buff, "timeout: %d", ServerRealm_get_timeout(pointer));
+ if (ServerRealm_get_maxIdle(pointer)) {
+ add_to_message(buff, "max idle: %d", ServerRealm_get_maxIdle(pointer));
+ }
+ else {
+ add_to_message(buff, "max idle: disabled");
+ }
add_to_message(buff, "baseport: %s", ServerRealm_get_basePortOn(pointer) ?
"yes" : "no");
add_to_message(buff, "audit: %s", ServerRealm_get_auditOn(pointer) ?
@@ -431,6 +437,8 @@ serve_admin(ServerConfiguration* config, int realm, int client, unsigned char* b
ConnectClient_get_usrCliPair(cpointer));
tmp = now - ConnectClient_get_connectTime(cpointer);
add_uptime_to_message(buff, "Connection time", tmp);
+ tmp = now - ConnectClient_get_lastActivity(cpointer);
+ add_uptime_to_message(buff, "Idle time", tmp);
add_to_message(buff, "Id: %s",
(ConnectClient_get_sClientId(cpointer) == NULL) ? "" :
ConnectClient_get_sClientId(cpointer));
diff --git a/src/server_remove.c b/src/server_remove.c
index 8a66813..93dcf15 100644
--- a/src/server_remove.c
+++ b/src/server_remove.c
@@ -29,19 +29,19 @@
* client - the client number
* set - the set of file descriptors for reading
* wset - the set of file descriptors for writing
- * con - the connection counter
+ * scheduler - the task scheduler
*/
void
-remove_client(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, int* con)
+remove_client(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, TaskScheduler* scheduler)
{
int i;
+ Task* task;
assert(ptr != NULL);
assert(client >= 0);
assert(set != NULL);
assert(wset != NULL);
- assert(con != NULL);
if (ConnectClient_get_state(ServerRealm_get_clientsTable(ptr)[client]) == CONNECTCLIENT_STATE_ACCEPTED) {
for (i = 0; i < ServerRealm_get_usersLimit(ptr); ++i) {
@@ -67,8 +67,11 @@ remove_client(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, int* con)
ConnectClient_set_connected(ServerRealm_get_clientsTable(ptr)[client], 0);
close(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_clientsTable(ptr)[client])));
FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_clientsTable(ptr)[client])), set);
- if (ConnectClient_get_state(ServerRealm_get_clientsTable(ptr)[client]) == CONNECTCLIENT_STATE_AUTHORIZING) {
- (*con)--;
+ if (scheduler) {
+ if ((task = ConnectClient_get_task(ServerRealm_get_clientsTable(ptr)[client]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(ServerRealm_get_clientsTable(ptr)[client], NULL);
+ }
}
SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(ServerRealm_get_clientsTable(ptr)[client])));
ConnectClient_set_state(ServerRealm_get_clientsTable(ptr)[client], CONNECTCLIENT_STATE_FREE);
@@ -82,19 +85,19 @@ remove_client(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, int* con)
* client - the client number
* set - the set of file descriptors for reading
* wset - the set of file descriptors for writing
- * con - the connection counter
+ * scheduler - the task scheduler
*/
void
-remove_raclient(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, int* con)
+remove_raclient(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, TaskScheduler* scheduler)
{
int i;
+ Task* task;
assert(ptr != NULL);
assert(client >= 0);
assert(set != NULL);
assert(wset != NULL);
- assert(con != NULL);
for (i = 0; i < ConnectClient_get_limit(ServerRealm_get_raClientsTable(ptr)[client]); ++i) {
ConnectClient_get_users(ServerRealm_get_raClientsTable(ptr)[client])[i] = -1;
@@ -103,8 +106,11 @@ remove_raclient(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, int* co
ConnectClient_set_connected(ServerRealm_get_raClientsTable(ptr)[client], 0);
close(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(ptr)[client])));
FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(ptr)[client])), set);
- if (ConnectClient_get_state(ServerRealm_get_raClientsTable(ptr)[client]) == CONNECTCLIENT_STATE_AUTHORIZING) {
- (*con)--;
+ if (scheduler) {
+ if ((task = ConnectClient_get_task(ServerRealm_get_clientsTable(ptr)[client]))) {
+ TaskScheduler_removeTask(scheduler, task);
+ ConnectClient_set_task(ServerRealm_get_clientsTable(ptr)[client], NULL);
+ }
}
SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(ptr)[client])));
ServerRealm_decrease_connectedClients(ptr);
diff --git a/src/server_remove.h b/src/server_remove.h
index 31dbe5c..7c745ac 100644
--- a/src/server_remove.h
+++ b/src/server_remove.h
@@ -19,12 +19,13 @@
*/
#include "file.h"
+#include "task_scheduler_struct.h"
#ifndef _JS_SERVER_REMOVE_H
#define _JS_SERVER_REMOVE_H
-void remove_client(ServerRealm*, int, fd_set*, fd_set*, int*);
-void remove_raclient(ServerRealm*, int, fd_set*, fd_set*, int*);
+void remove_client(ServerRealm*, int, fd_set*, fd_set*, TaskScheduler* scheduler);
+void remove_raclient(ServerRealm*, int, fd_set*, fd_set*, TaskScheduler* scheduler);
#endif
diff --git a/src/task_list_node_struct.c b/src/task_list_node_struct.c
new file mode 100644
index 0000000..70f43ef
--- /dev/null
+++ b/src/task_list_node_struct.c
@@ -0,0 +1,124 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "task_list_node_struct.h"
+
+/*
+ * Function name: TaskListNode_new
+ * Description: Creates and initializes new task list node. The task must point
+ * at previously allocated Task structure.
+ * Arguments: task - pointer to Task structure, which must be previously initialized
+ * Returns: Pointer to newly created TaskListNode structure.
+ */
+
+TaskListNode*
+TaskListNode_new(Task* task)
+{
+ TaskListNode* tmp = calloc(1, sizeof(TaskListNode));
+ assert(task != NULL);
+ if (task == NULL) {
+ return NULL;
+ }
+ assert(tmp != NULL);
+ if (tmp == NULL) {
+ return NULL;
+ }
+ tmp->task = task;
+
+ return tmp;
+}
+
+/*
+ * Function name: TaskListNode_free
+ * Description: Frees the memory allocated for TaskListNode structure.
+ * Arguments: node - pointer to pointer to TaskListNode structure
+ */
+
+void
+TaskListNode_free(TaskListNode** node)
+{
+ assert(node != NULL);
+ if (node == NULL) {
+ return;
+ }
+ assert((*node) != NULL);
+ if ((*node) == NULL) {
+ return;
+ }
+
+ free((*node));
+ (*node) = NULL;
+}
+
+/*
+ * Function name: TaskListNode_set_next
+ * Description: Sets the next pointer of the task list node.
+ * Arguments: node - pointer to TaskListNode structure
+ * next - the new next pointer
+ */
+
+void
+TaskListNode_set_next(TaskListNode* node, TaskListNode* next)
+{
+ assert(node != NULL);
+ if (node == NULL) {
+ return;
+ }
+ node->next = next;
+}
+
+/*
+ * Function name: TaskListNode_set_previous
+ * Description: Sets the previous pointer of the task list node.
+ * Arguments: node - pointer to TaskListNode structure
+ * next - the new previous pointer
+ */
+
+void
+TaskListNode_set_previous(TaskListNode* node, TaskListNode* previous)
+{
+ assert(node != NULL);
+ if (node == NULL) {
+ return;
+ }
+ node->previous = previous;
+}
+
+/*
+ * Function name: TaskListNode_get_task
+ * Description: Returns the task contained in this node.
+ * Arguments: node - pointer to TaskListNode structure
+ * Returns: The task contained in this node.
+ */
+
+Task*
+TaskListNode_get_task(TaskListNode* node)
+{
+ assert(node != NULL);
+ if (node == NULL) {
+ return NULL;
+ }
+ return node->task;
+}
diff --git a/src/task_list_node_struct.h b/src/task_list_node_struct.h
new file mode 100644
index 0000000..2e0cb7a
--- /dev/null
+++ b/src/task_list_node_struct.h
@@ -0,0 +1,42 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _JS_TASK_LIST_NODE_STRUCT_H
+#define _JS_TASK_LIST_NODE_STRUCT_H
+
+#include "task_struct.h"
+
+typedef struct tlnode{
+ Task* task;
+ struct tlnode* previous;
+ struct tlnode* next;
+} TaskListNode;
+
+/* 'constructor' */
+TaskListNode* TaskListNode_new(Task* task);
+/* 'destructor' */
+void TaskListNode_free(TaskListNode** node);
+/* setters */
+void TaskListNode_set_next(TaskListNode* node, TaskListNode* next);
+void TaskListNode_set_previous(TaskListNode* node, TaskListNode* previous);
+/* getters */
+Task* TaskListNode_get_task(TaskListNode* node);
+
+#endif
diff --git a/src/task_scheduler_struct.c b/src/task_scheduler_struct.c
new file mode 100644
index 0000000..b96a919
--- /dev/null
+++ b/src/task_scheduler_struct.c
@@ -0,0 +1,321 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "timeval_functions.h"
+#include "task_scheduler_struct.h"
+
+/*
+ * Function name: TaskScheduler_new
+ * Description: Creates and initializes task scheduler.
+ * Returns: Pointer to newly created TaskScheduler structure.
+ */
+
+TaskScheduler*
+TaskScheduler_new()
+{
+ TaskScheduler* tmp = calloc(1, sizeof(TaskScheduler));
+ assert(tmp != NULL);
+ if (tmp == NULL) {
+ return NULL;
+ }
+
+ return tmp;
+}
+
+/*
+ * Function name: TaskScheduler_free
+ * Description: Frees the memory allocated for TaskScheduler structure.
+ * Arguments: scheduler - pointer to pointer to TaskScheduler structure
+ */
+
+void
+TaskScheduler_free(TaskScheduler** scheduler)
+{
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return;
+ }
+ assert((*scheduler) != NULL);
+ if ((*scheduler) == NULL) {
+ return;
+ }
+
+ while ((*scheduler)->head) {
+ TaskScheduler_removeTask((*scheduler), TaskListNode_get_task((*scheduler)->head));
+ }
+
+ free((*scheduler));
+ (*scheduler) = NULL;
+}
+
+/*
+ * Function name: TaskScheduler_get_actualTimer
+ * Description: Returns the smallest timeval structure in the scheduler.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * Returns: The smallest timeval structure in the scheduler.
+ */
+
+struct timeval*
+TaskScheduler_get_actualTimer(TaskScheduler* scheduler)
+{
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return NULL;
+ }
+ return Task_get_timer(TaskListNode_get_task(scheduler->actualTask));
+}
+
+/*
+ * Function name: TaskScheduler_hasMoreTasks
+ * Description: Checks if there is more tasks in the scheduler.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * Returns: 0 - there is no more tasks in the scheduler,
+ * n>0 - there is more (n) tasks in the scheduler.
+ */
+
+int
+TaskScheduler_hasMoreTasks(TaskScheduler* scheduler)
+{
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return 0;
+ }
+ return scheduler->numberOfTasks;
+}
+
+/*
+ * Function name: TaskScheduler_addTask
+ * Description: Adds the task to the scheduler.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * task - the task to add to the scheduler
+ * Returns: 0 - the task has been added successfully,
+ * 1 - the task has NOT been added.
+ */
+
+int
+TaskScheduler_addTask(TaskScheduler* scheduler, Task* task)
+{
+ TaskListNode* tmp;
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return 1;
+ }
+ assert(task != NULL);
+ if (task == NULL) {
+ return 1;
+ }
+ tmp = TaskListNode_new(task);
+ assert(tmp != NULL);
+ if (tmp == NULL) {
+ return 1;
+ }
+ if (scheduler->head) {
+ TaskListNode_set_next(tmp, scheduler->head);
+ TaskListNode_set_previous(scheduler->head, tmp);
+ }
+ scheduler->head = tmp;
+ scheduler->numberOfTasks += 1;
+ if (scheduler->actualTask) {
+ if (timeval_compare(TaskScheduler_get_actualTimer(scheduler), Task_get_timer(task)) > 0) {
+ scheduler->actualTask = tmp;
+ }
+ }
+ else {
+ scheduler->actualTask = tmp;
+ }
+ return 0;
+}
+
+/*
+ * Function name: find_tasknode_with_minimal_timer
+ * Description: Finds the task list node with minimal timer.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * Returns: The task list node with minimal timer.
+ */
+static TaskListNode*
+find_tasknode_with_minimal_timer(TaskScheduler* scheduler)
+{
+ TaskListNode* iterator;
+ TaskListNode* candidate;
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return NULL;
+ }
+ if (scheduler->head == NULL) {
+ return NULL;
+ }
+ candidate = scheduler->head;
+ iterator = scheduler->head;
+ iterator = iterator->next;
+ while (iterator) {
+ if (timeval_compare(Task_get_timer(TaskListNode_get_task(iterator)),
+ Task_get_timer(TaskListNode_get_task(candidate))) == -1) {
+ candidate = iterator;
+ }
+ iterator = iterator->next;
+ }
+ return candidate;
+}
+
+/*
+ * Function name: TaskScheduler_removeTask
+ * Description: Removes the task from the scheduler.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * task - the task to remove from the scheduler
+ * Returns: 0 - the task has been removed successfully,
+ * 1 - the task has NOT been removed (probably there was no such task in the scheduler).
+ */
+
+int
+TaskScheduler_removeTask(TaskScheduler* scheduler, Task* task)
+{
+ TaskListNode* iterator;
+ Task* tmp;
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return 1;
+ }
+ assert(task != NULL);
+ if (task == NULL) {
+ return 1;
+ }
+ iterator = scheduler->head;
+ while (iterator) {
+ tmp = TaskListNode_get_task(iterator);
+ if (tmp == task) {
+ if (iterator->previous) {
+ TaskListNode_set_next(iterator->previous, iterator->next);
+ }
+ if (iterator->next) {
+ TaskListNode_set_previous(iterator->next, iterator->previous);
+ }
+ if (iterator == scheduler->head) {
+ scheduler->head = iterator->next;
+ }
+ if (iterator == scheduler->actualTask) {
+ scheduler->actualTask = find_tasknode_with_minimal_timer(scheduler);
+ }
+ scheduler->numberOfTasks -= 1;
+ TaskListNode_free(&iterator);
+ return 0;
+ }
+ iterator = iterator->next;
+ }
+ return 1;
+}
+
+/*
+ * Function name: TaskScheduler_startWatching
+ * Description: Starts counting the time for the actual timer.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * Returns: 0 - success,
+ * 1 - failure.
+ */
+
+int
+TaskScheduler_startWatching(TaskScheduler* scheduler)
+{
+ struct timeval* tmp;
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return 1;
+ }
+ tmp = TaskScheduler_get_actualTimer(scheduler);
+ assert(tmp != NULL);
+ if (tmp == NULL) {
+ return 1;
+ }
+ scheduler->delta = *tmp;
+ return 0;
+}
+
+/*
+ * Function name: TaskScheduler_stopWatching
+ * Description: Stops counting the time for the actual timer.
+ * Updates all the timers and destroys them if needed.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * Returns: 0 - success,
+ * 1 - failure.
+ */
+
+int
+TaskScheduler_stopWatching(TaskScheduler* scheduler)
+{
+ TaskListNode* iterator;
+ TaskListNode* actualTask;
+ Task* backup;
+ struct timeval* tmp;
+ int result;
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return 1;
+ }
+ tmp = TaskScheduler_get_actualTimer(scheduler);
+ assert(tmp != NULL);
+ if (tmp == NULL) {
+ return 1;
+ }
+ if (timeval_subtract(&(scheduler->delta), tmp)) {
+ return 1;
+ }
+ actualTask = scheduler->actualTask;
+ assert(scheduler->actualTask != NULL);
+ iterator = scheduler->head;
+ while (iterator) {
+ if (iterator != actualTask) {
+ result = timeval_subtract(Task_get_timer(TaskListNode_get_task(iterator)), &(scheduler->delta));
+ assert(result == 0);
+ }
+ if (timeval_lq_zero(Task_get_timer(TaskListNode_get_task(iterator)))) {
+ Task_exec(TaskListNode_get_task(iterator));
+ backup = TaskListNode_get_task(iterator);
+ iterator = iterator->next;
+ TaskScheduler_removeTask(scheduler, backup);
+ continue;
+ }
+ iterator = iterator->next;
+ }
+ TaskScheduler_update(scheduler);
+ return 0;
+}
+
+/*
+ * Function name: TaskScheduler_update
+ * Description: Updates the actual timer.
+ * Arguments: scheduler - pointer to TaskScheduler structure
+ * Returns: 0 - success,
+ * 1 - failure.
+ */
+
+int
+TaskScheduler_update(TaskScheduler* scheduler)
+{
+ assert(scheduler != NULL);
+ if (scheduler == NULL) {
+ return 1;
+ }
+ scheduler->actualTask = find_tasknode_with_minimal_timer(scheduler);
+ return 0;
+}
diff --git a/src/task_scheduler_struct.h b/src/task_scheduler_struct.h
new file mode 100644
index 0000000..4114f30
--- /dev/null
+++ b/src/task_scheduler_struct.h
@@ -0,0 +1,47 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _JS_TASK_SCHEDULER_STRUCT_H
+#define _JS_TASK_SCHEDULER_STRUCT_H
+
+#include "task_list_node_struct.h"
+
+typedef struct {
+ TaskListNode* head;
+ int numberOfTasks;
+ TaskListNode* actualTask;
+ struct timeval delta;
+} TaskScheduler;
+
+/* 'constructor' */
+TaskScheduler* TaskScheduler_new();
+/* 'destructor' */
+void TaskScheduler_free(TaskScheduler** scheduler);
+/* getters */
+struct timeval* TaskScheduler_get_actualTimer(TaskScheduler* scheduler);
+/* other */
+int TaskScheduler_hasMoreTasks(TaskScheduler* scheduler);
+int TaskScheduler_addTask(TaskScheduler* scheduler, Task* task);
+int TaskScheduler_removeTask(TaskScheduler* scheduler, Task* task);
+int TaskScheduler_startWatching(TaskScheduler* scheduler);
+int TaskScheduler_stopWatching(TaskScheduler* scheduler);
+int TaskScheduler_update(TaskScheduler* scheduler);
+
+#endif
diff --git a/src/task_struct.c b/src/task_struct.c
new file mode 100644
index 0000000..b422ffb
--- /dev/null
+++ b/src/task_struct.c
@@ -0,0 +1,122 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "task_struct.h"
+
+/*
+ * Function name: Task_new
+ * Description: Creates and initializes new task. User is responsible for
+ * allocating/freeing memory pointed by the pointers.
+ * Arguments: timerp - pointer to timeval structure used to counte time (required)
+ * function - pointer to function executed when the time is out (optional)
+ * data - pointer to data passed to function executed when the time is out (optional)
+ * clean - pointer to function that frees the data
+ * Returns: Pointer to newly created Task structure.
+ */
+
+Task*
+Task_new(struct timeval* timerp, void (*function)(void*), void* data, void (*clean)(void**))
+{
+ Task* tmp;
+ assert(timerp != NULL);
+ if (timerp == NULL) {
+ return NULL;
+ }
+ tmp = calloc(1, sizeof(Task));
+ assert(tmp != NULL);
+ if (tmp == NULL) {
+ return NULL;
+ }
+ tmp->timerp = timerp;
+ tmp->function = function;
+ tmp->data = data;
+ tmp->clean = clean;
+
+ return tmp;
+}
+
+/*
+ * Function name: Task_free
+ * Description: Frees the memory allocated for Task structure. User has to free the memory at the
+ * pointers by his own.
+ * Arguments: task - pointer to pointer to Task structure
+ */
+
+void
+Task_free(Task** task)
+{
+ assert(task != NULL);
+ if (task == NULL) {
+ return;
+ }
+ assert((*task) != NULL);
+ if ((*task) == NULL) {
+ return;
+ }
+
+ if ((*task)->clean) {
+ if ((*task)->data) {
+ (*task)->clean(&((*task)->data));
+ }
+ }
+
+ free((*task));
+ (*task) = NULL;
+}
+
+/*
+ * Function name: Task_get_timer
+ * Description: Returns the timer of the task.
+ * Arguments: task - pointer to Task structure
+ * Returns: The timer of the task.
+ */
+
+struct timeval*
+Task_get_timer(Task* task)
+{
+ assert(task != NULL);
+ if (task == NULL) {
+ return NULL;
+ }
+ return task->timerp;
+}
+
+/*
+ * Function name: Task_exec
+ * Description: Executes the function encapsulated in the task.
+ * Arguments: task - pointer to Task structure
+ */
+
+void
+Task_exec(Task* task)
+{
+ assert(task != NULL);
+ if (task == NULL) {
+ return;
+ }
+ if (task->function) {
+ task->function(task->data);
+ }
+}
diff --git a/src/task_struct.h b/src/task_struct.h
new file mode 100644
index 0000000..334e97d
--- /dev/null
+++ b/src/task_struct.h
@@ -0,0 +1,39 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003-2006 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _JS_TASK_STRUCT_H
+#define _JS_TASK_STRUCT_H
+
+typedef struct {
+ struct timeval* timerp;
+ void (*function)(void*);
+ void* data;
+ void (*clean)(void**);
+} Task;
+
+/* 'constructor' */
+Task* Task_new(struct timeval*, void (*function)(void*), void*, void (*clean)(void**));
+/* 'destructor' */
+void Task_free(Task** task);
+/* getters */
+struct timeval* Task_get_timer(Task* task);
+void Task_exec(Task* task);
+
+#endif
diff --git a/src/timeval_functions.c b/src/timeval_functions.c
index 84bfe7e..394b654 100644
--- a/src/timeval_functions.c
+++ b/src/timeval_functions.c
@@ -20,6 +20,9 @@
#include <config.h>
+#include <stdlib.h>
+#include <assert.h>
+
#include "timeval_functions.h"
/*
@@ -38,3 +41,94 @@ timeval_create(long tv_sec, long tv_usec)
tmp.tv_usec = tv_usec;
return tmp;
}
+
+/*
+ * Function name: timeval_compare
+ * Description: Compares two pointers to timeval structures.
+ * Arguments: first - the first timeval structure to compare
+ * second - the second timeval structure to compare
+ * Returns: -1 - the second structure is bigger
+ * 0 - structures are equals
+ * 1 - the first structure is bigger
+ */
+
+int
+timeval_compare(struct timeval* first, struct timeval* second)
+{
+ if (first == NULL) {
+ if (second == NULL) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ }
+ if (second == NULL) {
+ return 1;
+ }
+ if (first->tv_sec < second->tv_sec) {
+ return -1;
+ }
+ if (first->tv_sec > second->tv_sec) {
+ return 1;
+ }
+ if (first->tv_usec < second->tv_usec) {
+ return -1;
+ }
+ if (first->tv_usec > second->tv_usec) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Function name: timeval_subtract
+ * Description: Substracts second timeval structure from the first, updating the latter one.
+ * Arguments: first - the first timeval structure to subtract operation
+ * second - the second timeval structure to subtract operation
+ * Returns: 0 - success,
+ * 1 - failure.
+ */
+
+int
+timeval_subtract(struct timeval* first, struct timeval* second)
+{
+ assert(first != NULL);
+ assert(second != NULL);
+ if ((first == NULL) || (second == NULL)) {
+ return 1;
+ }
+ if (first->tv_usec < second->tv_usec) {
+ first->tv_sec -= 1;
+ first->tv_usec = 1000000 - second->tv_usec + first->tv_usec;
+ }
+ else {
+ first->tv_usec -= second->tv_usec;
+ }
+ first->tv_sec -= second->tv_sec;
+ return 0;
+}
+
+/*
+ * Function name: timeval_lq_zero
+ * Description: Checks if the timer is less or equiv zero.
+ * Arguments: timer - the timeval structure to check
+ * Returns: 1 - the timer is less or equiv zero,
+ * 0 - the timer is bigger than zero.
+ */
+
+int
+timeval_lq_zero(struct timeval* timer)
+{
+ assert(timer != NULL);
+ if (timer == NULL) {
+ return 0;
+ }
+ if (timer->tv_sec < 0) {
+ return 1;
+ }
+ if ((timer->tv_sec == 0) && (timer->tv_usec == 0)) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/timeval_functions.h b/src/timeval_functions.h
index 8741442..8472760 100644
--- a/src/timeval_functions.h
+++ b/src/timeval_functions.h
@@ -24,6 +24,9 @@
#include <sys/time.h>
struct timeval timeval_create(long tv_sec, long tv_usec);
+int timeval_compare(struct timeval* first, struct timeval* second);
+int timeval_subtract(struct timeval* first, struct timeval* second);
+int timeval_lq_zero(struct timeval* timer);
#endif
diff --git a/src/usage.c b/src/usage.c
index 2241228..3f13a78 100644
--- a/src/usage.c
+++ b/src/usage.c
@@ -72,9 +72,11 @@ server_long_usage(char* info)
printf(" -f, --cfgfile - the name of the file with the configuration for the\n");
printf(" active forwarder (server)\n");
printf(" -D, --dateformat - format of the date printed in logs (see 'man strftime'\n");
- printf(" for details) (default: %%Y-%%m-%%d %%H:%%M:%%S)\n\n");
+ printf(" for details) (default: %%Y-%%m-%%d %%H:%%M:%%S)\n");
printf(" -t, --timeout - the timeout value for the client's connection\n");
printf(" (default: 5)\n");
+ printf(" --maxidle - the maximum idle time for the client's connection\n");
+ printf(" (default: disabled)\n");
printf(" -u, --users - the amount of users allowed to use this server\n");
printf(" (default: 5)\n");
printf(" -C, --clients - the number of allowed clients to use this server\n");