- Attach ban reasons to banned_t

- Properly call D_SaveBan after remote bans. Bans are no longer saved in the ban command and instead wait for the actual kick to process, since before they were split between the two, which is what caused the discrepancy.

# Conflicts:
#	src/d_clisrv.c
#	src/i_tcp.c
This commit is contained in:
toaster 2022-06-14 16:58:07 +01:00
parent 2f0e1521d0
commit 24181ae738
4 changed files with 77 additions and 106 deletions

View file

@ -2637,40 +2637,27 @@ static void CL_ConnectToServer(void)
}
#ifndef NONET
typedef struct banreason_s
{
char *reason;
struct banreason_s *prev; //-1
struct banreason_s *next; //+1
} banreason_t;
static banreason_t *reasontail = NULL; //last entry, use prev
static banreason_t *reasonhead = NULL; //1st entry, use next
static void Command_ShowBan(void) //Print out ban list
{
size_t i;
const char *address, *mask;
banreason_t *reasonlist = reasonhead;
const char *address, *mask, *reason;
if (I_GetBanAddress)
CONS_Printf(M_GetText("Ban List:\n"));
else
return;
for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++)
for (i = 0; (address = I_GetBanAddress(i)) != NULL; i++)
{
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
CONS_Printf("%s: %s ", sizeu1(i+1), address);
else
CONS_Printf("%s: %s/%s ", sizeu1(i+1), address, mask);
if (reasonlist && reasonlist->reason)
CONS_Printf("(%s)\n", reasonlist->reason);
if (I_GetBanReason && (reason = I_GetBanReason(i)) != NULL)
CONS_Printf("(%s)\n", reason);
else
CONS_Printf("\n");
if (reasonlist) reasonlist = reasonlist->next;
}
if (i == 0 && !address)
@ -2681,13 +2668,10 @@ void D_SaveBan(void)
{
FILE *f;
size_t i;
banreason_t *reasonlist = reasonhead;
const char *address, *mask;
const char *address, *mask, *reason;
const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt");
if (!reasonhead)
return;
f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "w");
f = fopen(path, "w");
if (!f)
{
@ -2695,66 +2679,36 @@ void D_SaveBan(void)
return;
}
for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++)
for (i = 0; (address = I_GetBanAddress(i)) != NULL; i++)
{
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
fprintf(f, "%s 0", address);
else
fprintf(f, "%s %s", address, mask);
if (reasonlist && reasonlist->reason)
fprintf(f, " %s\n", reasonlist->reason);
if (I_GetBanReason && (reason = I_GetBanReason(i)) != NULL)
fprintf(f, " %s\n", reason);
else
fprintf(f, " %s\n", "NA");
if (reasonlist) reasonlist = reasonlist->next;
fprintf(f, " %s\n", "No reason given");
}
fclose(f);
}
static void Ban_Add(const char *reason)
{
banreason_t *reasonlist = malloc(sizeof(*reasonlist));
if (!reasonlist)
return;
if (!reason)
reason = "NA";
reasonlist->next = NULL;
reasonlist->reason = Z_StrDup(reason);
if ((reasonlist->prev = reasontail) == NULL)
reasonhead = reasonlist;
else
reasontail->next = reasonlist;
reasontail = reasonlist;
}
static void Command_ClearBans(void)
{
banreason_t *temp;
if (!I_ClearBans)
return;
I_ClearBans();
D_SaveBan();
reasontail = NULL;
while (reasonhead)
{
temp = reasonhead->next;
Z_Free(reasonhead->reason);
free(reasonhead);
reasonhead = temp;
}
}
static void Ban_Load_File(boolean warning)
{
FILE *f;
size_t i;
const char *address, *mask;
const char *address, *mask, *reason;
char buffer[MAX_WADPATH];
f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r");
@ -2766,22 +2720,17 @@ static void Ban_Load_File(boolean warning)
return;
}
if (I_ClearBans)
Command_ClearBans();
else
{
fclose(f);
return;
}
I_ClearBans();
for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++)
{
address = strtok(buffer, " \t\r\n");
mask = strtok(NULL, " \t\r\n");
reason = strtok(NULL, "\r\n");
I_SetBanAddress(address, mask);
Ban_Add(strtok(NULL, "\r\n"));
if (I_SetBanReason)
I_SetBanReason(reason);
}
fclose(f);
@ -3140,54 +3089,37 @@ static void Command_Ban(void)
XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
UINT8 *p = buf;
const SINT8 pn = nametonum(COM_Argv(1));
const INT32 node = playernode[(INT32)pn];
if (pn == -1 || pn == 0)
return;
WRITEUINT8(p, pn);
if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now
if (COM_Argc() == 2)
{
CONS_Alert(CONS_WARNING, M_GetText("Ban failed. Invalid node?\n"));
WRITEUINT8(p, KICK_MSG_GO_AWAY);
WRITEUINT8(p, KICK_MSG_BANNED);
SendNetXCmd(XD_KICK, &buf, 2);
}
else
{
if (server) // only the server is allowed to do this right now
size_t i, j = COM_Argc();
char message[MAX_REASONLENGTH];
//Steal from the motd code so you don't have to put the reason in quotes.
strlcpy(message, COM_Argv(2), sizeof message);
for (i = 3; i < j; i++)
{
Ban_Add(COM_Argv(2));
D_SaveBan(); // save the ban list
strlcat(message, " ", sizeof message);
strlcat(message, COM_Argv(i), sizeof message);
}
if (COM_Argc() == 2)
{
WRITEUINT8(p, KICK_MSG_BANNED);
SendNetXCmd(XD_KICK, &buf, 2);
}
else
{
size_t i, j = COM_Argc();
char message[MAX_REASONLENGTH];
//Steal from the motd code so you don't have to put the reason in quotes.
strlcpy(message, COM_Argv(2), sizeof message);
for (i = 3; i < j; i++)
{
strlcat(message, " ", sizeof message);
strlcat(message, COM_Argv(i), sizeof message);
}
WRITEUINT8(p, KICK_MSG_CUSTOM_BAN);
WRITESTRINGN(p, message, MAX_REASONLENGTH);
SendNetXCmd(XD_KICK, &buf, p - buf);
}
WRITEUINT8(p, KICK_MSG_CUSTOM_BAN);
WRITESTRINGN(p, message, MAX_REASONLENGTH);
SendNetXCmd(XD_KICK, &buf, p - buf);
}
}
else
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
}
static void Command_BanIP(void)
@ -3208,7 +3140,6 @@ static void Command_BanIP(void)
else
reason = COM_Argv(2);
if (I_SetBanAddress && I_SetBanAddress(address, NULL))
{
if (reason)
@ -3216,7 +3147,8 @@ static void Command_BanIP(void)
else
CONS_Printf("Banned IP address %s\n", address);
Ban_Add(reason);
if (I_SetBanReason)
I_SetBanReason(reason);
D_SaveBan();
}
else
@ -3357,16 +3289,21 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
//CONS_Printf("\x82%s ", player_names[pnum]);
// If a verified admin banned someone, the server needs to know about it.
// If the playernum isn't zero (the server) then the server needs to record the ban.
if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
// Save bans here. Used to be split between here and the actual command, depending on
// whenever the server did it or a remote admin did it, but it's simply more convenient
// to keep it all in one place.
if (server && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
{
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
#ifndef NONET
{
CONS_Alert(CONS_WARNING, M_GetText("Ban failed. Invalid node?\n"));
}
else
Ban_Add(reason);
#endif
{
if (I_SetBanReason)
I_SetBanReason(reason);
D_SaveBan();
}
}
if (msg == KICK_MSG_PLAYER_QUIT)

View file

@ -79,7 +79,9 @@ void (*I_ClearBans)(void) = NULL;
const char *(*I_GetNodeAddress) (INT32 node) = NULL;
const char *(*I_GetBanAddress) (size_t ban) = NULL;
const char *(*I_GetBanMask) (size_t ban) = NULL;
const char *(*I_GetBanReason) (size_t ban) = NULL;
boolean (*I_SetBanAddress) (const char *address, const char *mask) = NULL;
boolean (*I_SetBanReason) (const char *reason) = NULL;
boolean *bannednode = NULL;

View file

@ -145,7 +145,9 @@ extern void (*I_ClearBans)(void);
extern const char *(*I_GetNodeAddress) (INT32 node);
extern const char *(*I_GetBanAddress) (size_t ban);
extern const char *(*I_GetBanMask) (size_t ban);
extern const char *(*I_GetBanReason) (size_t ban);
extern boolean (*I_SetBanAddress) (const char *address,const char *mask);
extern boolean (*I_SetBanReason) (const char *reason);
extern boolean *bannednode;
/// \brief Called by D_SRB2Main to be defined by extern network driver

View file

@ -235,6 +235,7 @@ typedef struct
{
mysockaddr_t address;
UINT8 mask;
char *reason;
// TODO: timestamp, for tempbans!
} banned_t;
@ -498,6 +499,16 @@ static const char *SOCK_GetBanMask(size_t ban)
return NULL;
}
static const char *SOCK_GetBanReason(size_t ban)
{
#ifdef NONET
(void)ban;
return NULL;
#else
return banned[ban].reason;
#endif
}
#ifndef NONET
static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
{
@ -1521,6 +1532,23 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
#endif
}
static boolean SOCK_SetBanReason(const char *reason)
{
#ifdef NONET
(void)reason;
return false;
#else
if (!reason)
{
reason = "No reason given";
}
banned[numbans - 1].reason = Z_StrDup(reason);
return true;
#endif
}
static void SOCK_ClearBans(void)
{
numbans = 0;
@ -1617,7 +1645,9 @@ boolean I_InitTcpNetwork(void)
I_GetNodeAddress = SOCK_GetNodeAddress;
I_GetBanAddress = SOCK_GetBanAddress;
I_GetBanMask = SOCK_GetBanMask;
I_GetBanReason = SOCK_GetBanReason;
I_SetBanAddress = SOCK_SetBanAddress;
I_SetBanReason = SOCK_SetBanReason;
bannednode = SOCK_bannednode;
return ret;