]>
jfr.im git - solanum.git/blob - ircd/ratelimit.c
2 * charybdis: an advanced ircd
3 * ratelimit.c: Per-client ratelimiting for high-bandwidth commands.
5 * Copyright (c) 2012 Keith Buck <mr_flea -at- esper.net>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice is present in all copies.
11 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
12 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
15 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
19 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
20 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21 * POSSIBILITY OF SUCH DAMAGE.
27 #include "ratelimit.h"
31 * ratelimit_client(struct Client *client_p, int penalty)
33 * Applies a penalty to a client for executing a rate-limited command.
36 * - the client to be rate-limited
37 * - the penalty to apply
40 * - 1 if the user has been penalized and the command should be
42 * - 0 if the command should not execute and the user has not
43 * been penalized (they are executing commands too fast and have
45 * The caller should return RPL_LOAD2HI
48 * - The ratelimit for the user will be initialized if it hasn't
49 * been initialized yet.
51 int ratelimit_client(struct Client
*client_p
, unsigned int penalty
)
54 s_assert(MyClient(client_p
));
56 if (!client_p
->localClient
->ratelimit
)
58 /* Not initialized yet - do it now. */
59 client_p
->localClient
->ratelimit
= rb_current_time() - ConfigFileEntry
.max_ratelimit_tokens
;
62 /* Don't make it impossible to execute anything. */
63 if (penalty
> (unsigned int)ConfigFileEntry
.max_ratelimit_tokens
)
64 penalty
= ConfigFileEntry
.max_ratelimit_tokens
;
66 if (client_p
->localClient
->ratelimit
<= rb_current_time() - ConfigFileEntry
.max_ratelimit_tokens
)
68 client_p
->localClient
->ratelimit
= rb_current_time() - ConfigFileEntry
.max_ratelimit_tokens
+ penalty
;
72 if (client_p
->localClient
->ratelimit
+ penalty
> rb_current_time())
78 client_p
->localClient
->ratelimit
+= penalty
;
84 * ratelimit_client_who(struct Client *client_p, int penalty)
86 * Rate-limits a client for a WHO query if they have no remaining "free"
87 * WHO queries to execute.
90 * - same as ratelimit_client
93 * - same as ratelimit_client
96 * - A "free who" token will be removed from the user if one exists.
97 * If one doesn't exist, the user will be ratelimited as normal.
99 int ratelimit_client_who(struct Client
*client_p
, unsigned int penalty
)
102 s_assert(MyClient(client_p
));
104 if (client_p
->localClient
->join_who_credits
)
106 --client_p
->localClient
->join_who_credits
;
110 return ratelimit_client(client_p
, penalty
);
114 * credit_client_join(struct Client *client_p)
116 * Gives a user a credit to execute a WHO for joining a channel.
119 * - the client to be credited
127 void credit_client_join(struct Client
*client_p
)
130 s_assert(MyClient(client_p
));
132 ++client_p
->localClient
->join_who_credits
;