mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-07-05 14:33:12 +02:00
Add set::max-stats-matches which limits output such as '/STATS gline'
to the specified number of lines. This defaults to 1000.
This will prevent IRCOps from being flooded off ("Max SendQ exceeded")
if they list all *LINES and there are thousands.
In the newly introduced error message, after too many matches,
we also kindly point out to use filters like '/STATS gline +m *.nl'
This commit is contained in:
+1
-1
@@ -697,7 +697,7 @@ extern MODVAR int (*find_shun)(Client *cptr);
|
||||
extern MODVAR int (*find_spamfilter_user)(Client *client, int flags);
|
||||
extern MODVAR TKL *(*find_qline)(Client *cptr, char *nick, int *ishold);
|
||||
extern MODVAR TKL *(*find_tkline_match_zap)(Client *cptr);
|
||||
extern MODVAR void (*tkl_stats)(Client *cptr, int type, char *para);
|
||||
extern MODVAR void (*tkl_stats)(Client *cptr, int type, char *para, int *cnt);
|
||||
extern MODVAR void (*tkl_sync)(Client *client);
|
||||
extern MODVAR void (*cmd_tkl)(Client *client, MessageTag *recv_mtags, int parc, char *parv[]);
|
||||
extern MODVAR int (*place_host_ban)(Client *client, BanAction action, char *reason, long duration);
|
||||
|
||||
@@ -63,7 +63,7 @@ int (*find_shun)(Client *client);
|
||||
int(*find_spamfilter_user)(Client *client, int flags);
|
||||
TKL *(*find_qline)(Client *client, char *nick, int *ishold);
|
||||
TKL *(*find_tkline_match_zap)(Client *client);
|
||||
void (*tkl_stats)(Client *client, int type, char *para);
|
||||
void (*tkl_stats)(Client *client, int type, char *para, int *cnt);
|
||||
void (*tkl_sync)(Client *client);
|
||||
void (*cmd_tkl)(Client *client, MessageTag *mtags, int parc, char *parv[]);
|
||||
int (*place_host_ban)(Client *client, BanAction action, char *reason, long duration);
|
||||
|
||||
+19
-12
@@ -462,22 +462,25 @@ int stats_denylinkall(Client *client, char *para)
|
||||
|
||||
int stats_gline(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_KILL, para);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_ZAP, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_KILL, para, &cnt);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_ZAP, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stats_spamfilter(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_SPAMF, para);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SPAMF, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_SPAMF, para, &cnt);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SPAMF, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stats_except(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_EXCEPTION, para);
|
||||
tkl_stats(client, TKL_EXCEPTION|TKL_GLOBAL, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_EXCEPTION, para, &cnt);
|
||||
tkl_stats(client, TKL_EXCEPTION|TKL_GLOBAL, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -564,8 +567,9 @@ int stats_port(Client *client, char *para)
|
||||
|
||||
int stats_bannick(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_NAME, para);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_NAME, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_NAME, para, &cnt);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_NAME, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -699,8 +703,9 @@ int stats_denylinkauto(Client *client, char *para)
|
||||
|
||||
int stats_kline(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_KILL, NULL);
|
||||
tkl_stats(client, TKL_ZAP, NULL);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_KILL, NULL, &cnt);
|
||||
tkl_stats(client, TKL_ZAP, NULL, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -720,7 +725,8 @@ int stats_banrealname(Client *client, char *para)
|
||||
|
||||
int stats_sqline(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_NAME|TKL_GLOBAL, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_NAME|TKL_GLOBAL, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -741,7 +747,8 @@ int stats_chanrestrict(Client *client, char *para)
|
||||
|
||||
int stats_shun(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SHUN, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SHUN, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+89
-19
@@ -39,6 +39,8 @@ int tkl_config_test_ban(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_ban(ConfigFile *, ConfigEntry *, int);
|
||||
int tkl_config_test_except(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_except(ConfigFile *, ConfigEntry *, int);
|
||||
int tkl_config_test_set(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_set(ConfigFile *, ConfigEntry *, int);
|
||||
CMD_FUNC(cmd_gline);
|
||||
CMD_FUNC(cmd_shun);
|
||||
CMD_FUNC(cmd_tempshun);
|
||||
@@ -76,7 +78,7 @@ int _find_shun(Client *client);
|
||||
int _find_spamfilter_user(Client *client, int flags);
|
||||
TKL *_find_qline(Client *client, char *nick, int *ishold);
|
||||
TKL *_find_tkline_match_zap(Client *client);
|
||||
void _tkl_stats(Client *client, int type, char *para);
|
||||
void _tkl_stats(Client *client, int type, char *para, int *cnt);
|
||||
void _tkl_sync(Client *client);
|
||||
CMD_FUNC(_cmd_tkl);
|
||||
int _place_host_ban(Client *client, BanAction action, char *reason, long duration);
|
||||
@@ -142,12 +144,15 @@ TKLTypeTable tkl_types[] = {
|
||||
};
|
||||
#define ALL_VALID_EXCEPTION_TYPES "kline, gline, zline, gzline, spamfilter, shun, qline, blacklist, connect-flood, unknown-data-flood, antirandom, antimixedutf8, ban-version"
|
||||
|
||||
int max_stats_matches = 1000;
|
||||
|
||||
MOD_TEST()
|
||||
{
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_spamfilter);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_ban);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_except);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_set);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_TKL_HASH, _tkl_hash);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_TKL_TYPETOCHAR, TO_INTFUNC(_tkl_typetochar));
|
||||
EfunctionAdd(modinfo->handle, EFUNC_TKL_CHARTOTYPE, TO_INTFUNC(_tkl_chartotype));
|
||||
@@ -190,6 +195,7 @@ MOD_INIT()
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_match_spamfilter);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_ban);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_except);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_set);
|
||||
CommandAdd(modinfo->handle, "GLINE", cmd_gline, 3, CMD_OPER);
|
||||
CommandAdd(modinfo->handle, "SHUN", cmd_shun, 3, CMD_OPER);
|
||||
CommandAdd(modinfo->handle, "TEMPSHUN", cmd_tempshun, 2, CMD_OPER);
|
||||
@@ -902,6 +908,44 @@ int tkl_config_run_except(ConfigFile *cf, ConfigEntry *ce, int configtype)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tkl_config_test_set(ConfigFile *cf, ConfigEntry *ce, int configtype, int *errs)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
/* We are only interested in set { } blocks */
|
||||
if (configtype != CONFIG_SET)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(ce->ce_varname, "max-stats-matches"))
|
||||
{
|
||||
if (!ce->ce_vardata)
|
||||
{
|
||||
config_error("%s:%i: set::max-stats-matches: no value specified",
|
||||
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
|
||||
errors++;
|
||||
}
|
||||
// allow any other value, including 0 and negative.
|
||||
*errs = errors;
|
||||
return errors ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tkl_config_run_set(ConfigFile *cf, ConfigEntry *ce, int configtype)
|
||||
{
|
||||
/* We are only interested in set { } blocks */
|
||||
if (configtype != CONFIG_SET)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(ce->ce_varname, "max-stats-matches"))
|
||||
{
|
||||
max_stats_matches = atoi(ce->ce_vardata);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return unique spamfilter id for TKL */
|
||||
char *spamfilter_id(TKL *tk)
|
||||
{
|
||||
@@ -3298,7 +3342,7 @@ static void parse_stats_params(char *para, TKLFlag *flag)
|
||||
/** Does this TKL entry match the search terms?
|
||||
* This is a helper function for tkl_stats().
|
||||
*/
|
||||
void tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags, TKL *tkl)
|
||||
int tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags, TKL *tkl)
|
||||
{
|
||||
/***** First, handle the selection ******/
|
||||
|
||||
@@ -3306,66 +3350,66 @@ void tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags,
|
||||
{
|
||||
if (tklflags->flags & BY_SETBY)
|
||||
if (!match_simple(tklflags->set_by, tkl->set_by))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_SETBY)
|
||||
if (match_simple(tklflags->set_by, tkl->set_by))
|
||||
return;
|
||||
return 0;
|
||||
if (TKLIsServerBan(tkl))
|
||||
{
|
||||
if (tklflags->flags & BY_MASK)
|
||||
{
|
||||
if (!match_simple(tklflags->mask, make_user_host(tkl->ptr.serverban->usermask, tkl->ptr.serverban->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & NOT_BY_MASK)
|
||||
{
|
||||
if (match_simple(tklflags->mask, make_user_host(tkl->ptr.serverban->usermask, tkl->ptr.serverban->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & BY_REASON)
|
||||
if (!match_simple(tklflags->reason, tkl->ptr.serverban->reason))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_REASON)
|
||||
if (match_simple(tklflags->reason, tkl->ptr.serverban->reason))
|
||||
return;
|
||||
return 0;
|
||||
} else
|
||||
if (TKLIsNameBan(tkl))
|
||||
{
|
||||
if (tklflags->flags & BY_MASK)
|
||||
{
|
||||
if (!match_simple(tklflags->mask, tkl->ptr.nameban->name))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & NOT_BY_MASK)
|
||||
{
|
||||
if (match_simple(tklflags->mask, tkl->ptr.nameban->name))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & BY_REASON)
|
||||
if (!match_simple(tklflags->reason, tkl->ptr.nameban->reason))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_REASON)
|
||||
if (match_simple(tklflags->reason, tkl->ptr.nameban->reason))
|
||||
return;
|
||||
return 0;
|
||||
} else
|
||||
if (TKLIsBanException(tkl))
|
||||
{
|
||||
if (tklflags->flags & BY_MASK)
|
||||
{
|
||||
if (!match_simple(tklflags->mask, make_user_host(tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & NOT_BY_MASK)
|
||||
{
|
||||
if (match_simple(tklflags->mask, make_user_host(tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & BY_REASON)
|
||||
if (!match_simple(tklflags->reason, tkl->ptr.banexception->reason))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_REASON)
|
||||
if (match_simple(tklflags->reason, tkl->ptr.banexception->reason))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3444,16 +3488,24 @@ void tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags,
|
||||
tkl->ptr.banexception->bantypes,
|
||||
(tkl->expire_at != 0) ? (tkl->expire_at - TStime()) : 0,
|
||||
(TStime() - tkl->set_at), tkl->set_by, tkl->ptr.banexception->reason);
|
||||
} else
|
||||
{
|
||||
/* That's weird, unknown TKL type */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* TKL Stats. This is used by /STATS gline and all the others */
|
||||
void _tkl_stats(Client *client, int type, char *para)
|
||||
void _tkl_stats(Client *client, int type, char *para, int *cnt)
|
||||
{
|
||||
TKL *tk;
|
||||
TKLFlag tklflags;
|
||||
int index, index2;
|
||||
|
||||
if ((max_stats_matches > 0) && (*cnt >= max_stats_matches))
|
||||
return;
|
||||
|
||||
if (!BadPtr(para))
|
||||
parse_stats_params(para, &tklflags);
|
||||
|
||||
@@ -3467,7 +3519,16 @@ void _tkl_stats(Client *client, int type, char *para)
|
||||
{
|
||||
if (type && tk->type != type)
|
||||
continue;
|
||||
tkl_stats_matcher(client, type, para, &tklflags, tk);
|
||||
if (tkl_stats_matcher(client, type, para, &tklflags, tk))
|
||||
{
|
||||
*cnt += 1;
|
||||
if ((max_stats_matches > 0) && (*cnt >= max_stats_matches))
|
||||
{
|
||||
sendnumeric(client, ERR_TOOMANYMATCHES, "STATS", "too many matches (set::max-stats-matches)");
|
||||
sendnotice(client, "Consider searching on something more specific, eg '/STATS gline +m *.nl'. See '/STATS' (without parameters) for help.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3479,7 +3540,16 @@ void _tkl_stats(Client *client, int type, char *para)
|
||||
{
|
||||
if (type && tk->type != type)
|
||||
continue;
|
||||
tkl_stats_matcher(client, type, para, &tklflags, tk);
|
||||
if (tkl_stats_matcher(client, type, para, &tklflags, tk))
|
||||
{
|
||||
*cnt += 1;
|
||||
if ((max_stats_matches > 0) && (*cnt >= max_stats_matches))
|
||||
{
|
||||
sendnumeric(client, ERR_TOOMANYMATCHES, "STATS", "too many matches (set::max-stats-matches)");
|
||||
sendnotice(client, "Consider searching on something more specific, eg '/STATS gline +m *.nl'. See '/STATS' (without parameters) for help.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user