mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 14:42:13 +00:00
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:
parent
f375d5d6ac
commit
c19474d271
7 changed files with 440 additions and 54 deletions
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue