mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-20 06:58:20 +00:00
finished the ban support
This commit is contained in:
parent
b281831d5d
commit
b42eb55794
|
@ -135,6 +135,6 @@ int server_tick();
|
|||
*/
|
||||
int server_tickspeed();
|
||||
|
||||
int server_ban_add(NETADDR addr, int type, int seconds);
|
||||
int server_ban_add(NETADDR addr, int seconds);
|
||||
int server_ban_remove(NETADDR addr);
|
||||
#endif
|
||||
|
|
|
@ -264,6 +264,20 @@ unsigned char *unpack_chunk_header(unsigned char *data, NETCHUNKHEADER *header)
|
|||
}
|
||||
|
||||
|
||||
void send_controlmsg(NETSOCKET socket, NETADDR *addr, int ack, int controlmsg, const void *extra, int extra_size)
|
||||
{
|
||||
NETPACKETCONSTRUCT construct;
|
||||
construct.flags = NET_PACKETFLAG_CONTROL;
|
||||
construct.ack = ack;
|
||||
construct.num_chunks = 0;
|
||||
construct.data_size = 1+extra_size;
|
||||
construct.chunk_data[0] = controlmsg;
|
||||
mem_copy(&construct.chunk_data[1], extra, extra_size);
|
||||
|
||||
/* send the control message */
|
||||
send_packet(socket, addr, &construct);
|
||||
}
|
||||
|
||||
void netcommon_openlog(const char *sentlog, const char *recvlog)
|
||||
{
|
||||
if(sentlog)
|
||||
|
|
|
@ -18,7 +18,6 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
NETADDR addr;
|
||||
int type;
|
||||
int expires;
|
||||
} NETBANINFO;
|
||||
|
||||
|
@ -72,7 +71,7 @@ int netserver_drop(NETSERVER *s, int client_id, const char *reason);
|
|||
int netserver_client_addr(NETSERVER *s, int client_id, NETADDR *addr);
|
||||
int netserver_max_clients(NETSERVER *s);
|
||||
|
||||
int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds);
|
||||
int netserver_ban_add(NETSERVER *s, NETADDR addr, int seconds);
|
||||
int netserver_ban_remove(NETSERVER *s, NETADDR addr);
|
||||
int netserver_ban_num(NETSERVER *s); /* caution, slow */
|
||||
int netserver_ban_get(NETSERVER *s, int index, NETBANINFO *info); /* caution, slow */
|
||||
|
|
|
@ -129,19 +129,11 @@ void conn_queue_chunk(NETCONNECTION *conn, int flags, int data_size, const void
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void conn_send_control(NETCONNECTION *conn, int controlmsg, const void *extra, int extra_size)
|
||||
{
|
||||
NETPACKETCONSTRUCT construct;
|
||||
construct.flags = NET_PACKETFLAG_CONTROL;
|
||||
construct.ack = conn->ack;
|
||||
construct.num_chunks = 0;
|
||||
construct.data_size = 1+extra_size;
|
||||
construct.chunk_data[0] = controlmsg;
|
||||
mem_copy(&construct.chunk_data[1], extra, extra_size);
|
||||
|
||||
/* send the control message */
|
||||
send_packet(conn->socket, &conn->peeraddr, &construct);
|
||||
conn->last_send_time = time_get();
|
||||
send_controlmsg(conn->socket, &conn->peeraddr, conn->ack, controlmsg, extra, extra_size);
|
||||
}
|
||||
|
||||
static void conn_resend_chunk(NETCONNECTION *conn, NETCHUNKDATA *resend)
|
||||
|
|
|
@ -127,6 +127,7 @@ typedef struct NETRECVINFO
|
|||
unsigned char buffer[NET_MAX_PACKETSIZE];
|
||||
} NETRECVINFO;
|
||||
|
||||
/* */
|
||||
|
||||
/* connection functions */
|
||||
void conn_init(NETCONNECTION *conn, NETSOCKET socket);
|
||||
|
@ -145,6 +146,7 @@ void recvinfo_start(NETRECVINFO *info, NETADDR *addr, NETCONNECTION *conn, int c
|
|||
int recvinfo_fetch_chunk(NETRECVINFO *info, NETCHUNK *chunk);
|
||||
|
||||
/* misc helper functions */
|
||||
void send_controlmsg(NETSOCKET socket, NETADDR *addr, int ack, int controlmsg, const void *extra, int extra_size);
|
||||
void send_packet_connless(NETSOCKET socket, NETADDR *addr, const void *data, int data_size);
|
||||
void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *packet);
|
||||
int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *packet);
|
||||
|
|
|
@ -11,13 +11,38 @@ typedef struct NETBAN
|
|||
{
|
||||
NETBANINFO info;
|
||||
|
||||
/* hash list */
|
||||
struct NETBAN *hashnext;
|
||||
struct NETBAN *hashprev;
|
||||
|
||||
/* used or free list */
|
||||
struct NETBAN *next;
|
||||
struct NETBAN *prev;
|
||||
} NETBAN;
|
||||
|
||||
#define MACRO_LIST_LINK_FIRST(object, first, prev, next) \
|
||||
{ if(first) first->prev = object; \
|
||||
object->prev = (void*)0; \
|
||||
object->next = first; \
|
||||
first = object; }
|
||||
|
||||
#define MACRO_LIST_LINK_AFTER(object, after, prev, next) \
|
||||
{ object->prev = after; \
|
||||
object->next = after->next; \
|
||||
after->next = object; \
|
||||
if(object->next) \
|
||||
object->next->prev = object; \
|
||||
}
|
||||
|
||||
#define MACRO_LIST_UNLINK(object, first, prev, next) \
|
||||
{ if(object->next) object->next->prev = object->prev; \
|
||||
if(object->prev) object->prev->next = object->next; \
|
||||
else first = object->next; \
|
||||
object->next = 0; object->prev = 0; }
|
||||
|
||||
#define MACRO_LIST_FIND(start, next, expression) \
|
||||
{ while(start && !(expression)) start = start->next; }
|
||||
|
||||
struct NETSERVER
|
||||
{
|
||||
NETSOCKET socket;
|
||||
|
@ -129,29 +154,52 @@ int netserver_ban_num(NETSERVER *s)
|
|||
return count;
|
||||
}
|
||||
|
||||
int netserver_ban_remove(NETSERVER *s, NETADDR addr)
|
||||
static void netserver_ban_remove_by_object(NETSERVER *s, NETBAN *ban)
|
||||
{
|
||||
return 0;
|
||||
int iphash = (ban->info.addr.ip[0]+ban->info.addr.ip[1]+ban->info.addr.ip[2]+ban->info.addr.ip[3])&0xff;
|
||||
dbg_msg("netserver", "removing ban on %d.%d.%d.%d",
|
||||
ban->info.addr.ip[0], ban->info.addr.ip[1], ban->info.addr.ip[2], ban->info.addr.ip[3]);
|
||||
MACRO_LIST_UNLINK(ban, s->banpool_firstused, prev, next);
|
||||
MACRO_LIST_UNLINK(ban, s->bans[iphash], hashprev, hashnext);
|
||||
MACRO_LIST_LINK_FIRST(ban, s->banpool_firstfree, prev, next);
|
||||
}
|
||||
|
||||
int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
|
||||
int netserver_ban_remove(NETSERVER *s, NETADDR addr)
|
||||
{
|
||||
int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff;
|
||||
unsigned stamp = time_timestamp() + seconds;
|
||||
NETBAN *ban = s->bans[iphash];
|
||||
|
||||
MACRO_LIST_FIND(ban, hashnext, net_addr_comp(&ban->info.addr, &addr) == 0);
|
||||
|
||||
if(ban)
|
||||
{
|
||||
netserver_ban_remove_by_object(s, ban);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int netserver_ban_add(NETSERVER *s, NETADDR addr, int seconds)
|
||||
{
|
||||
int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff;
|
||||
unsigned stamp = 0xffffffff;
|
||||
NETBAN *ban;
|
||||
NETBAN *insert_after;
|
||||
|
||||
/* remove the port */
|
||||
addr.port = 0;
|
||||
|
||||
if(seconds)
|
||||
stamp = time_timestamp() + seconds;
|
||||
|
||||
/* search to see if it already exists */
|
||||
for(ban = s->bans[iphash]; ban; ban = ban->hashnext)
|
||||
ban = s->bans[iphash];
|
||||
MACRO_LIST_FIND(ban, hashnext, net_addr_comp(&ban->info.addr, &addr) == 0);
|
||||
if(ban)
|
||||
{
|
||||
if(net_addr_comp(&ban->info.addr, &addr) == 0)
|
||||
{
|
||||
if(ban->info.expires < stamp)
|
||||
{
|
||||
/* decide what to do here */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/* adjust the ban */
|
||||
ban->info.expires = stamp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!s->banpool_firstfree)
|
||||
|
@ -159,48 +207,45 @@ int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
|
|||
|
||||
/* fetch and clear the new ban */
|
||||
ban = s->banpool_firstfree;
|
||||
s->banpool_firstfree->prev = 0;
|
||||
ban->next = 0;
|
||||
ban->prev = 0;
|
||||
ban->info.expires = 0;
|
||||
if(seconds)
|
||||
MACRO_LIST_UNLINK(ban, s->banpool_firstfree, prev, next);
|
||||
|
||||
/* setup the ban info */
|
||||
ban->info.expires = stamp;
|
||||
ban->info.type = type;
|
||||
ban->info.addr = addr;
|
||||
|
||||
/* add it to the ban hash */
|
||||
if(s->bans[iphash])
|
||||
s->bans[iphash]->hashprev = ban;
|
||||
ban->hashnext = s->bans[iphash];
|
||||
ban->hashprev = 0;
|
||||
s->bans[iphash] = ban;
|
||||
MACRO_LIST_LINK_FIRST(ban, s->bans[iphash], hashprev, hashnext);
|
||||
|
||||
/* insert it into the used list */
|
||||
insert_after = s->banpool_firstused;
|
||||
while(insert_after)
|
||||
{
|
||||
if(!insert_after->next)
|
||||
break;
|
||||
if(insert_after->next->info.expires < stamp)
|
||||
break;
|
||||
if(s->banpool_firstused)
|
||||
{
|
||||
NETBAN *insert_after = s->banpool_firstused;
|
||||
MACRO_LIST_FIND(insert_after, next, stamp < insert_after->info.expires);
|
||||
|
||||
if(insert_after)
|
||||
insert_after = insert_after->prev;
|
||||
else
|
||||
{
|
||||
/* add to last */
|
||||
insert_after = s->banpool_firstused;
|
||||
while(insert_after->next)
|
||||
insert_after = insert_after->next;
|
||||
}
|
||||
|
||||
if(!insert_after || insert_after->info.expires > stamp)
|
||||
if(insert_after)
|
||||
{
|
||||
/* insert first */
|
||||
s->banpool_firstused = ban;
|
||||
ban->next = insert_after;
|
||||
ban->prev = 0;
|
||||
MACRO_LIST_LINK_AFTER(ban, insert_after, prev, next);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* insert after */
|
||||
ban->next = insert_after->next;
|
||||
ban->prev = insert_after;
|
||||
if(ban->next)
|
||||
ban->next->prev = ban;
|
||||
insert_after->next = ban;
|
||||
MACRO_LIST_LINK_FIRST(ban, s->banpool_firstused, prev, next);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MACRO_LIST_LINK_FIRST(ban, s->banpool_firstused, prev, next);
|
||||
}
|
||||
}
|
||||
|
||||
/* drop banned clients */
|
||||
|
@ -210,9 +255,9 @@ int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
|
|||
NETADDR banaddr;
|
||||
|
||||
if(seconds)
|
||||
str_format(buf, sizeof(buf), "you have been banned for %d seconds", seconds);
|
||||
str_format(buf, sizeof(buf), "you have been banned for %d minutes", seconds/60);
|
||||
else
|
||||
str_format(buf, sizeof(buf), "you have been banned");
|
||||
str_format(buf, sizeof(buf), "you have been banned for life");
|
||||
|
||||
for(i = 0; i < s->max_clients; i++)
|
||||
{
|
||||
|
@ -223,12 +268,13 @@ int netserver_ban_add(NETSERVER *s, NETADDR addr, int type, int seconds)
|
|||
netserver_drop(s, i, buf);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netserver_update(NETSERVER *s)
|
||||
{
|
||||
unsigned now = time_timestamp();
|
||||
|
||||
int i;
|
||||
for(i = 0; i < s->max_clients; i++)
|
||||
{
|
||||
|
@ -236,6 +282,16 @@ int netserver_update(NETSERVER *s)
|
|||
if(s->slots[i].conn.state == NET_CONNSTATE_ERROR)
|
||||
netserver_drop(s, i, conn_error(&s->slots[i].conn));
|
||||
}
|
||||
|
||||
/* remove expired bans */
|
||||
while(s->banpool_firstused && s->banpool_firstused->info.expires < now)
|
||||
{
|
||||
NETBAN *ban = s->banpool_firstused;
|
||||
netserver_ban_remove_by_object(s, ban);
|
||||
}
|
||||
|
||||
(void)now;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -278,8 +334,23 @@ int netserver_recv(NETSERVER *s, NETCHUNK *chunk)
|
|||
}
|
||||
|
||||
/* check if we just should drop the packet */
|
||||
if(ban && ban->info.type == NETBANTYPE_DROP && (!ban->info.expires || ban->info.expires > now))
|
||||
if(ban)
|
||||
{
|
||||
// banned, reply with a message
|
||||
char banstr[128];
|
||||
if(ban->info.expires)
|
||||
{
|
||||
int mins = ((ban->info.expires - now)+59)/60;
|
||||
if(mins == 1)
|
||||
str_format(banstr, sizeof(banstr), "banned for %d minute", mins);
|
||||
else
|
||||
str_format(banstr, sizeof(banstr), "banned for %d minutes", mins);
|
||||
}
|
||||
else
|
||||
str_format(banstr, sizeof(banstr), "banned for life");
|
||||
send_controlmsg(s->socket, &addr, 0, NET_CTRLMSG_CLOSE, banstr, str_length(banstr)+1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(s->recv.data.flags&NET_PACKETFLAG_CONNLESS)
|
||||
{
|
||||
|
@ -297,12 +368,6 @@ int netserver_recv(NETSERVER *s, NETCHUNK *chunk)
|
|||
{
|
||||
found = 0;
|
||||
|
||||
if(ban && ban->info.expires > now)
|
||||
{
|
||||
/* TODO: soft ban, reply with a message */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check if we already got this client */
|
||||
for(i = 0; i < s->max_clients; i++)
|
||||
{
|
||||
|
@ -331,8 +396,8 @@ int netserver_recv(NETSERVER *s, NETCHUNK *chunk)
|
|||
|
||||
if(!found)
|
||||
{
|
||||
/* TODO: send server full message */
|
||||
}
|
||||
const char fullmsg[] = "server is full";
|
||||
send_controlmsg(s->socket, &addr, 0, NET_CTRLMSG_CLOSE, fullmsg, sizeof(fullmsg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -824,9 +824,9 @@ static void server_process_client_packet(NETCHUNK *packet)
|
|||
}
|
||||
|
||||
|
||||
int server_ban_add(NETADDR addr, int type, int seconds)
|
||||
int server_ban_add(NETADDR addr, int seconds)
|
||||
{
|
||||
return netserver_ban_add(net, addr, type, seconds);
|
||||
return netserver_ban_add(net, addr, seconds);
|
||||
}
|
||||
|
||||
int server_ban_remove(NETADDR addr)
|
||||
|
@ -1177,29 +1177,78 @@ static void con_kick(void *result, void *user_data)
|
|||
server_kick(console_arg_int(result, 0), "kicked by console");
|
||||
}
|
||||
|
||||
static int str_allnum(const char *str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
if(!(*str >= '0' && *str <= '9'))
|
||||
return 0;
|
||||
str++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void con_ban(void *result, void *user_data)
|
||||
{
|
||||
NETADDR addr;
|
||||
char addrstr[128];
|
||||
const char *str = console_arg_string(result, 0);
|
||||
int minutes = console_arg_int(result, 1);
|
||||
|
||||
if(minutes == 0)
|
||||
minutes = 30;
|
||||
|
||||
if(net_addr_from_str(&addr, str) == 0)
|
||||
server_ban_add(addr, minutes*60);
|
||||
else if(str_allnum(str))
|
||||
{
|
||||
NETADDR addr;
|
||||
int cid = atoi(str);
|
||||
|
||||
if(cid < 0 || cid > MAX_CLIENTS || clients[cid].state == SRVCLIENT_STATE_EMPTY)
|
||||
{
|
||||
dbg_msg("server", "invalid client id");
|
||||
return;
|
||||
}
|
||||
|
||||
netserver_client_addr(net, cid, &addr);
|
||||
server_ban_add(addr, minutes*60);
|
||||
}
|
||||
|
||||
addr.port = 0;
|
||||
net_addr_str(&addr, addrstr, sizeof(addrstr));
|
||||
|
||||
dbg_msg("server", "banned %s for %d minutes", addrstr, minutes);
|
||||
}
|
||||
|
||||
static void con_unban(void *result, void *user_data)
|
||||
{
|
||||
NETADDR addr;
|
||||
const char *str = console_arg_string(result, 0);
|
||||
|
||||
if(net_addr_from_str(&addr, str) == 0)
|
||||
server_ban_add(addr, 2, 60);
|
||||
server_ban_remove(addr);
|
||||
else
|
||||
dbg_msg("server", "invalid network address");
|
||||
}
|
||||
|
||||
|
||||
static void con_bans(void *result, void *user_data)
|
||||
{
|
||||
int i;
|
||||
unsigned now = time_timestamp();
|
||||
NETBANINFO info;
|
||||
NETADDR addr;
|
||||
int num = netserver_ban_num(net);
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
unsigned t;
|
||||
netserver_ban_get(net, i, &info);
|
||||
addr = info.addr;
|
||||
|
||||
dbg_msg("server", "#%d %d.%d.%d.%d", i, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]);
|
||||
t = info.expires - now;
|
||||
dbg_msg("server", "#%d %d.%d.%d.%d for %d minutes and %d seconds", i, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3], t/60, t%60);
|
||||
}
|
||||
dbg_msg("server", "%d ban(s)", num);
|
||||
}
|
||||
|
||||
static void con_status(void *result, void *user_data)
|
||||
|
@ -1238,7 +1287,8 @@ static void con_stoprecord(void *result, void *user_data)
|
|||
static void server_register_commands()
|
||||
{
|
||||
MACRO_REGISTER_COMMAND("kick", "i", con_kick, 0);
|
||||
MACRO_REGISTER_COMMAND("ban", "r", con_ban, 0);
|
||||
MACRO_REGISTER_COMMAND("ban", "s?i", con_ban, 0);
|
||||
MACRO_REGISTER_COMMAND("unban", "s", con_unban, 0);
|
||||
MACRO_REGISTER_COMMAND("bans", "", con_bans, 0);
|
||||
MACRO_REGISTER_COMMAND("status", "", con_status, 0);
|
||||
MACRO_REGISTER_COMMAND("shutdown", "", con_shutdown, 0);
|
||||
|
|
Loading…
Reference in a new issue