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
|
|
|
}
|
|
|
|
}
|