mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-03-11 05:21:07 +00:00
Port ip filter and partially useragent from old engine.
This commit is contained in:
parent
8b94443ba2
commit
83953c7fb3
@ -709,6 +709,7 @@ int CL_Active( void );
|
||||
|
||||
void SV_Init( void );
|
||||
void SV_Shutdown( const char *finalmsg );
|
||||
void SV_ShutdownFilter( void );
|
||||
void Host_ServerFrame( void );
|
||||
qboolean SV_Active( void );
|
||||
|
||||
@ -831,6 +832,15 @@ void Key_EnableTextInput( qboolean enable, qboolean force );
|
||||
|
||||
#include "avi/avi.h"
|
||||
|
||||
//
|
||||
// input.c
|
||||
//
|
||||
|
||||
#define INPUT_DEVICE_MOUSE (1<<0)
|
||||
#define INPUT_DEVICE_TOUCH (1<<1)
|
||||
#define INPUT_DEVICE_JOYSTICK (1<<2)
|
||||
#define INPUT_DEVICE_VR (1<<3)
|
||||
|
||||
// shared calls
|
||||
struct physent_s;
|
||||
typedef struct sv_client_s sv_client_t;
|
||||
|
@ -1059,6 +1059,7 @@ void EXPORT Host_Shutdown( void )
|
||||
#endif
|
||||
|
||||
SV_Shutdown( "Server shutdown\n" );
|
||||
SV_ShutdownFilter();
|
||||
CL_Shutdown();
|
||||
|
||||
Mod_Shutdown();
|
||||
|
@ -253,6 +253,7 @@ typedef struct sv_client_s
|
||||
int challenge; // challenge of this user, randomly generated
|
||||
int userid; // identifying number on server
|
||||
int extensions;
|
||||
char useragent[MAX_INFO_STRING];
|
||||
} sv_client_t;
|
||||
|
||||
/*
|
||||
@ -457,6 +458,7 @@ void SV_ProcessFile( sv_client_t *cl, const char *filename );
|
||||
void SV_SendResource( resource_t *pResource, sizebuf_t *msg );
|
||||
void SV_SendResourceList( sv_client_t *cl );
|
||||
void SV_AddToMaster( netadr_t from, sizebuf_t *msg );
|
||||
qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent );
|
||||
void Host_SetServerState( int state );
|
||||
qboolean SV_IsSimulating( void );
|
||||
qboolean SV_InitGame( void );
|
||||
@ -515,6 +517,8 @@ void SV_DirectConnect( netadr_t from );
|
||||
void SV_TogglePause( const char *msg );
|
||||
qboolean SV_ShouldUpdatePing( sv_client_t *cl );
|
||||
const char *SV_GetClientIDString( sv_client_t *cl );
|
||||
sv_client_t *SV_ClientById( int id );
|
||||
sv_client_t *SV_ClientByName( const char *name );
|
||||
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_FullUpdateMovevars( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_GetPlayerStats( sv_client_t *cl, int *ping, int *packet_loss );
|
||||
@ -554,6 +558,14 @@ void SV_ClearResourceLists( sv_client_t *cl );
|
||||
void SV_TransferConsistencyInfo( void );
|
||||
void SV_RequestMissingResources( void );
|
||||
|
||||
//
|
||||
// sv_filter.c
|
||||
//
|
||||
void SV_InitFilter( void );
|
||||
void SV_ShutdownFilter( void );
|
||||
qboolean SV_CheckIP( netadr_t *adr );
|
||||
qboolean SV_CheckID( const char *id );
|
||||
|
||||
//
|
||||
// sv_frame.c
|
||||
//
|
||||
|
@ -287,6 +287,12 @@ void SV_ConnectClient( netadr_t from )
|
||||
return;
|
||||
}
|
||||
|
||||
if( !SV_ProcessUserAgent( from, Cmd_Argv( 6 ) ) )
|
||||
{
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
challenge = Q_atoi( Cmd_Argv( 2 )); // get challenge
|
||||
|
||||
// see if the challenge is valid (local clients don't need to challenge)
|
||||
@ -372,6 +378,18 @@ void SV_ConnectClient( netadr_t from )
|
||||
|
||||
// build a new connection
|
||||
// accept the new client
|
||||
if( Q_strncpy( newcl->useragent, Cmd_Argv( 6 ), MAX_INFO_STRING ) )
|
||||
{
|
||||
const char *id = Info_ValueForKey( newcl->useragent, "i" );
|
||||
|
||||
if( *id )
|
||||
{
|
||||
//sscanf( id, "%llx", &newcl->WonID );
|
||||
}
|
||||
|
||||
// Q_strncpy( cl->auth_id, id, sizeof( cl->auth_id ) );
|
||||
}
|
||||
|
||||
sv.current_client = newcl;
|
||||
newcl->edict = EDICT_NUM( (newcl - svs.clients) + 1 );
|
||||
newcl->challenge = challenge; // save challenge for checksumming
|
||||
@ -662,6 +680,44 @@ const char *SV_GetClientIDString( sv_client_t *cl )
|
||||
return result;
|
||||
}
|
||||
|
||||
sv_client_t *SV_ClientById( int id )
|
||||
{
|
||||
sv_client_t *cl;
|
||||
int i;
|
||||
|
||||
ASSERT( id >= 0 );
|
||||
|
||||
for( i = 0, cl = svs.clients; i < svgame.globals->maxClients; i++, cl++ )
|
||||
{
|
||||
if( !cl->state )
|
||||
continue;
|
||||
|
||||
if( cl->userid == id )
|
||||
return cl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sv_client_t *SV_ClientByName( const char *name )
|
||||
{
|
||||
sv_client_t *cl;
|
||||
int i;
|
||||
|
||||
ASSERT( name && *name );
|
||||
|
||||
for( i = 0, cl = svs.clients; i < svgame.globals->maxClients; i++, cl++ )
|
||||
{
|
||||
if( !cl->state )
|
||||
continue;
|
||||
|
||||
if( !Q_strcmp( cl->name, name ) )
|
||||
return cl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_TestBandWidth
|
||||
@ -2146,6 +2202,10 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
char buf[MAX_SYSPATH];
|
||||
int len = sizeof( buf );
|
||||
|
||||
// prevent flooding from banned address
|
||||
if( SV_CheckIP( &from ) )
|
||||
return;
|
||||
|
||||
MSG_Clear( msg );
|
||||
MSG_ReadLong( msg );// skip the -1 marker
|
||||
|
||||
|
@ -541,15 +541,25 @@ Kick a user off of the server
|
||||
void SV_Kick_f( void )
|
||||
{
|
||||
sv_client_t *cl;
|
||||
const char *param, *clientId;
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "kick <userid> | <name>\n" );
|
||||
Con_Printf( S_USAGE "kick <#id|name> [reason]\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if(( cl = SV_SetPlayer( )) == NULL )
|
||||
param = Cmd_Argv( 1 );
|
||||
|
||||
if( *param == '#' && Q_isdigit( param + 1 ) )
|
||||
cl = SV_ClientById( Q_atoi( param + 1 ) );
|
||||
else cl = SV_ClientByName( param );
|
||||
|
||||
if( !cl )
|
||||
{
|
||||
Con_Printf( "Client is not on the server\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( NET_IsLocalAddress( cl->netchan.remote_address ))
|
||||
{
|
||||
@ -557,9 +567,31 @@ void SV_Kick_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
Log_Printf( "Kick: \"%s<%i>\" was kicked\n", cl->name, cl->userid );
|
||||
SV_BroadcastPrintf( cl, "%s was kicked\n", cl->name );
|
||||
SV_ClientPrintf( cl, "You were kicked from the game\n" );
|
||||
param = Cmd_Argv( 2 );
|
||||
|
||||
clientId = SV_GetClientIDString( cl );
|
||||
|
||||
if( *param )
|
||||
{
|
||||
Log_Printf( "Kick: \"%s<%i><%s><>\" was kicked by \"Console\" (message \"%s\")\n", cl->name, cl->userid, clientId, param );
|
||||
SV_BroadcastPrintf( cl, "%s was kicked with message: \"%s\"\n", cl->name, param );
|
||||
SV_ClientPrintf( cl, "You were kicked from the game with message: \"%s\"\n", param );
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_Printf( "Kick: \"%s<%i><%s><>\" was kicked by \"Console\"\n", cl->name, cl->userid, clientId );
|
||||
SV_BroadcastPrintf( cl, "%s was kicked\n", cl->name );
|
||||
SV_ClientPrintf( cl, "You were kicked from the game\n" );
|
||||
}
|
||||
|
||||
if( cl->useragent[0] )
|
||||
{
|
||||
if( *param )
|
||||
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, "errormsg\nKicked with message:\n%s\n", param );
|
||||
else
|
||||
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, "errormsg\nYou were kicked from the game\n" );
|
||||
}
|
||||
|
||||
SV_DropClient( cl, false );
|
||||
}
|
||||
|
||||
@ -781,6 +813,31 @@ void SV_ClientInfo_f( void )
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
SV_ClientUserAgent_f
|
||||
|
||||
Examine useragent strings
|
||||
===========
|
||||
*/
|
||||
void SV_ClientUserAgent_f( void )
|
||||
{
|
||||
sv_client_t *cl;
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "clientuseragent <userid>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if(( cl = SV_SetPlayer( )) == NULL )
|
||||
return;
|
||||
|
||||
Con_Printf( "useragent\n" );
|
||||
Con_Printf( "---------\n" );
|
||||
Info_Print( cl->useragent );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
SV_KillServer_f
|
||||
@ -912,6 +969,7 @@ void SV_InitOperatorCommands( void )
|
||||
Cmd_AddCommand( "localinfo", SV_LocalInfo_f, "examine or change the localinfo string" );
|
||||
Cmd_AddCommand( "serverinfo", SV_ServerInfo_f, "examine or change the serverinfo string" );
|
||||
Cmd_AddCommand( "clientinfo", SV_ClientInfo_f, "print user infostring (player num required)" );
|
||||
Cmd_AddCommand( "clientuseragent", SV_ClientUserAgent_f, "print user agent (player num required)" );
|
||||
Cmd_AddCommand( "playersonly", SV_PlayersOnly_f, "freezes time, except for players" );
|
||||
Cmd_AddCommand( "restart", SV_Restart_f, "restarting current level" );
|
||||
Cmd_AddCommand( "entpatch", SV_EntPatch_f, "write entity patch to allow external editing" );
|
||||
|
462
engine/server/sv_filter.c
Normal file
462
engine/server/sv_filter.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
sv_filter.c - server ID/IP filter
|
||||
Copyright (C) 2017 a1batross
|
||||
|
||||
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 3 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.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
||||
|
||||
typedef struct ipfilter_s
|
||||
{
|
||||
float time;
|
||||
float endTime; // -1 for permanent ban
|
||||
struct ipfilter_s *next;
|
||||
uint mask;
|
||||
uint ip;
|
||||
} ipfilter_t;
|
||||
|
||||
static ipfilter_t *ipfilter = NULL;
|
||||
|
||||
|
||||
// TODO: Is IP filter really needed?
|
||||
// TODO: Make it IPv6 compatible, for future expansion
|
||||
|
||||
typedef struct cidfilter_s
|
||||
{
|
||||
float endTime;
|
||||
struct cidfilter_s *next;
|
||||
string id;
|
||||
} cidfilter_t;
|
||||
|
||||
static cidfilter_t *cidfilter = NULL;
|
||||
|
||||
static void SV_RemoveID( const char *id )
|
||||
{
|
||||
cidfilter_t *filter, *prevfilter = NULL;
|
||||
|
||||
for( filter = cidfilter; filter; filter = filter->next )
|
||||
{
|
||||
if( Q_strcmp( filter->id, id ) )
|
||||
{
|
||||
prevfilter = filter;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( filter == cidfilter )
|
||||
{
|
||||
cidfilter = cidfilter->next;
|
||||
Mem_Free( filter );
|
||||
return;
|
||||
}
|
||||
|
||||
if( prevfilter )
|
||||
prevfilter->next = filter->next;
|
||||
Mem_Free( filter );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void SV_RemoveIP( uint ip, uint mask )
|
||||
{
|
||||
ipfilter_t *filter, *prevfilter = NULL;
|
||||
|
||||
for( filter = ipfilter; filter; filter = filter->next )
|
||||
{
|
||||
if( filter->ip != ip || mask != filter->mask )
|
||||
{
|
||||
prevfilter = filter;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( filter == ipfilter )
|
||||
{
|
||||
ipfilter = ipfilter->next;
|
||||
Mem_Free( filter );
|
||||
return;
|
||||
}
|
||||
|
||||
if( prevfilter )
|
||||
prevfilter->next = filter->next;
|
||||
Mem_Free( filter );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qboolean SV_CheckID( const char *id )
|
||||
{
|
||||
qboolean ret = false;
|
||||
cidfilter_t *filter;
|
||||
|
||||
for( filter = cidfilter; filter; filter = filter->next )
|
||||
{
|
||||
int len1 = Q_strlen( id ), len2 = Q_strlen( filter->id );
|
||||
int len = min( len1, len2 );
|
||||
|
||||
while( filter->endTime && host.realtime > filter->endTime )
|
||||
{
|
||||
char *fid = filter->id;
|
||||
filter = filter->next;
|
||||
SV_RemoveID( fid );
|
||||
if( !filter )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !Q_strncmp( id, filter->id, len ) )
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
qboolean SV_CheckIP( netadr_t *addr )
|
||||
{
|
||||
uint ip = addr->ip[0] << 24 | addr->ip[1] << 16 | addr->ip[2] << 8 | addr->ip[3];
|
||||
qboolean ret = false;
|
||||
ipfilter_t *filter;
|
||||
|
||||
for( filter = ipfilter; filter; filter = filter->next )
|
||||
{
|
||||
while( filter->endTime && host.realtime > filter->endTime )
|
||||
{
|
||||
uint rip = filter->ip;
|
||||
uint rmask = filter->mask;
|
||||
SV_RemoveIP( rip, rmask );
|
||||
filter = filter->next;
|
||||
if( !filter )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (ip & filter->mask) == (filter->ip & filter->mask) )
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SV_BanID_f( void )
|
||||
{
|
||||
float time = Q_atof( Cmd_Argv( 1 ) );
|
||||
const char *id = Cmd_Argv( 2 );
|
||||
sv_client_t *cl = NULL;
|
||||
cidfilter_t *filter;
|
||||
|
||||
if( time )
|
||||
time = host.realtime + time * 60.0f;
|
||||
|
||||
if( !id[0] )
|
||||
{
|
||||
Con_Reportf( "Usage: banid <minutes> <#userid or unique id>\n0 minutes for permanent ban\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !Q_strnicmp( id, "STEAM_", 6 ) || !Q_strnicmp( id, "VALVE_", 6 ) )
|
||||
id += 6;
|
||||
if( !Q_strnicmp( id, "XASH_", 5 ) )
|
||||
id += 5;
|
||||
|
||||
if( svs.clients )
|
||||
{
|
||||
if( id[0] == '#' )
|
||||
cl = SV_ClientById( Q_atoi( id + 1 ) );
|
||||
|
||||
if( !cl )
|
||||
{
|
||||
int i;
|
||||
sv_client_t *cl1;
|
||||
int len = Q_strlen( id );
|
||||
|
||||
for( i = 0, cl1 = svs.clients; i < sv_maxclients->value; i++, cl1++ )
|
||||
{
|
||||
if( !Q_strncmp( id, Info_ValueForKey( cl1->useragent, "i" ), len ) )
|
||||
{
|
||||
cl = cl1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !cl )
|
||||
{
|
||||
Con_DPrintf( S_WARN "banid: no such player\n" );
|
||||
}
|
||||
else
|
||||
id = Info_ValueForKey( cl->useragent, "i" );
|
||||
|
||||
if( !id[0] )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Could not ban, not implemented yet\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( !id[0] || id[0] == '#' )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "banid: bad id\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
SV_RemoveID( id );
|
||||
|
||||
filter = Mem_Malloc( host.mempool, sizeof( cidfilter_t ) );
|
||||
filter->endTime = time;
|
||||
filter->next = cidfilter;
|
||||
Q_strncpy( filter->id, id, sizeof( filter->id ) );
|
||||
cidfilter = filter;
|
||||
|
||||
if( cl && !Q_stricmp( Cmd_Argv( Cmd_Argc() - 1 ), "kick" ) )
|
||||
Cbuf_AddText( va( "kick #%d \"Kicked and banned\"\n", cl->userid ) );
|
||||
}
|
||||
|
||||
static void SV_ListID_f( void )
|
||||
{
|
||||
cidfilter_t *filter;
|
||||
|
||||
Con_Reportf( "id ban list\n" );
|
||||
Con_Reportf( "-----------\n" );
|
||||
|
||||
for( filter = cidfilter; filter; filter = filter->next )
|
||||
{
|
||||
if( filter->endTime && host.realtime > filter->endTime )
|
||||
continue; // no negative time
|
||||
|
||||
if( filter->endTime )
|
||||
Con_Reportf( "%s expries in %f minutes\n", filter->id, ( filter->endTime - host.realtime ) / 60.0f );
|
||||
else
|
||||
Con_Reportf( "%s permanent\n", filter->id );
|
||||
}
|
||||
}
|
||||
|
||||
static void SV_RemoveID_f( void )
|
||||
{
|
||||
const char *id = Cmd_Argv( 1 );
|
||||
|
||||
if( id[0] == '#' && svs.clients )
|
||||
{
|
||||
int num = Q_atoi( id + 1 );
|
||||
|
||||
if( num >= sv_maxclients->value || num < 0 )
|
||||
return;
|
||||
|
||||
id = Info_ValueForKey( svs.clients[num].useragent, "i" );
|
||||
}
|
||||
|
||||
if( !id[0] )
|
||||
{
|
||||
Con_Reportf("Usage: removeid <#slotnumber or uniqueid>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SV_RemoveID( id );
|
||||
}
|
||||
|
||||
static void SV_WriteID_f( void )
|
||||
{
|
||||
file_t *f = FS_Open( Cvar_VariableString( "bannedcfgfile" ), "w", false );
|
||||
cidfilter_t *filter;
|
||||
|
||||
if( !f )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Could not write %s\n", Cvar_VariableString( "bannedcfgfile" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\t\tCopyright Flying With Gauss Team %s ©\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\t %s - archive of id blacklist\n", Cvar_VariableString( "bannedcfgfile" ) );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
|
||||
for( filter = cidfilter; filter; filter = filter->next )
|
||||
if( !filter->endTime ) // only permanent
|
||||
FS_Printf( f, "banid 0 %s\n", filter->id );
|
||||
|
||||
FS_Close( f );
|
||||
}
|
||||
|
||||
static qboolean StringToIP( const char *str, const char *maskstr, uint *outip, uint *outmask )
|
||||
{
|
||||
byte ip[4] = {0};
|
||||
byte mask[4] = {0};
|
||||
int i = 0;
|
||||
|
||||
if( *str > '9' || *str < '0' )
|
||||
return false;
|
||||
|
||||
do
|
||||
{
|
||||
while( *str <= '9' && *str >= '0' )
|
||||
{
|
||||
ip[i] *=10;
|
||||
ip[i] += *str - '0';
|
||||
str++;
|
||||
}
|
||||
mask[i] = 255;
|
||||
i++;
|
||||
if( *str != '.' ) break;
|
||||
str++;
|
||||
} while( i < 4 );
|
||||
|
||||
i = 0;
|
||||
|
||||
if( !maskstr || *maskstr > '9' || *maskstr < '0' )
|
||||
goto end;
|
||||
|
||||
do
|
||||
{
|
||||
byte mask1 = 0;
|
||||
while( *maskstr <= '9' && *maskstr >= '0' )
|
||||
{
|
||||
mask1 *=10;
|
||||
mask1 += *maskstr - '0';
|
||||
maskstr++;
|
||||
}
|
||||
mask[i] &= mask1;
|
||||
i++;
|
||||
if( *maskstr != '.' ) break;
|
||||
maskstr++;
|
||||
} while( i < 4 );
|
||||
|
||||
end:
|
||||
*outip = ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3];
|
||||
if( outmask )
|
||||
*outmask = mask[0] << 24 | mask[1] << 16 | mask[2] << 8 | mask[3];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define IPARGS(ip) (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF
|
||||
static void SV_AddIP_f( void )
|
||||
{
|
||||
float time = Q_atof( Cmd_Argv( 1 ) );
|
||||
const char *ipstr = Cmd_Argv( 2 );
|
||||
const char *maskstr = Cmd_Argv( 3 );
|
||||
uint ip, mask;
|
||||
ipfilter_t *filter;
|
||||
|
||||
if( time )
|
||||
time = host.realtime + time * 60.0f;
|
||||
|
||||
if( !StringToIP( ipstr, maskstr, &ip, &mask ) )
|
||||
{
|
||||
Con_Reportf( "Usage: addip <minutes> <ip> [mask]\n0 minutes for permanent ban\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SV_RemoveIP( ip, mask );
|
||||
|
||||
filter = Mem_Malloc( host.mempool, sizeof( ipfilter_t ) );
|
||||
filter->endTime = time;
|
||||
filter->ip = ip;
|
||||
filter->mask = mask;
|
||||
filter->next = ipfilter;
|
||||
|
||||
ipfilter = filter;
|
||||
}
|
||||
|
||||
static void SV_ListIP_f( void )
|
||||
{
|
||||
ipfilter_t *filter;
|
||||
|
||||
Con_Reportf( "ip ban list\n" );
|
||||
Con_Reportf( "-----------\n" );
|
||||
|
||||
for( filter = ipfilter; filter; filter = filter->next )
|
||||
{
|
||||
if( filter->endTime && host.realtime > filter->endTime )
|
||||
continue; // no negative time
|
||||
|
||||
if( filter->endTime )
|
||||
Con_Reportf( "%d.%d.%d.%d %d.%d.%d.%d expries in %f minutes\n", IPARGS( filter->ip ), IPARGS( filter->mask ), ( filter->endTime - host.realtime ) / 60.0f );
|
||||
else
|
||||
Con_Reportf( "%d.%d.%d.%d %d.%d.%d.%d permanent\n", IPARGS( filter->ip ), IPARGS( filter->mask ) );
|
||||
}
|
||||
}
|
||||
|
||||
static void SV_RemoveIP_f( void )
|
||||
{
|
||||
uint ip, mask;
|
||||
|
||||
if( !StringToIP( Cmd_Argv(1), Cmd_Argv(2), &ip, &mask ) )
|
||||
{
|
||||
Con_Reportf( "Usage: removeip <ip> [mask]\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
SV_RemoveIP( ip, mask );
|
||||
}
|
||||
|
||||
static void SV_WriteIP_f( void )
|
||||
{
|
||||
file_t *f = FS_Open( Cvar_VariableString( "listipcfgfile" ), "w", false );
|
||||
ipfilter_t *filter;
|
||||
|
||||
if( !f )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Could not write %s\n", Cvar_VariableString( "listipcfgfile" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\t\tCopyright Flying With Gauss Team %s ©\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\t %s - archive of IP blacklist\n", Cvar_VariableString( "listipcfgfile" ) );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
|
||||
for( filter = ipfilter; filter; filter = filter->next )
|
||||
if( !filter->endTime ) // only permanent
|
||||
FS_Printf( f, "addip 0 %d.%d.%d.%d %d.%d.%d.%d\n", IPARGS(filter->ip), IPARGS(filter->mask) );
|
||||
|
||||
FS_Close( f );
|
||||
}
|
||||
|
||||
void SV_InitFilter( void )
|
||||
{
|
||||
Cmd_AddCommand( "banid", SV_BanID_f, "ban player by ID" );
|
||||
Cmd_AddCommand( "listid", SV_ListID_f, "list banned players" );
|
||||
Cmd_AddCommand( "removeid", SV_RemoveID_f, "remove player from banned list" );
|
||||
Cmd_AddCommand( "writeid", SV_WriteID_f, "write banned.cfg" );
|
||||
Cmd_AddCommand( "addip", SV_AddIP_f, "add entry to IP filter" );
|
||||
Cmd_AddCommand( "listip", SV_ListIP_f, "list current IP filter" );
|
||||
Cmd_AddCommand( "removeip", SV_RemoveIP_f, "remove IP filter" );
|
||||
Cmd_AddCommand( "writeip", SV_WriteIP_f, "write listip.cfg" );
|
||||
}
|
||||
|
||||
void SV_ShutdownFilter( void )
|
||||
{
|
||||
ipfilter_t *ipList, *ipNext;
|
||||
cidfilter_t *cidList, *cidNext;
|
||||
|
||||
// should be called manually because banned.cfg is not executed by engine
|
||||
//SV_WriteIP_f();
|
||||
//SV_WriteID_f();
|
||||
|
||||
for( ipList = ipfilter; ipList; ipList = ipNext )
|
||||
{
|
||||
ipNext = ipList->next;
|
||||
Mem_Free( ipList );
|
||||
}
|
||||
|
||||
for( cidList = cidfilter; cidList; cidList = cidNext )
|
||||
{
|
||||
cidNext = cidList->next;
|
||||
Mem_Free( cidList );
|
||||
}
|
||||
|
||||
cidfilter = NULL;
|
||||
ipfilter = NULL;
|
||||
}
|
@ -117,6 +117,12 @@ convar_t *sv_validate_changelevel;
|
||||
convar_t *sv_sendvelocity;
|
||||
convar_t *sv_hostmap;
|
||||
|
||||
convar_t *sv_allow_noinputdevices;
|
||||
convar_t *sv_allow_touch;
|
||||
convar_t *sv_allow_mouse;
|
||||
convar_t *sv_allow_joystick;
|
||||
convar_t *sv_allow_vr;
|
||||
|
||||
void Master_Shutdown( void );
|
||||
|
||||
//============================================================================
|
||||
@ -765,6 +771,64 @@ void SV_AddToMaster( netadr_t from, sizebuf_t *msg )
|
||||
NET_SendPacket( NS_SERVER, Q_strlen( s ), s, from );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_ProcessUserAgent
|
||||
|
||||
send error message and return false on wrong input devices
|
||||
====================
|
||||
*/
|
||||
qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent )
|
||||
{
|
||||
const char *input_devices_str = Info_ValueForKey( useragent, "d" );
|
||||
const char *id = Info_ValueForKey( useragent, "i" );
|
||||
|
||||
if( !sv_allow_noinputdevices->value && ( !input_devices_str || !input_devices_str[0] ) )
|
||||
{
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "print\nThis server does not allow\nconnect without input devices list.\nPlease update your engine.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( input_devices_str )
|
||||
{
|
||||
int input_devices = Q_atoi( input_devices_str );
|
||||
|
||||
if( !sv_allow_touch->value && ( input_devices & INPUT_DEVICE_TOUCH ) )
|
||||
{
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "errormsg\nThis server does not allow touch\nDisable it (touch_enable 0)\nto play on this server\n" );
|
||||
return false;
|
||||
}
|
||||
if( !sv_allow_mouse->value && ( input_devices & INPUT_DEVICE_MOUSE) )
|
||||
{
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "errormsg\nThis server does not allow mouse\nDisable it(m_ignore 1)\nto play on this server\n" );
|
||||
return false;
|
||||
}
|
||||
if( !sv_allow_joystick->value && ( input_devices & INPUT_DEVICE_JOYSTICK) )
|
||||
{
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "errormsg\nThis server does not allow joystick\nDisable it(joy_enable 0)\nto play on this server\n" );
|
||||
return false;
|
||||
}
|
||||
if( !sv_allow_vr->value && ( input_devices & INPUT_DEVICE_VR) )
|
||||
{
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "errormsg\nThis server does not allow VR\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( id )
|
||||
{
|
||||
qboolean banned = SV_CheckID( id );
|
||||
|
||||
if( banned )
|
||||
{
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "errormsg\nYou are banned!\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
@ -868,6 +932,12 @@ void SV_Init( void )
|
||||
Cvar_RegisterVariable (&mp_logfile);
|
||||
Cvar_RegisterVariable (&sv_background_freeze);
|
||||
|
||||
sv_allow_joystick = Cvar_Get( "sv_allow_joystick", "1", FCVAR_ARCHIVE, "allow connect with joystick enabled" );
|
||||
sv_allow_mouse = Cvar_Get( "sv_allow_mouse", "1", FCVAR_ARCHIVE, "allow connect with mouse" );
|
||||
sv_allow_touch = Cvar_Get( "sv_allow_touch", "1", FCVAR_ARCHIVE, "allow connect with touch controls" );
|
||||
sv_allow_vr = Cvar_Get( "sv_allow_vr", "1", FCVAR_ARCHIVE, "allow connect from vr version" );
|
||||
sv_allow_noinputdevices = Cvar_Get( "sv_allow_noinputdevices", "1", FCVAR_ARCHIVE, "allow connect from old versions without useragent" );
|
||||
|
||||
// when we in developer-mode automatically turn cheats on
|
||||
if( host_developer.value ) Cvar_SetValue( "sv_cheats", 1.0f );
|
||||
|
||||
@ -878,6 +948,7 @@ void SV_Init( void )
|
||||
|
||||
Cvar_FullSet( "sv_version", versionString, FCVAR_READ_ONLY );
|
||||
|
||||
SV_InitFilter();
|
||||
SV_ClearGameState (); // delete all temporary *.hl files
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user