diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c index d8ef62c04eec11d6bd1217a10b6925fb300a6889..d632e1f72132dcbb93210ddbdd236da95e062e94 100644 --- a/src/sbbs3/ftpsrvr.c +++ b/src/sbbs3/ftpsrvr.c @@ -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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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; diff --git a/src/sbbs3/ftpsrvr.h b/src/sbbs3/ftpsrvr.h index e83599d978f13e54b74bf4aafad6c84570c6ae99..d9a0a2d1d0a71877df03197c6c640e1708bd6e07 100644 --- a/src/sbbs3/ftpsrvr.h +++ b/src/sbbs3/ftpsrvr.h @@ -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 */ diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c index d754f5b50f3aa4eec830371472f1d88738c73e63..bd9011be7d232a9b0582e331816da1e80a6d1c4c 100644 --- a/src/sbbs3/sbbs_ini.c +++ b/src/sbbs3/sbbs_ini.c @@ -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