diff --git a/include/client.h b/include/client.h index 4f07cb17..a36da325 100644 --- a/include/client.h +++ b/include/client.h @@ -166,6 +166,7 @@ enum Flag FLAG_DEBUG, /**< send global debug/anti-hack info */ FLAG_ACCOUNT, /**< account name has been set */ FLAG_HIDDENHOST, /**< user's host is hidden */ + FLAG_EXEMPTFLOOD, /**< Client is exempt from flood limits */ FLAG_LAST_FLAG, /**< number of flags */ FLAG_LOCAL_UMODES = FLAG_LOCOP, /**< First local mode flag */ FLAG_GLOBAL_UMODES = FLAG_OPER /**< First global mode flag */ @@ -599,6 +600,8 @@ struct Client { #define IsHiddenHost(x) HasFlag(x, FLAG_HIDDENHOST) /** Return non-zero if the client has an active PING request. */ #define IsPingSent(x) HasFlag(x, FLAG_PINGSENT) +/** Return non-zero if the client is exempt from flood limits. */ +#define IsExemptFlood(x) HasFlag(x, FLAG_EXEMPTFLOOD) /** Return non-zero if the client has operator or server privileges. */ #define IsPrivileged(x) (IsAnOper(x) || IsServer(x)) @@ -645,6 +648,8 @@ struct Client { #define SetHiddenHost(x) SetFlag(x, FLAG_HIDDENHOST) /** Mark a client as having a pending PING. */ #define SetPingSent(x) SetFlag(x, FLAG_PINGSENT) +/** Mark a client as being exempt from flood limits. */ +#define SetExemptFlood(x) SetFlag(x, FLAG_EXEMPTFLOOD) /** Return non-zero if \a sptr sees \a acptr as an operator. */ #define SeeOper(sptr,acptr) (IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) \ diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c index 9bfb8760..697948eb 100644 --- a/ircd/s_bsd.c +++ b/ircd/s_bsd.c @@ -631,8 +631,15 @@ static int read_packet(struct Client *cptr, int socket_ready) if (DBufLength(&(cli_recvQ(cptr))) > GetMaxFlood(cptr)) return exit_client(cptr, cptr, &me, "Excess Flood"); + /* If client has a higher sendq limit than default, + * mark them flood exempt to avoid throttling + */ + if (GetMaxFlood(cptr) > feature_int(FEAT_CLIENT_FLOOD)) { + SetExemptFlood(cptr); + } + while (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) && - (IsTrusted(cptr) || cli_since(cptr) - CurrentTime < 10)) + (IsTrusted(cptr) || IsExemptFlood(cptr) || cli_since(cptr) - CurrentTime < 10)) { dolen = dbuf_getmsg(&(cli_recvQ(cptr)), cli_buffer(cptr), BUFSIZE); /* @@ -677,14 +684,16 @@ static int read_packet(struct Client *cptr, int socket_ready) } } - /* If there's still data to process, wait 2 seconds first */ + /* If there's still data to process, wait 2 seconds first, + * unless the user is exempt from throttling + */ if (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) && - !t_onqueue(&(cli_proc(cptr)))) + !IsExemptFlood(cptr) && !t_onqueue(&(cli_proc(cptr)))) { Debug((DEBUG_LIST, "Adding client process timer for %C", cptr)); cli_freeflag(cptr) |= FREEFLAG_TIMER; timer_add(&(cli_proc(cptr)), client_timer_callback, cli_connect(cptr), - TT_RELATIVE, 2); + TT_RELATIVE, 2); } } return 1;