- fix a potential file descriptor leak in server side of pak downloading
- add new functions for banning clients from server, in engine part. This will also make it possible to ban ipv6 addresses in old mods.
This commit is contained in:
parent
9a8cc99a93
commit
f8d8a1c2f7
9 changed files with 477 additions and 3 deletions
|
@ -511,6 +511,333 @@ static void SV_BanNum_f( void ) {
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_RehashBans_f
|
||||
|
||||
Load saved bans from file.
|
||||
==================
|
||||
*/
|
||||
void SV_RehashBans_f(void)
|
||||
{
|
||||
int index, filelen;
|
||||
fileHandle_t readfrom;
|
||||
char *textbuf, *curpos, *maskpos, *newlinepos, *endpos;
|
||||
char filepath[MAX_QPATH];
|
||||
|
||||
serverBansCount = 0;
|
||||
|
||||
if(!(curpos = Cvar_VariableString("fs_game")) || !*curpos)
|
||||
curpos = BASEGAME;
|
||||
|
||||
Com_sprintf(filepath, sizeof(filepath), "%s/%s", curpos, SERVER_BANFILE);
|
||||
|
||||
if((filelen = FS_SV_FOpenFileRead(filepath, &readfrom)) >= 0)
|
||||
{
|
||||
if(filelen < 2)
|
||||
{
|
||||
// Don't bother if file is too short.
|
||||
FS_FCloseFile(readfrom);
|
||||
return;
|
||||
}
|
||||
|
||||
curpos = textbuf = Z_Malloc(filelen);
|
||||
|
||||
filelen = FS_Read(textbuf, filelen, readfrom);
|
||||
FS_FCloseFile(readfrom);
|
||||
|
||||
endpos = textbuf + filelen;
|
||||
|
||||
for(index = 0; index < SERVER_MAXBANS && curpos + 2 < endpos; index++)
|
||||
{
|
||||
// find the end of the address string
|
||||
for(maskpos = curpos + 2; maskpos < endpos && *maskpos != ' '; maskpos++);
|
||||
|
||||
if(maskpos + 1 >= endpos)
|
||||
break;
|
||||
|
||||
*maskpos = '\0';
|
||||
maskpos++;
|
||||
|
||||
// find the end of the subnet specifier
|
||||
for(newlinepos = maskpos; newlinepos < endpos && *newlinepos != '\n'; newlinepos++);
|
||||
|
||||
if(newlinepos >= endpos)
|
||||
break;
|
||||
|
||||
*newlinepos = '\0';
|
||||
|
||||
if(NET_StringToAdr(curpos + 2, &serverBans[index].ip, NA_UNSPEC))
|
||||
{
|
||||
serverBans[index].isexception = !(curpos[0] == '0');
|
||||
serverBans[index].subnet = atoi(maskpos);
|
||||
|
||||
if(serverBans[index].ip.type == NA_IP &&
|
||||
(serverBans[index].subnet < 0 || serverBans[index].subnet > 32))
|
||||
{
|
||||
serverBans[index].subnet = 32;
|
||||
}
|
||||
else if(serverBans[index].ip.type == NA_IP6 &&
|
||||
(serverBans[index].subnet < 0 || serverBans[index].subnet > 128))
|
||||
{
|
||||
serverBans[index].subnet = 128;
|
||||
}
|
||||
}
|
||||
|
||||
curpos = newlinepos + 1;
|
||||
}
|
||||
|
||||
serverBansCount = index;
|
||||
|
||||
Z_Free(textbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_BanAddr_f
|
||||
|
||||
Ban a user from being able to play on this server based on his ip address.
|
||||
==================
|
||||
*/
|
||||
|
||||
static void SV_AddBanToList(qboolean isexception)
|
||||
{
|
||||
char *banstring, *suffix;
|
||||
netadr_t ip;
|
||||
int argc, mask;
|
||||
fileHandle_t writeto;
|
||||
|
||||
argc = Cmd_Argc();
|
||||
|
||||
if(argc < 2 || argc > 3)
|
||||
{
|
||||
Com_Printf ("Usage: %s (ip[/subnet] | clientnum [subnet])\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
|
||||
if(serverBansCount > sizeof(serverBans) / sizeof(*serverBans))
|
||||
{
|
||||
Com_Printf ("Error: Maximum number of bans/exceptions exceeded.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
banstring = Cmd_Argv(1);
|
||||
|
||||
if(strchr(banstring, '.') || strchr(banstring, ':'))
|
||||
{
|
||||
// This is an ip address, not a client num.
|
||||
|
||||
// Look for a CIDR-Notation suffix
|
||||
suffix = strchr(banstring, '/');
|
||||
if(suffix)
|
||||
{
|
||||
*suffix = '\0';
|
||||
suffix++;
|
||||
}
|
||||
|
||||
if(!NET_StringToAdr(banstring, &ip, NA_UNSPEC))
|
||||
{
|
||||
Com_Printf("Error: Invalid address %s\n", banstring);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client_t *cl;
|
||||
|
||||
// client num.
|
||||
if(!com_sv_running->integer)
|
||||
{
|
||||
Com_Printf("Server is not running.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cl = SV_GetPlayerByNum();
|
||||
|
||||
if(!cl)
|
||||
{
|
||||
Com_Printf("Error: Playernum %s does not exist.\n", Cmd_Argv(1));
|
||||
return;
|
||||
}
|
||||
|
||||
ip = cl->netchan.remoteAddress;
|
||||
|
||||
if(argc == 3)
|
||||
suffix = Cmd_Argv(2);
|
||||
else
|
||||
suffix = NULL;
|
||||
}
|
||||
|
||||
if(ip.type != NA_IP && ip.type != NA_IP6)
|
||||
{
|
||||
Com_Printf("Error: Can ban players connected via the internet only.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(suffix)
|
||||
{
|
||||
mask = atoi(suffix);
|
||||
|
||||
if(ip.type == NA_IP)
|
||||
{
|
||||
if(mask < 0 || mask > 32)
|
||||
mask = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mask < 0 || mask > 128)
|
||||
mask = 128;
|
||||
}
|
||||
}
|
||||
else if(ip.type == NA_IP)
|
||||
mask = 32;
|
||||
else
|
||||
mask = 128;
|
||||
|
||||
serverBans[serverBansCount].ip = ip;
|
||||
serverBans[serverBansCount].subnet = mask;
|
||||
serverBans[serverBansCount].isexception = isexception;
|
||||
|
||||
Com_Printf("Added %s: %s/%d\n", isexception ? "ban exception" : "ban",
|
||||
NET_AdrToString(ip), mask);
|
||||
|
||||
// Write out the ban information.
|
||||
if((writeto = FS_FOpenFileAppend(SERVER_BANFILE)))
|
||||
{
|
||||
char writebuf[128];
|
||||
|
||||
Com_sprintf(writebuf, sizeof(writebuf), "%d %s %d\n", isexception, NET_AdrToString(ip), mask);
|
||||
FS_Write(writebuf, strlen(writebuf), writeto);
|
||||
FS_FCloseFile(writeto);
|
||||
}
|
||||
|
||||
serverBansCount++;
|
||||
}
|
||||
|
||||
static void SV_DelBanFromList(qboolean isexception)
|
||||
{
|
||||
int index, count, todel;
|
||||
fileHandle_t writeto;
|
||||
|
||||
if(Cmd_Argc() != 2)
|
||||
{
|
||||
Com_Printf ("Usage: %s <num>\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
|
||||
todel = atoi(Cmd_Argv(1));
|
||||
|
||||
if(todel < 0 || todel > serverBansCount)
|
||||
return;
|
||||
|
||||
for(index = count = 0; index < serverBansCount; index++)
|
||||
{
|
||||
if(serverBans[index].isexception == isexception)
|
||||
{
|
||||
count++;
|
||||
|
||||
if(count == todel)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(index == serverBansCount - 1)
|
||||
serverBansCount--;
|
||||
else if(index < sizeof(serverBans) / sizeof(*serverBans) - 1)
|
||||
{
|
||||
memmove(serverBans + index, serverBans + index + 1, (serverBansCount - index - 1) * sizeof(*serverBans));
|
||||
serverBansCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("Error: No such entry #%d\n", todel);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write out the ban information.
|
||||
if((writeto = FS_FOpenFileWrite(SERVER_BANFILE)))
|
||||
{
|
||||
char writebuf[128];
|
||||
serverBan_t *curban;
|
||||
|
||||
for(index = 0; index < serverBansCount; index++)
|
||||
{
|
||||
curban = &serverBans[index];
|
||||
|
||||
Com_sprintf(writebuf, sizeof(writebuf), "%d %s %d\n",
|
||||
curban->isexception, NET_AdrToString(curban->ip), curban->subnet);
|
||||
FS_Write(writebuf, strlen(writebuf), writeto);
|
||||
}
|
||||
|
||||
FS_FCloseFile(writeto);
|
||||
}
|
||||
}
|
||||
|
||||
static void SV_ListBans_f(void)
|
||||
{
|
||||
int index, count;
|
||||
serverBan_t *ban;
|
||||
|
||||
// List all bans
|
||||
for(index = count = 0; index < serverBansCount; index++)
|
||||
{
|
||||
ban = &serverBans[index];
|
||||
if(!ban->isexception)
|
||||
{
|
||||
count++;
|
||||
|
||||
Com_Printf("Ban #%d: %s/%d\n", count,
|
||||
NET_AdrToString(ban->ip), ban->subnet);
|
||||
}
|
||||
}
|
||||
// List all exceptions
|
||||
for(index = count = 0; index < serverBansCount; index++)
|
||||
{
|
||||
ban = &serverBans[index];
|
||||
if(ban->isexception)
|
||||
{
|
||||
count++;
|
||||
|
||||
Com_Printf("Except #%d: %s/%d\n", count,
|
||||
NET_AdrToString(ban->ip), ban->subnet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SV_FlushBans_f(void)
|
||||
{
|
||||
fileHandle_t blankf;
|
||||
|
||||
serverBansCount = 0;
|
||||
|
||||
// empty the ban file.
|
||||
blankf = FS_FOpenFileWrite(SERVER_BANFILE);
|
||||
|
||||
if(blankf)
|
||||
FS_FCloseFile(blankf);
|
||||
}
|
||||
|
||||
static void SV_BanAddr_f(void)
|
||||
{
|
||||
SV_AddBanToList(qfalse);
|
||||
}
|
||||
|
||||
static void SV_ExceptAddr_f(void)
|
||||
{
|
||||
SV_AddBanToList(qtrue);
|
||||
}
|
||||
|
||||
static void SV_BanDel_f(void)
|
||||
{
|
||||
SV_DelBanFromList(qfalse);
|
||||
}
|
||||
|
||||
static void SV_ExceptDel_f(void)
|
||||
{
|
||||
SV_DelBanFromList(qtrue);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_KickNum_f
|
||||
|
@ -763,6 +1090,14 @@ void SV_AddOperatorCommands( void ) {
|
|||
if( com_dedicated->integer ) {
|
||||
Cmd_AddCommand ("say", SV_ConSay_f);
|
||||
}
|
||||
|
||||
Cmd_AddCommand("rehashbans", SV_RehashBans_f);
|
||||
Cmd_AddCommand("listbans", SV_ListBans_f);
|
||||
Cmd_AddCommand("banaddr", SV_BanAddr_f);
|
||||
Cmd_AddCommand("exceptaddr", SV_ExceptAddr_f);
|
||||
Cmd_AddCommand("bandel", SV_BanDel_f);
|
||||
Cmd_AddCommand("exceptdel", SV_ExceptDel_f);
|
||||
Cmd_AddCommand("flushbans", SV_FlushBans_f);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue