]> jfr.im git - solanum.git/blame - src/ratelimit.c
Add new conf_read_start and conf_read_end hooks.
[solanum.git] / src / ratelimit.c
CommitLineData
e88a1f1b
KB
1/*
2 * charybdis: an advanced ircd
3 * ratelimit.c: Per-client ratelimiting for high-bandwidth commands.
4 *
5 * Copyright (c) 2012 Keith Buck <mr_flea -at- esper.net>
6 *
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.
10 *
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.
22 */
23
24#include "stdinc.h"
25#include "s_conf.h"
26#include "s_stats.h"
27#include "ratelimit.h"
28
29/*
30 * ratelimit_client(struct Client *client_p, int penalty)
31 *
32 * Applies a penalty to a client for executing a rate-limited command.
33 *
34 * Inputs:
35 * - the client to be rate-limited
36 * - the penalty to apply
37 *
38 * Outputs:
39 * - 1 if the user has been penalized and the command should be
40 * allowed to execute
41 * - 0 if the command should not execute and the user has not
42 * been penalized (they are executing commands too fast and have
43 * been rate-limited)
44 * The caller should return RPL_LOAD2HI
45 *
46 * Side effects:
47 * - The ratelimit for the user will be initialized if it hasn't
48 * been initialized yet.
49 */
50int ratelimit_client(struct Client *client_p, unsigned int penalty)
51{
52 s_assert(client_p);
53 s_assert(MyClient(client_p));
54
55 if (!client_p->localClient->ratelimit)
56 {
57 /* Not initialized yet - do it now. */
58 client_p->localClient->ratelimit = rb_current_time() - ConfigFileEntry.max_ratelimit_tokens;
59 }
60
61 /* Don't make it impossible to execute anything. */
62 if (penalty > ConfigFileEntry.max_ratelimit_tokens)
63 penalty = ConfigFileEntry.max_ratelimit_tokens;
64
65 if (client_p->localClient->ratelimit <= rb_current_time() - ConfigFileEntry.max_ratelimit_tokens)
66 {
67 client_p->localClient->ratelimit = rb_current_time() - ConfigFileEntry.max_ratelimit_tokens + penalty;
68 return 1;
69 }
70
71 if (client_p->localClient->ratelimit + penalty > rb_current_time())
72 {
73 ServerStats.is_rl++;
74 return 0;
75 }
76
77 client_p->localClient->ratelimit += penalty;
78
79 return 1;
80}
81
82/*
83 * ratelimit_client_who(struct Client *client_p, int penalty)
84 *
85 * Rate-limits a client for a WHO query if they have no remaining "free"
86 * WHO queries to execute.
87 *
88 * Inputs:
89 * - same as ratelimit_client
90 *
91 * Outputs:
92 * - same as ratelimit_client
93 *
94 * Side effects:
95 * - A "free who" token will be removed from the user if one exists.
96 * If one doesn't exist, the user will be ratelimited as normal.
97 */
98int ratelimit_client_who(struct Client *client_p, unsigned int penalty)
99{
100 s_assert(client_p);
101 s_assert(MyClient(client_p));
102
103 if (client_p->localClient->join_who_credits)
104 {
105 --client_p->localClient->join_who_credits;
106 return 1;
107 }
108
109 return ratelimit_client(client_p, penalty);
110}
111
112/*
113 * credit_client_join(struct Client *client_p)
114 *
115 * Gives a user a credit to execute a WHO for joining a channel.
116 *
117 * Inputs:
118 * - the client to be credited
119 *
120 * Outputs:
121 * - (none)
122 *
123 * Side effects:
124 * - (none)
125 */
126void credit_client_join(struct Client *client_p)
127{
128 s_assert(client_p);
129 s_assert(MyClient(client_p));
130
131 ++client_p->localClient->join_who_credits;
132}