...
 
Commits (2)
  • Rob Swindell's avatar
    Connection and logon linked lists need re-init for every recycle · b5d19603
    Rob Swindell authored
    Each list mutex is destroyed in the call to listFree() in cleanup(). Without a call to listInit(), the mutex is not recreated and thus the lists are no longer mutex-protected after a recycle. No negative consequences were observed from this issue, but a potential issue it is (was).
    b5d19603
  • Rob Swindell's avatar
    Implement max concurrent connections for FTP · 8b2b02e1
    Rob Swindell authored
    Support optional limit on concurrent connections from the same IP address to the FTP server by setting MaxConcurrentConnections in the [ftp] section of sbbs.ini. Unlike the mail server and the terminal server, this concurrent-connection count is not discounted by the number of authenticated logins. The default value is 0 (unlimited).
    
    This closes issue #156
    8b2b02e1
......@@ -84,6 +84,7 @@ static volatile BOOL terminate_server=FALSE;
static char *text[TOTAL_TEXT];
static str_list_t recycle_semfiles;
static str_list_t shutdown_semfiles;
static link_list_t current_connections;
#ifdef SOCKET_DEBUG
static BYTE socket_debug[0x10000]={0};
......@@ -203,12 +204,15 @@ static void update_clients(void)
static void client_on(SOCKET sock, client_t* client, BOOL update)
{
if(!update)
listAddNodeData(&current_connections, client->addr, strlen(client->addr) + 1, sock, LAST_NODE);
if(startup!=NULL && startup->client_on!=NULL)
startup->client_on(startup->cbdata,TRUE,sock,client,update);
}
static void client_off(SOCKET sock)
{
listRemoveTaggedNode(&current_connections, sock, /* free_data */TRUE);
if(startup!=NULL && startup->client_on!=NULL)
startup->client_on(startup->cbdata,FALSE,sock,NULL,FALSE);
}
......@@ -5029,6 +5033,8 @@ static void cleanup(int code, int line)
update_clients(); /* active_clients is destroyed below */
listFree(&current_connections);
if(protected_uint32_value(active_clients))
lprintf(LOG_WARNING,"!!!! Terminating with %d active clients", protected_uint32_value(active_clients));
else
......@@ -5117,6 +5123,7 @@ void DLLCALL ftp_server(void* arg)
protected_uint32_init(&thread_count, 0);
do {
listInit(&current_connections, LINK_LIST_MUTEX);
protected_uint32_init(&active_clients, 0);
/* Setup intelligent defaults */
......@@ -5295,6 +5302,20 @@ void DLLCALL ftp_server(void* arg)
startup->socket_open(startup->cbdata,TRUE);
inet_addrtop(&client_addr, client_ip, sizeof(client_ip));
if(startup->max_concurrent_connections > 0) {
int ip_len = strlen(client_ip) + 1;
uint connections = listCountMatches(&current_connections, client_ip, ip_len);
if(connections >= startup->max_concurrent_connections
&& !is_host_exempt(&scfg, client_ip, /* host_name */NULL)) {
lprintf(LOG_NOTICE, "%04d [%s] !Maximum concurrent connections (%u) exceeded"
,client_socket, client_ip, startup->max_concurrent_connections);
sockprintf(client_socket, -1, "421 Maximum connections (%u) exceeded", startup->max_concurrent_connections);
ftp_close_socket(&client_socket,&none,__LINE__);
continue;
}
}
if(trashcan(&scfg,client_ip,"ip-silent")) {
ftp_close_socket(&client_socket,&none,__LINE__);
continue;
......
......@@ -83,6 +83,8 @@ typedef struct {
struct login_attempt_settings login_attempt;
link_list_t* login_attempt_list;
uint max_concurrent_connections;
} ftp_startup_t;
/* startup options that requires re-initialization/recycle when changed */
......
......@@ -6086,10 +6086,10 @@ void DLLCALL mail_server(void* arg)
SetThreadName("sbbs/mailServer");
protected_uint32_init(&thread_count, 0);
listInit(&current_logins, LINK_LIST_MUTEX);
listInit(&current_connections, LINK_LIST_MUTEX);
do {
listInit(&current_logins, LINK_LIST_MUTEX);
listInit(&current_connections, LINK_LIST_MUTEX);
protected_uint32_init(&active_clients, 0);
/* Setup intelligent defaults */
......
......@@ -39,6 +39,7 @@ static const char* strInterfaces="Interface";
static const char* strPort="Port";
static const char* strMaxClients="MaxClients";
static const char* strMaxInactivity="MaxInactivity";
static const char* strMaxConConn="MaxConcurrentConnections";
static const char* strHostName="HostName";
static const char* strLogLevel="LogLevel";
static const char* strBindRetryCount="BindRetryCount";
......@@ -391,7 +392,7 @@ void sbbs_read_ini(
bbs->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay);
bbs->login_attempt = get_login_attempt_settings(list, section, global);
bbs->max_concurrent_connections = iniGetInteger(list, section, "MaxConcurrentConnections", 0);
bbs->max_concurrent_connections = iniGetInteger(list, section, strMaxConConn, 0);
}
/***********************************************************************/
......@@ -459,6 +460,7 @@ void sbbs_read_ini(
ftp->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,global->bind_retry_count);
ftp->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay);
ftp->login_attempt = get_login_attempt_settings(list, section, global);
ftp->max_concurrent_connections = iniGetInteger(list, section, strMaxConConn, 0);
}
/***********************************************************************/
......@@ -563,7 +565,7 @@ void sbbs_read_ini(
mail->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,global->bind_retry_count);
mail->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay);
mail->login_attempt = get_login_attempt_settings(list, section, global);
mail->max_concurrent_connections = iniGetInteger(list, section, "MaxConcurrentConnections", 0);
mail->max_concurrent_connections = iniGetInteger(list, section, strMaxConConn, 0);
}
/***********************************************************************/
......@@ -801,7 +803,7 @@ BOOL sbbs_write_ini(
break;
if(!iniSetShortInt(lp,section,"OutbufDrainTimeout",bbs->outbuf_drain_timeout,&style))
break;
if(!iniSetInteger(lp,section,"MaxConcurrentConnections",bbs->max_concurrent_connections,&style))
if(!iniSetInteger(lp,section,strMaxConConn,bbs->max_concurrent_connections,&style))
break;
......@@ -886,6 +888,8 @@ BOOL sbbs_write_ini(
break;
if(!iniSetShortInt(lp,section,strMaxInactivity,ftp->max_inactivity,&style))
break;
if(!iniSetInteger(lp,section,strMaxConConn,ftp->max_concurrent_connections,&style))
break;
if(!iniSetShortInt(lp,section,"QwkTimeout",ftp->qwk_timeout,&style))
break;
if(!iniSetBytes(lp,section,"MinFileSize",1,ftp->min_fsize,&style))
......@@ -1010,7 +1014,7 @@ BOOL sbbs_write_ini(
break;
if(!iniSetInteger(lp,section,"ConnectTimeout",mail->connect_timeout,&style))
break;
if(!iniSetInteger(lp,section,"MaxConcurrentConnections",mail->max_concurrent_connections,&style))
if(!iniSetInteger(lp,section,strMaxConConn,mail->max_concurrent_connections,&style))
break;
if(strcmp(mail->host_name,global->host_name)==0
......