fixed sw build, fixed server banning, banip works properly and accepts the format x.x.x.x/n and x.x.x.x/x.x.x.x, added unban and banlist

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2294 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
TimeServ 2006-05-22 22:51:14 +00:00
parent f375d5d6ac
commit c19474d271
7 changed files with 440 additions and 54 deletions

View file

@ -210,7 +210,7 @@ extern cvar_t r_waterwarp;
extern cvar_t r_fullbright;
extern cvar_t r_shadows;
extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha;
cvar_t r_wateralpha = SCVAR("r_wateralpha","1");
cvar_t r_dynamic = SCVARF("r_dynamic","1", CVAR_ARCHIVE);
cvar_t r_flashblend = SCVARF("gl_flashblend","0", CVAR_ARCHIVE);
cvar_t r_lightstylesmooth = SCVAR("r_lightstylesmooth", "0");

View file

@ -84,6 +84,11 @@ qboolean NET_IsClientLegal(netadr_t *adr);
qboolean NET_IsLoopBackAddress (netadr_t adr);
qboolean NET_StringToAdrMasked (char *s, netadr_t *a, netadr_t *amask);
char *NET_AdrToStringMasked (netadr_t a, netadr_t amask);
void NET_IntegerToMask (netadr_t *a, netadr_t *amask, int bits);
qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask);
//============================================================================
#define OLD_AVG 0.99 // total = oldtotal*OLD_AVG + new*(1-OLD_AVG)

View file

@ -575,6 +575,323 @@ qboolean NET_StringToAdr (char *s, netadr_t *a)
return true;
}
// NET_IntegerToMask: given a source address pointer, a mask address pointer, and
// desired number of bits, fills the mask pointer with given bits
// (bits < 0 will always fill all bits)
void NET_IntegerToMask (netadr_t *a, netadr_t *amask, int bits)
{
int i;
qbyte *n;
memset (amask, 0, sizeof(*amask));
amask->type = a->type;
if (bits < 0)
i = 8000; // fill all bits
else
i = bits;
switch (amask->type)
{
#ifdef USEIPX
case NA_IPX:
case NA_BROADCAST_IPX:
n = amask->address.ipx;
if (i > 80)
i = 80;
for (; i >= 8; i -= 8)
{
*n = 0xFF;
n++;
}
// fill last bit
if (i)
{
i = (~((1 << i) - 1)) & 0xFF;
*n = i;
}
break;
#endif
#ifdef IPPROTO_IPV6
case NA_IPV6:
case NA_BROADCAST_IP6:
n = amask->address.ip6;
if (i > 128)
i = 128;
for (; i >= 8; i -= 8)
{
*n = 0xFF;
n++;
}
// fill last bit
if (i)
{
i = (~((1 << i) - 1)) & 0xFF;
*n = i;
}
break;
#endif
case NA_IP:
case NA_BROADCAST_IP:
n = amask->address.ip;
if (i > 32)
i = 32;
for (; i >= 8; i -= 8)
{
*n = 0xFF;
n++;
}
// fill last bit
if (i)
{
i = (~((1 << i) - 1)) & 0xFF;
*n = i;
}
break;
}
}
// NET_StringToAdrMasked: extension to NET_StringToAdr to handle IP addresses
// with masks or integers representing the bit masks
qboolean NET_StringToAdrMasked (char *s, netadr_t *a, netadr_t *amask)
{
char t[64];
char *spoint;
int i;
spoint = strchr(s, '/');
if (spoint)
{
// we have a slash in the address so split and resolve separately
char *c;
i = spoint - s;
if (i + 1 > sizeof(t))
i = sizeof(t);
Q_strncpyz(t, s, i);
if (!NET_StringToAdr(t, a))
return false;
spoint++;
c = spoint;
if (!*c)
return false;
while (*c) // check for non-numeric characters
{
if (*c < '0' || *c > '9')
{
c = NULL;
break;
}
c++;
}
if (c == NULL) // we have an address so resolve it and return
return NET_StringToAdr(spoint, amask);
// otherwise generate mask for given bits
i = atoi(spoint);
NET_IntegerToMask(a, amask, i);
}
else
{
// we don't have a slash, resolve and fill with a full mask
if (!NET_StringToAdr(s, a))
return false;
memset (amask, 0, sizeof(*amask));
amask->type = a->type;
NET_IntegerToMask(a, amask, -1);
}
return true;
}
// NET_CompareAdrMasked: given 3 addresses, 2 to compare with a complimentary mask,
// returns true or false if they match
qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask)
{
int i;
// check to make sure all types match
if (a.type != b.type || a.type != mask.type)
return false;
// check port if both are non-zero
if (a.port && b.port && a.port != b.port)
return false;
// match on protocol type and compare address
switch (a.type)
{
case NA_LOOPBACK:
return true;
case NA_BROADCAST_IP:
case NA_IP:
for (i = 0; i < 4; i++)
{
if ((a.address.ip[i] & mask.address.ip[i]) != (b.address.ip[i] & mask.address.ip[i]))
return false;
}
break;
#ifdef IPPROTO_IPV6
case NA_BROADCAST_IP6:
case NA_IPV6:
for (i = 0; i < 16; i++)
{
if ((a.address.ip6[i] & mask.address.ip6[i]) != (b.address.ip6[i] & mask.address.ip6[i]))
return false;
}
break;
#endif
#ifdef USEIPX
case NA_BROADCAST_IPX:
case NA_IPX:
for (i = 0; i < 10; i++)
{
if ((a.address.ipx[i] & mask.address.ipx[i]) != (b.address.ipx[i] & mask.address.ipx[i]))
return false;
}
break;
#endif
default:
return false; // invalid protocol
}
return true; // all checks passed
}
// UniformMaskedBits: counts number of bits in an assumed uniform mask, returns
// -1 if not uniform
int UniformMaskedBits(netadr_t mask)
{
int bits;
int b;
int bs;
qboolean bitenc = false;
switch (mask.type)
{
case NA_BROADCAST_IP:
case NA_IP:
bits = 32;
for (b = 3; b >= 0; b--)
{
if (mask.address.ip[b] == 0xFF)
bitenc = true;
else if (mask.address.ip[b])
{
bs = ~mask.address.ip[b];
while (bs)
{
if (bs & 1)
{
bits -= 1;
if (bitenc)
return -1;
}
else
bitenc = true;
bs >>= 1;
}
}
else if (bitenc)
return -1;
else
bits -= 8;
}
break;
#ifdef IPPROTO_IPV6
case NA_BROADCAST_IP6:
case NA_IPV6:
bits = 128;
for (b = 15; b >= 0; b--)
{
if (mask.address.ip6[b] == 0xFF)
bitenc = true;
else if (mask.address.ip6[b])
{
bs = ~mask.address.ip6[b];
while (bs)
{
if (bs & 1)
{
bits -= 1;
if (bitenc)
return -1;
}
else
bitenc = true;
bs >>= 1;
}
}
else if (bitenc)
return -1;
else
bits -= 8;
}
break;
#endif
#ifdef USEIPX
case NA_BROADCAST_IPX:
case NA_IPX:
bits = 80;
for (b = 9; b >= 0; b--)
{
if (mask.address.ipx[b] == 0xFF)
bitenc = true;
else if (mask.address.ipx[b])
{
bs = ~mask.address.ipx[b];
while (bs)
{
if (bs & 1)
{
bits -= 1;
if (bitenc)
return -1;
}
else
bitenc = true;
bs >>= 1;
}
}
else if (bitenc)
return -1;
else
bits -= 8;
}
break;
#endif
default:
return -1; // invalid protocol
}
return bits; // all checks passed
}
char *NET_AdrToStringMasked (netadr_t a, netadr_t amask)
{
static char s[128];
int i;
i = UniformMaskedBits(amask);
if (i >= 0)
sprintf(s, "%s/%i", NET_AdrToString(a), i);
else
sprintf(s, "%s/%s", NET_AdrToString(a), NET_AdrToString(amask));
return s;
}
// Returns true if we can't bind the address locally--in other words,
// the IP is NOT one of our interfaces.
qboolean NET_IsClientLegal(netadr_t *adr)

View file

@ -104,7 +104,6 @@ cvar_t r_norefresh = SCVAR("r_norefresh","0");
//cvar_t r_speeds = SCVAR("r_speeds","0");
//cvar_t r_fullbright = SCVAR("r_fullbright","0");
cvar_t r_mirroralpha = SCVARF("r_mirroralpha","1", CVAR_CHEAT);
cvar_t r_wateralpha = SCVAR("r_wateralpha","1");
//cvar_t r_waterwarp = SCVAR("r_waterwarp", "0");
cvar_t r_novis = SCVAR("r_novis","0");
//cvar_t r_netgraph = SCVAR("r_netgraph","0");

View file

@ -650,6 +650,7 @@ typedef struct
typedef struct bannedips_s {
struct bannedips_s *next;
netadr_t adr;
netadr_t adrmask;
} bannedips_t;
typedef enum {
@ -1060,7 +1061,6 @@ void ClientReliableWrite_SZ(client_t *cl, void *data, int len);
#ifdef SVRANKING
//flags
#define RANK_BANNED 1
#define RANK_MUTED 2
#define RANK_CUFFED 4
#define RANK_CRIPPLED 8 //ha ha... get speed cheaters with this!... :o)

View file

@ -634,18 +634,32 @@ void SV_Kick_f (void)
Con_TPrintf (STL_USERDOESNTEXIST, Cmd_Argv(1));
}
void SV_BanIP_f (void)
void SV_BanName_f (void)
{
client_t *cl;
int clnum=-1;
if (Cmd_Argc() < 2)
{
Con_Printf("%s userid|nick\n", Cmd_Argv(0));
return;
}
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
if (cl)
{
bannedips_t *nb;
if (NET_IsLoopBackAddress(cl->netchan.remote_address))
{
Con_Printf("You're not allowed to ban loopback!\n");
continue;
}
nb = Z_Malloc(sizeof(bannedips_t));
nb->next = svs.bannedips;
nb->adr = cl->netchan.remote_address;
NET_IntegerToMask(&nb->adr, &nb->adrmask, -1); // fill mask
if (*Cmd_Argv(2)) //explicit blocking of all ports of a client ip
nb->adr.port = 0;
svs.bannedips = nb;
@ -661,38 +675,108 @@ void SV_BanIP_f (void)
Con_TPrintf (STL_USERDOESNTEXIST, Cmd_Argv(1));
}
void SV_BanName_f (void)
void SV_BanIP_f (void)
{
netadr_t banadr;
netadr_t banmask;
int i;
client_t *cl;
int clnum=-1;
#ifdef SVRANKING
rankstats_t rs;
#endif
bannedips_t *nb;
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
if (Cmd_Argc() < 2)
{
SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTWASBANNED, cl->name);
// print directly, because the dropped client won't get the
// SV_BroadcastPrintf message
SV_ClientTPrintf (cl, PRINT_HIGH, STL_YOUWEREBANNED);
#ifdef SVRANKING
if (cl->rankid)
{
if (Rank_GetPlayerStats(cl->rankid, &rs))
{
rs.flags1 |= RANK_BANNED;
Rank_SetPlayerStats(cl->rankid, &rs);
}
}
else
Con_Printf("User is not using an account\n");
#endif
SV_DropClient (cl);
Con_Printf("%s address/mask|adress/maskbits\n", Cmd_Argv(0));
return;
}
if (clnum == -1)
Con_TPrintf (STL_USERDOESNTEXIST, Cmd_Argv(1));
if (!NET_StringToAdrMasked(Cmd_Argv(1), &banadr, &banmask))
{
Con_Printf("invalid address or mask\n");
return;
}
if (NET_IsLoopBackAddress(banadr))
{
Con_Printf("You're not allowed to ban loopback!\n");
return;
}
// loop through clients and kick the ones that match
for (i = 0, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++)
{
if (cl->state<=cs_zombie)
continue;
if (NET_CompareAdrMasked(cl->netchan.remote_address, banadr, banmask))
{
// match, so kick
SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTWASBANNED, cl->name);
// print directly, because the dropped client won't get the
// SV_BroadcastPrintf message
SV_ClientTPrintf (cl, PRINT_HIGH, STL_YOUWEREBANNED);
SV_DropClient (cl);
}
}
// add IP and mask to ban list
nb = Z_Malloc(sizeof(bannedips_t));
nb->next = svs.bannedips;
nb->adr = banadr;
nb->adrmask = banmask;
svs.bannedips = nb;
}
void SV_BanList_f (void)
{
int bancount = 0;
bannedips_t *nb = svs.bannedips;
while (nb)
{
Con_Printf("%s\n", NET_AdrToStringMasked(nb->adr, nb->adrmask));
bancount++;
nb = nb->next;
}
Con_Printf("%i total entries in ban list\n", bancount);
}
void SV_Unban_f (void)
{
qboolean all = false;
bannedips_t *nb = svs.bannedips;
bannedips_t *nbnext;
netadr_t unbanadr = {0};
netadr_t unbanmask = {0};
if (Cmd_Argc() < 2)
{
Con_Printf("%s address/mask|address/maskbits|all\n", Cmd_Argv(0));
return;
}
if (!Q_strcasecmp(Cmd_Argv(1), "all"))
all = true;
else if (!NET_StringToAdrMasked(Cmd_Argv(1), &unbanadr, &unbanmask))
{
Con_Printf("invalid address or mask\n");
return;
}
while (nb)
{
nbnext = nb->next;
if (NET_CompareAdrMasked(nb->adr, unbanadr, unbanmask))
{
if (!all)
Con_Printf("unbanned %s\n", NET_AdrToStringMasked(nb->adr, nb->adrmask));
if (svs.bannedips == nb)
svs.bannedips = nbnext;
Z_Free(nb);
}
nb = nbnext;
}
}
void SV_ForceName_f (void)
@ -1717,7 +1801,9 @@ void SV_InitOperatorCommands (void)
Cmd_AddCommand ("renameclient", SV_ForceName_f);
Cmd_AddCommand ("cripple", SV_CripplePlayer_f);
Cmd_AddCommand ("banname", SV_BanName_f);
Cmd_AddCommand ("banlist", SV_BanList_f);
Cmd_AddCommand ("banip", SV_BanIP_f);
Cmd_AddCommand ("unban", SV_Unban_f);
// Cmd_AddCommand ("ban", SV_BanName_f);
Cmd_AddCommand ("status", SV_Status_f);

View file

@ -1762,21 +1762,10 @@ client_t *SVC_DirectConnect(void)
bannedips_t *banip;
for (banip = svs.bannedips; banip; banip=banip->next)
{
if (banip->adr.port)
if (NET_CompareAdrMasked(adr, banip->adr, banip->adrmask))
{
if (NET_CompareAdr (adr, newcl->netchan.remote_address))
{
SV_RejectMessage (protocol, "You were banned.\nContact the administrator to complain.\n");
return NULL;
}
}
else
{
if (NET_CompareBaseAdr (adr, newcl->netchan.remote_address))
{
SV_RejectMessage (protocol, "You were banned.\nContact the administrator to complain.\n");
return NULL;
}
SV_RejectMessage (protocol, "You were banned.\nContact the administrator to complain.\n");
return NULL;
}
}
//yay, a legit client who we havn't banned yet.
@ -1917,16 +1906,6 @@ client_t *SVC_DirectConnect(void)
return NULL;
}
if (rs.flags1 & RANK_BANNED)
{
SV_RejectMessage (protocol, "You were banned.\nContact the administrator to complain.\n");
Con_Printf("banned player %s is trying to connect\n", newcl->name);
newcl->name[0] = 0;
memset (newcl->userinfo, 0, sizeof(newcl->userinfo));
newcl->state = cs_free;
return NULL;
}
if (rs.flags1 & RANK_MUTED)
{
SV_BroadcastTPrintf(PRINT_MEDIUM, STL_CLIENTISSTILLMUTED, newcl->name);