openmohaa/code/fgame/ipfilter.cpp

361 lines
6.8 KiB
C++
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// ipfilter.cpp: PACKET FILTERING
//
// You can add or remove addresses from the filter list with:
//
// addip <ip>
// removeip <ip>
//
// The ip address is specified in dot format, and any unspecified digits will match
// any value, so you can specify an entire class C network with "addip 192.246.40".
//
// Removeip will only remove an address specified exactly the same way. You cannot
// addip a subnet, then removeip a single host.
//
// listip
// Prints the current list of filters.
//
// writeip
// Dumps "addip <ip>" commands to listip.cfg so it can be execed at a later date.
// The filter lists are not saved and restored by default, because I beleive it would
// cause too much confusion.
//
// filterban <0 or 1>
//
// If 1 (the default), then ip addresses matching the current list will be prohibited
// from entering the game. This is the default setting.
//
// If 0, then only addresses matching the list will be allowed. This lets you easily
// set up a private game, or a game that only allows players from your local network.
//
#include "ipfilter.h"
#include "g_local.h"
typedef struct
{
unsigned mask;
unsigned compare;
} ipfilter_t;
#define MAX_IPFILTERS 1024
ipfilter_t ipfilters[ MAX_IPFILTERS ];
int numipfilters;
/*
=================
StringToFilter
=================
*/
static qboolean StringToFilter
(
const char *s,
ipfilter_t *f
)
{
char num[ 128 ];
int i;
int j;
byte b[ 4 ];
byte m[ 4 ];
for( i = 0; i < 4; i++ )
{
b[ i ] = 0;
m[ i ] = 0;
}
for( i = 0; i < 4; i++ )
{
if ( *s < '0' || *s > '9' )
{
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Bad filter address: %s\n\"", s );
2016-03-27 11:49:47 +02:00
return false;
}
j = 0;
while( *s >= '0' && *s <= '9' )
{
num[ j++ ] = *s++;
}
num[ j ] = 0;
b[ i ] = atoi( num );
if ( b[ i ] != 0 )
{
m[ i ] = 255;
}
if ( !*s )
{
break;
}
s++;
}
f->mask = *( unsigned * )m;
f->compare = *( unsigned * )b;
return true;
}
/*
=================
SV_FilterPacket
=================
*/
qboolean SV_FilterPacket
(
const char *from
)
{
int i;
unsigned in;
byte m[ 4 ];
const char *p;
i = 0;
p = from;
while( *p && i < 4 )
{
m[ i ] = 0;
while( *p >= '0' && *p <= '9' )
{
m[ i ] = m[ i ] * 10 + ( *p - '0' );
p++;
}
if ( !*p || *p == ':' )
{
break;
}
i++;
p++;
}
in = *( unsigned * )m;
for( i = 0; i < numipfilters; i++ )
{
if ( ( in & ipfilters[ i ].mask ) == ipfilters[ i ].compare )
{
return ( int )filterban->integer;
}
}
return !( int )filterban->integer;
}
/*
=================
SV_AddIP_f
=================
*/
void SVCmd_AddIP_f
(
void
)
{
int i;
if ( gi.Argc() < 3 )
{
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Usage: addip <ip-mask>\n\"" );
2016-03-27 11:49:47 +02:00
return;
}
for( i = 0; i < numipfilters; i++ )
{
if ( ipfilters[ i ].compare == 0xffffffff )
{
// free spot
break;
}
}
if ( i == numipfilters )
{
if ( numipfilters == MAX_IPFILTERS )
{
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"IP filter list is full\n\"" );
2016-03-27 11:49:47 +02:00
return;
}
numipfilters++;
}
if ( !StringToFilter( gi.Argv( 2 ), &ipfilters[ i ] ) )
{
ipfilters[ i ].compare = 0xffffffff;
}
}
/*
=================
SV_RemoveIP_f
=================
*/
void SVCmd_RemoveIP_f
(
void
)
{
ipfilter_t f;
int i;
int j;
if ( gi.Argc() < 3 )
{
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Usage: sv removeip <ip-mask>\n\"" );
2016-03-27 11:49:47 +02:00
return;
}
if ( !StringToFilter( gi.Argv( 2 ), &f ) )
{
return;
}
for( i = 0; i < numipfilters; i++ )
{
if ( ( ipfilters[ i ].mask == f.mask ) && ( ipfilters[ i ].compare == f.compare ) )
{
for ( j = i + 1; j < numipfilters; j++ )
{
ipfilters[ j - 1 ] = ipfilters[ j ];
}
numipfilters--;
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Removed.\n\"" );
2016-03-27 11:49:47 +02:00
return;
}
}
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Didn't find %s.\n\"", gi.Argv( 2 ) );
2016-03-27 11:49:47 +02:00
}
/*
=================
SV_ListIP_f
=================
*/
void SVCmd_ListIP_f
(
void
)
{
int i;
byte b[ 4 ];
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Filter list:\n\"", gi.Argv( 2 ) );
2016-03-27 11:49:47 +02:00
for( i = 0; i < numipfilters; i++ )
{
*( unsigned * )b = ipfilters[ i ].compare;
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"%3i.%3i.%3i.%3i\n\"", b[ 0 ], b[ 1 ], b[ 2 ], b[ 3 ] );
2016-03-27 11:49:47 +02:00
}
}
/*
=================
SV_WriteIP_f
=================
*/
void SVCmd_WriteIP_f
(
void
)
{
FILE *f;
char name[ MAX_OSPATH ];
byte b[ 4 ];
int i;
2024-09-20 21:53:48 +02:00
Com_sprintf( name, sizeof( name ), "%s/listip.cfg", GAMEVERSION );
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Writing %s.\n\"", name );
2016-03-27 11:49:47 +02:00
f = fopen( name, "wb" );
if ( !f )
{
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Couldn't open %s.\n\"", name );
2016-03-27 11:49:47 +02:00
return;
}
fprintf( f, "set filterban %d\n", ( int )filterban->integer );
for( i = 0; i < numipfilters; i++ )
{
*( unsigned * )b = ipfilters[ i ].compare;
fprintf( f, "sv addip %i.%i.%i.%i\n", b[ 0 ], b[ 1 ], b[ 2 ], b[ 3 ] );
}
fclose( f );
}
/*
=================
G_ServerCommand
G_ServerCommand will be called when an "sv" command is issued.
The game can issue gi.Argc() / gi.Argv() commands to get the rest
of the parameters
=================
*/
void G_ServerCommand
(
void
)
{
const char *cmd;
cmd = gi.Argv(1);
if ( Q_stricmp( cmd, "addip" ) == 0 )
{
SVCmd_AddIP_f();
}
else if ( Q_stricmp( cmd, "removeip" ) == 0 )
{
SVCmd_RemoveIP_f();
}
else if ( Q_stricmp( cmd, "listip" ) == 0 )
{
SVCmd_ListIP_f();
}
else if ( Q_stricmp( cmd, "writeip" ) == 0 )
{
SVCmd_WriteIP_f();
}
else
{
2023-02-01 00:28:40 +01:00
gi.SendServerCommand( 0, "print \"Unknown server command %s.\n\"", cmd );
2016-03-27 11:49:47 +02:00
}
}