Clean g_svcmds.c up and add sanity checks

This commit is contained in:
Yamagi Burmeister 2013-01-05 13:30:05 +01:00
parent 214bd0a6f5
commit 81adfbff59

View file

@ -1,281 +1,333 @@
/* =======================================================================
*
* Game side of server CMDs. At this time only the ipfilter.
*
* =======================================================================
*/
#include "header/local.h" #include "header/local.h"
#define MAX_IPFILTERS 1024
void Svcmd_Test_f (void) void
Svcmd_Test_f(void)
{ {
gi.cprintf (NULL, PRINT_HIGH, "Svcmd_Test_f()\n"); gi.cprintf(NULL, PRINT_HIGH, "Svcmd_Test_f()\n");
} }
/* /*
============================================================================== * ==============================================================================
*
PACKET FILTERING * PACKET FILTERING
*
*
You can add or remove addresses from the filter list with: * You can add or remove addresses from the filter list with:
*
addip <ip> * addip <ip>
removeip <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". * The ip address is specified in dot format, and any unspecified
* digits will match any value, so you can specify an entire class
Removeip will only remove an address specified exactly the same way. You cannot addip a subnet, then removeip a single host. * C network with "addip 192.246.40".
*
listip * Removeip will only remove an address specified exactly the same
Prints the current list of filters. * way. You cannot addip a subnet, then removeip a single host.
*
writeip * listip
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. * Prints the current list of filters.
*
filterban <0 or 1> * writeip
* Dumps "addip <ip>" commands to listip.cfg so it can be execed
If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game. This is the default setting. * at a later date. The filter lists are not saved and restored
* by default, because I belive it would cause too much confusion.
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. *
* 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.
*
* ==============================================================================
*/
typedef struct typedef struct
{ {
unsigned mask; unsigned mask;
unsigned compare; unsigned compare;
} ipfilter_t; } ipfilter_t;
#define MAX_IPFILTERS 1024 ipfilter_t ipfilters[MAX_IPFILTERS];
int numipfilters;
ipfilter_t ipfilters[MAX_IPFILTERS]; qboolean
int numipfilters; StringToFilter(char *s, ipfilter_t *f)
/*
=================
StringToFilter
=================
*/
qboolean StringToFilter (char *s, ipfilter_t *f)
{ {
char num[128]; char num[128];
int i, j; int i, j;
byte b[4]; byte b[4];
byte m[4]; byte m[4];
for (i=0 ; i<4 ; i++) if (!s || !f)
{
return false;
}
for (i = 0; i < 4; i++)
{ {
b[i] = 0; b[i] = 0;
m[i] = 0; m[i] = 0;
} }
for (i=0 ; i<4 ; i++) for (i = 0; i < 4; i++)
{ {
if (*s < '0' || *s > '9') if ((*s < '0') || (*s > '9'))
{ {
gi.cprintf(NULL, PRINT_HIGH, "Bad filter address: %s\n", s); gi.cprintf(NULL, PRINT_HIGH, "Bad filter address: %s\n", s);
return false; return false;
} }
j = 0; j = 0;
while (*s >= '0' && *s <= '9') while (*s >= '0' && *s <= '9')
{ {
num[j++] = *s++; num[j++] = *s++;
} }
num[j] = 0; num[j] = 0;
b[i] = atoi(num); b[i] = atoi(num);
if (b[i] != 0) if (b[i] != 0)
{
m[i] = 255; m[i] = 255;
}
if (!*s) if (!*s)
{
break; break;
}
s++; s++;
} }
f->mask = *(unsigned *)m; f->mask = *(unsigned *)m;
f->compare = *(unsigned *)b; f->compare = *(unsigned *)b;
return true; return true;
} }
/* qboolean
================= SV_FilterPacket(char *from)
SV_FilterPacket
=================
*/
qboolean SV_FilterPacket (char *from)
{ {
int i; int i;
unsigned in; unsigned in;
byte m[4]; byte m[4];
char *p; char *p;
if (!from)
{
return false;
}
i = 0; i = 0;
p = from; p = from;
while (*p && i < 4) {
while (*p && i < 4)
{
m[i] = 0; m[i] = 0;
while (*p >= '0' && *p <= '9') {
m[i] = m[i]*10 + (*p - '0'); while (*p >= '0' && *p <= '9')
{
m[i] = m[i] * 10 + (*p - '0');
p++; p++;
} }
if (!*p || *p == ':')
if (!*p || (*p == ':'))
{
break; break;
}
i++, p++; i++, p++;
} }
in = *(unsigned *)m; in = *(unsigned *)m;
for (i=0 ; i<numipfilters ; i++) for (i = 0; i < numipfilters; i++)
if ( (in & ipfilters[i].mask) == ipfilters[i].compare) {
if ((in & ipfilters[i].mask) == ipfilters[i].compare)
{
return (int)filterban->value; return (int)filterban->value;
}
}
return (int)!filterban->value; return (int)!filterban->value;
} }
void
/* SVCmd_AddIP_f(void)
=================
SV_AddIP_f
=================
*/
void SVCmd_AddIP_f (void)
{ {
int i; int i;
if (gi.argc() < 3) { if (gi.argc() < 3)
{
gi.cprintf(NULL, PRINT_HIGH, "Usage: addip <ip-mask>\n"); gi.cprintf(NULL, PRINT_HIGH, "Usage: addip <ip-mask>\n");
return; return;
} }
for (i=0 ; i<numipfilters ; i++) for (i = 0; i < numipfilters; i++)
{
if (ipfilters[i].compare == 0xffffffff) if (ipfilters[i].compare == 0xffffffff)
break; // free spot {
break; /* free spot */
}
}
if (i == numipfilters) if (i == numipfilters)
{ {
if (numipfilters == MAX_IPFILTERS) if (numipfilters == MAX_IPFILTERS)
{ {
gi.cprintf (NULL, PRINT_HIGH, "IP filter list is full\n"); gi.cprintf(NULL, PRINT_HIGH, "IP filter list is full\n");
return; return;
} }
numipfilters++; numipfilters++;
} }
if (!StringToFilter (gi.argv(2), &ipfilters[i])) if (!StringToFilter(gi.argv(2), &ipfilters[i]))
{
ipfilters[i].compare = 0xffffffff; ipfilters[i].compare = 0xffffffff;
}
} }
/* void
================= SVCmd_RemoveIP_f(void)
SV_RemoveIP_f
=================
*/
void SVCmd_RemoveIP_f (void)
{ {
ipfilter_t f; ipfilter_t f;
int i, j; int i, j;
if (gi.argc() < 3) { if (gi.argc() < 3)
{
gi.cprintf(NULL, PRINT_HIGH, "Usage: sv removeip <ip-mask>\n"); gi.cprintf(NULL, PRINT_HIGH, "Usage: sv removeip <ip-mask>\n");
return; return;
} }
if (!StringToFilter (gi.argv(2), &f)) if (!StringToFilter(gi.argv(2), &f))
{
return; return;
}
for (i=0 ; i<numipfilters ; i++) for (i = 0; i < numipfilters; i++)
if (ipfilters[i].mask == f.mask {
&& ipfilters[i].compare == f.compare) if ((ipfilters[i].mask == f.mask) &&
(ipfilters[i].compare == f.compare))
{ {
for (j=i+1 ; j<numipfilters ; j++) for (j = i + 1; j < numipfilters; j++)
ipfilters[j-1] = ipfilters[j]; {
ipfilters[j - 1] = ipfilters[j];
}
numipfilters--; numipfilters--;
gi.cprintf (NULL, PRINT_HIGH, "Removed.\n"); gi.cprintf(NULL, PRINT_HIGH, "Removed.\n");
return; return;
} }
gi.cprintf (NULL, PRINT_HIGH, "Didn't find %s.\n", gi.argv(2)); }
gi.cprintf(NULL, PRINT_HIGH, "Didn't find %s.\n", gi.argv(2));
} }
/* void
================= SVCmd_ListIP_f(void)
SV_ListIP_f
=================
*/
void SVCmd_ListIP_f (void)
{ {
int i; int i;
byte b[4]; byte b[4];
gi.cprintf (NULL, PRINT_HIGH, "Filter list:\n"); gi.cprintf(NULL, PRINT_HIGH, "Filter list:\n");
for (i=0 ; i<numipfilters ; i++)
for (i = 0; i < numipfilters; i++)
{ {
*(unsigned *)b = ipfilters[i].compare; *(unsigned *)b = ipfilters[i].compare;
gi.cprintf (NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]); gi.cprintf(NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i\n",
b[0], b[1], b[2], b[3]);
} }
} }
/* void
================= SVCmd_WriteIP_f(void)
SV_WriteIP_f
=================
*/
void SVCmd_WriteIP_f (void)
{ {
FILE *f; FILE *f;
char name[MAX_OSPATH]; char name[MAX_OSPATH];
byte b[4]; byte b[4];
int i; int i;
cvar_t *game; cvar_t *game;
game = gi.cvar("game", "", 0); game = gi.cvar("game", "", 0);
if (!*game->string) if (!*game->string)
sprintf (name, "%s/listip.cfg", GAMEVERSION); {
sprintf(name, "%s/listip.cfg", GAMEVERSION);
}
else else
sprintf (name, "%s/listip.cfg", game->string); {
sprintf(name, "%s/listip.cfg", game->string);
}
gi.cprintf (NULL, PRINT_HIGH, "Writing %s.\n", name); gi.cprintf(NULL, PRINT_HIGH, "Writing %s.\n", name);
f = fopen(name, "wb");
f = fopen (name, "wb");
if (!f) if (!f)
{ {
gi.cprintf (NULL, PRINT_HIGH, "Couldn't open %s\n", name); gi.cprintf(NULL, PRINT_HIGH, "Couldn't open %s\n", name);
return; return;
} }
fprintf(f, "set filterban %d\n", (int)filterban->value); fprintf(f, "set filterban %d\n", (int)filterban->value);
for (i=0 ; i<numipfilters ; i++) for (i = 0; i < numipfilters; i++)
{ {
*(unsigned *)b = ipfilters[i].compare; *(unsigned *)b = ipfilters[i].compare;
fprintf (f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]); fprintf(f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
} }
fclose (f); fclose(f);
} }
/* /*
================= * ServerCommand will be called when an "sv" command is issued.
ServerCommand * The game can issue gi.argc() / gi.argv() commands to get the rest
* of the parameters
ServerCommand will be called when an "sv" command is issued. */
The game can issue gi.argc() / gi.argv() commands to get the rest void
of the parameters ServerCommand(void)
=================
*/
void ServerCommand (void)
{ {
char *cmd; char *cmd;
cmd = gi.argv(1); cmd = gi.argv(1);
if (Q_stricmp (cmd, "test") == 0)
Svcmd_Test_f (); if (Q_stricmp(cmd, "test") == 0)
else if (Q_stricmp (cmd, "addip") == 0) {
SVCmd_AddIP_f (); Svcmd_Test_f();
else if (Q_stricmp (cmd, "removeip") == 0) }
SVCmd_RemoveIP_f (); else if (Q_stricmp(cmd, "addip") == 0)
else if (Q_stricmp (cmd, "listip") == 0) {
SVCmd_ListIP_f (); SVCmd_AddIP_f();
else if (Q_stricmp (cmd, "writeip") == 0) }
SVCmd_WriteIP_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 else
gi.cprintf (NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd); {
gi.cprintf(NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd);
}
} }