00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031
00032 #include "../../mem/shm_mem.h"
00033 #include "../../sr_module.h"
00034 #include "../../dprint.h"
00035 #include "../../timer.h"
00036 #include "../../ut.h"
00037
00038 MODULE_VERSION
00039
00040
00041 #define RL_WITH_RED 1
00042
00043 #define RL_TIMER_INTERVAL 10
00044
00045 #ifndef rpc_lf
00046 #define rpc_lf(rpc, c) rpc->add(c, "s","")
00047 #endif
00048
00049
00050 int *invite_limit, *register_limit, *subscribe_limit = NULL;
00051
00052
00053 int invite_limit_mp = 0;
00054 int register_limit_mp = 0;
00055 int subscribe_limit_mp = 0;
00056 int timer_interval = RL_TIMER_INTERVAL;
00057
00058
00059 int *invite_counter = NULL;
00060 int *register_counter = NULL;
00061 int *subscribe_counter = NULL;
00062
00063 #if defined(RL_WITH_RED)
00064
00065 int *invite_load = NULL;
00066 int *register_load = NULL;
00067 int *subscribe_load = NULL;
00068 #endif
00069
00071 static int mod_init(void);
00072 static int child_init(int);
00073 static int rl_check(struct sip_msg*, char *, char *);
00074 #if defined (RL_WITH_RED)
00075 static int rl_limit_check(int, int, int);
00076 #else
00077 static int rl_limit_check(int, int);
00078 #endif
00079 static void timer(unsigned int, void *);
00080 static void destroy(void);
00081
00082 static rpc_export_t rpc_methods[];
00083
00084 static cmd_export_t cmds[]={
00085 {"rl_check", rl_check, 0, 0, REQUEST_ROUTE},
00086 {0,0,0,0,0}
00087 };
00088
00089 static param_export_t params[]={
00090 {"invite_limit", PARAM_INT, &invite_limit_mp},
00091 {"register_limit", PARAM_INT, ®ister_limit_mp},
00092 {"subscribe_limit", PARAM_INT, &subscribe_limit_mp},
00093 {"timer_interval", PARAM_INT, &timer_interval},
00094 {0,0,0}
00095 };
00096
00098 struct module_exports exports= {
00099 "ratelimit",
00100 cmds,
00101 rpc_methods,
00102 params,
00103 mod_init,
00104 (response_function) 0,
00105 (destroy_function) destroy,
00106 0,
00107 child_init
00108 };
00109
00110
00111 static int mod_init(void)
00112 {
00113 DBG("RATELIMIT: initializing ...\n");
00114
00115
00116 if (register_timer(timer, 0, timer_interval) < 0) {
00117 LOG(L_ERR, "RATELIMIT:ERROR: could not register timer function\n");
00118 return -1;
00119 }
00120
00121 invite_counter = shm_malloc(sizeof(int));
00122 register_counter = shm_malloc(sizeof(int));
00123 subscribe_counter = shm_malloc(sizeof(int));
00124 if (!invite_counter || !register_counter || !subscribe_counter) {
00125 LOG(L_ERR, "RATELIMIT:ERROR: no memory for counters\n");
00126 return -1;
00127 }
00128 *invite_counter = 0;
00129 *register_counter = 0;
00130 *subscribe_counter = 0;
00131
00132 invite_limit = shm_malloc(sizeof(int));
00133 register_limit = shm_malloc(sizeof(int));
00134 subscribe_limit = shm_malloc(sizeof(int));
00135 if (!invite_limit || !register_limit || !subscribe_limit) {
00136 LOG(L_ERR, "RATELIMIT:ERROR: no memory for limit settings\n");
00137 return -1;
00138 }
00139
00140 *invite_limit = invite_limit_mp;
00141 *register_limit = register_limit_mp;
00142 *subscribe_limit = subscribe_limit_mp;
00143
00144
00145 #if defined (RL_WITH_RED)
00146
00147 invite_load = shm_malloc(sizeof(int));
00148 register_load = shm_malloc(sizeof(int));
00149 subscribe_load = shm_malloc(sizeof(int));
00150 if (!invite_load || !register_load || !subscribe_load) {
00151 LOG(L_ERR, "RATELIMIT:ERROR: no memory for load levels\n");
00152 return -1;
00153 }
00154 *invite_load = -1;
00155 *register_load = -1;
00156 *subscribe_load = -1;
00157 #endif
00158
00159 return 0;
00160 }
00161
00162
00163 static int child_init(int rank)
00164 {
00165 DBG("RATELIMIT:init_child #%d / pid <%d>\n", rank, getpid());
00166 return 0;
00167 }
00168 static void destroy(void)
00169 {
00170 DBG("RATELIMIT: destroy module ...\n");
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 static int rl_check(struct sip_msg* msg, char *_foo, char *_bar) {
00182
00183 DBG("RATELIMIT:rl_check:invoked\n");
00184
00185 if (msg->first_line.type != SIP_REQUEST) {
00186 DBG("RATELIMIT:rl_check:not a request\n");
00187 return 0;
00188 }
00189
00190 if (msg->first_line.u.request.method_value == METHOD_INVITE) {
00191 if (*invite_limit == 0)
00192 return 1;
00193 *invite_counter = *invite_counter + 1;
00194 #if defined(RL_WITH_RED)
00195 return rl_limit_check(*invite_counter, *invite_limit, *invite_load);
00196 #else
00197 return rl_limit_check(*invite_counter, *invite_limit);
00198 #endif
00199 } else if (msg->first_line.u.request.method_value == METHOD_REGISTER) {
00200 if (*register_limit == 0)
00201 return 1;
00202 *register_counter = *register_counter + 1;
00203 #if defined(RL_WITH_RED)
00204 return rl_limit_check(*register_counter, *register_limit,
00205 *register_load);
00206 #else
00207 return rl_limit_check(*register_counter, *register_limit);
00208 #endif
00209 } else if (msg->first_line.u.request.method_value == METHOD_SUBSCRIBE) {
00210 if (*subscribe_limit == 0)
00211 return 1;
00212 *subscribe_counter = *subscribe_counter + 1;
00213 #if defined(RL_WITH_RED)
00214 return rl_limit_check(*subscribe_counter, *subscribe_limit,
00215 *subscribe_load);
00216 #else
00217 return rl_limit_check(*subscribe_counter, *subscribe_limit);
00218 #endif
00219 } else {
00220 return 0;
00221 }
00222 return -1;
00223 }
00224
00225
00226
00227 static void timer(unsigned int ticks, void *param) {
00228 DBG("RATELIMIT:timer:invoked\n");
00229
00230 #if defined(RL_WITH_RED)
00231
00232 if (*invite_limit > 0) {
00233 if (*invite_counter < *invite_limit)
00234 *invite_load = 0;
00235 else
00236 *invite_load = (int) (*invite_counter / *invite_limit);
00237 }
00238 if (*register_limit > 0) {
00239 if (*register_counter < *register_limit)
00240 *register_load = 0;
00241 else
00242 *register_load = (int) (*register_counter / *register_limit);
00243 }
00244 if (*subscribe_limit > 0) {
00245 if (*subscribe_counter < *subscribe_limit)
00246 *subscribe_load = 0;
00247 else
00248 *subscribe_load = (int) (*subscribe_counter / *subscribe_limit);
00249 }
00250 #endif
00251
00252
00253 if (*invite_limit > 0) *invite_counter = 0;
00254 if (*register_limit > 0) *register_counter = 0;
00255 if (*subscribe_limit > 0) *subscribe_counter = 0;
00256 }
00257
00258 #if defined(RL_WITH_RED)
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 static int rl_limit_check(int cnt, int limit, int load) {
00275
00276 DBG("RATELIMIT:rl_limit_check: invoked\n");
00277
00278
00279 if (load == -1) return (cnt > limit) ? -1 : 1;
00280
00281
00282 if (load <= 1) return 1;
00283
00284
00285 return (!(cnt % load)) ? 1 : -1;
00286 }
00287
00288 #else
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 static int rl_limit_check(int cnt, int limit) {
00306 DBG("RATELIMIT:rl_limit_check: invoked\n");
00307 return (cnt > limit) ? -1 : 1;
00308 }
00309
00310 #endif
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 static const char *rpc_stats_doc[2] = {
00323 "Print ratelimit statistics",
00324 0
00325 };
00326
00327 static const char *rpc_invite_doc[2] = {
00328 "Set INVITEs per timer interval limit",
00329 0
00330 };
00331 static const char *rpc_register_doc[2] = {
00332 "Set REGISTERs per timer interval limit",
00333 0
00334 };
00335 static const char *rpc_subscribe_doc[2] = {
00336 "Set SUBSCRIBEs per timer interval limit",
00337 0
00338 };
00339 static const char *rpc_timer_doc[2] = {
00340 "Set the ratelimit timer_interval length",
00341 0
00342 };
00343
00344
00345 static void rpc_stats(rpc_t *rpc, void *c) {
00346
00347 #if defined(RL_WITH_RED)
00348 if (rpc->printf(c, " INVITE: %d/%d (drop rate: %d)", *invite_counter,
00349 *invite_limit, *invite_load) < 0) return;
00350 rpc_lf(rpc, c);
00351 if (rpc->printf(c, " REGISTER: %d/%d (drop rate: %d)", *register_counter,
00352 *register_limit, *register_load) < 0) return;
00353 rpc_lf(rpc, c);
00354 if (rpc->printf(c, "SUBSCRIBE: %d/%d (drop rate: %d)", *subscribe_counter,
00355 *subscribe_limit, *subscribe_load) < 0) return;
00356 rpc_lf(rpc, c);
00357 #else
00358 if (rpc->printf(c, " INVITE: %d/%d", *invite_counter,
00359 *invite_limit) < 0) return;
00360 rpc_lf(rpc, c);
00361 if (rpc->printf(c, " REGISTER: %d/%d", *register_counter,
00362 *register_limit) < 0) return;
00363 rpc_lf(rpc, c);
00364 if (rpc->printf(c, "SUBSCRIBE: %d/%d", *subscribe_counter,
00365 *subscribe_limit) < 0) return;
00366 rpc_lf(rpc, c);
00367 #endif
00368
00369 }
00370 static void rpc_invite(rpc_t *rpc, void *c) {
00371
00372 int limit;
00373 if (rpc->scan(c, "d", &limit) < 1) {
00374 rpc->fault(c, 400, "Limit expected");
00375 return;
00376 }
00377 if (limit < 0) {
00378 rpc->fault(c, 400, "limit must be >= 0 (0 = unlimited)");
00379 return;
00380 }
00381 DBG("RATELIMIT:setting INVITE limit to %d messages\n", limit);
00382 *invite_limit = limit;
00383 }
00384 static void rpc_register(rpc_t *rpc, void *c) {
00385
00386 int limit;
00387 if (rpc->scan(c, "d", &limit) < 1) {
00388 rpc->fault(c, 400, "Limit expected");
00389 return;
00390 }
00391 if (limit < 0) {
00392 rpc->fault(c, 400, "limit must be >= 0 (0 = unlimited)");
00393 return;
00394 }
00395 DBG("RATELIMIT:setting REGISTER limit to %d messages\n", limit);
00396 *register_limit = limit;
00397 }
00398 static void rpc_subscribe(rpc_t *rpc, void *c) {
00399
00400 int limit;
00401 if (rpc->scan(c, "d", &limit) < 1) {
00402 rpc->fault(c, 400, "Limit expected");
00403 return;
00404 }
00405 if (limit < 0) {
00406 rpc->fault(c, 400, "limit must be >= 0 (0 = unlimited)");
00407 return;
00408 }
00409 DBG("RATELIMIT:setting SUBSCRIBE limit to %d messages\n", limit);
00410 *subscribe_limit = limit;
00411 }
00412 static void rpc_timer(rpc_t *rpc, void *c) {
00413 rpc->fault(c, 400, "Not yet implemented");
00414 }
00415
00416 static rpc_export_t rpc_methods[] = {
00417 {"rl.stats", rpc_stats, rpc_stats_doc, 0},
00418 {"rl.invite_limit", rpc_invite, rpc_invite_doc, 0},
00419 {"rl.register_limit", rpc_register, rpc_register_doc, 0},
00420 {"rl.subscribe_limit", rpc_subscribe, rpc_subscribe_doc, 0},
00421 {"rl.timer_interval", rpc_timer, rpc_timer_doc, 0},
00422 {0, 0, 0, 0}
00423 };