emehta-contrib/os_defcon.c

240 lines
6.2 KiB
C

/*
* Copyright (c) 2010 JD Horelick <jdhore1@gmail.com>
* Rights to this code are as defined in doc/LICENSE.
*
* DEFCON implementation.
*
* By default, any setting except 5 will expire after 15 minutes,
* to change this, add a defcon_timeout = X; option to the operserv{}
* block in your atheme.con. X = amount of time in minutes for a defcon
* setting to time out/expire.
*
*/
#include "atheme-compat.h"
#define DEFCON_CMODE "R"
DECLARE_MODULE_V1
(
"contrib/os_defcon", false, _modinit, _moddeinit,
PACKAGE_STRING,
"Atheme Development Group <http://www.atheme.org>"
);
static void os_cmd_defcon(sourceinfo_t *si, int parc, char *parv[]);
static void defcon_nouserreg(hook_user_register_check_t *hdata);
static void defcon_nochanreg(hook_channel_register_check_t *hdatac);
static void defcon_useradd(hook_user_nick_t *data);
static void defcon_timeoutfunc(void *dummy);
static int level = 5;
static unsigned int defcon_timeout = 900;
static mowgli_eventloop_timer_t *defcon_timer = NULL;
command_t os_defcon = { "DEFCON", N_("Implements Defense Condition lockdowns."), PRIV_ADMIN, 1, os_cmd_defcon, { .path = "contrib/defcon" } };
void _modinit(module_t *m)
{
service_named_bind_command("operserv", &os_defcon);
TAINT_ON("Using os_defcon", "Use of os_defcon is unsupported and not recommend. Use only at your own risk.");
/* Hooks for all the stuff defcon disables */
hook_add_event("user_can_register");
hook_add_user_can_register(defcon_nouserreg);
hook_add_event("channel_can_register");
hook_add_channel_can_register(defcon_nochanreg);
hook_add_event("user_add");
hook_add_user_add(defcon_useradd);
service_t *svs;
svs = service_find("operserv");
add_duration_conf_item("DEFCON_TIMEOUT", &svs->conf_table, 0, &defcon_timeout, "m", 900);
}
void _moddeinit(module_unload_intent_t intent)
{
service_named_unbind_command("operserv", &os_defcon);
hook_del_user_can_register(defcon_nouserreg);
hook_del_channel_can_register(defcon_nochanreg);
hook_del_user_add(defcon_useradd);
service_t *svs;
svs = service_find("operserv");
del_conf_item("DEFCON_TIMEOUT", &svs->conf_table);
if (defcon_timer != NULL)
mowgli_timer_destroy(base_eventloop, defcon_timer);
}
static void defcon_nouserreg(hook_user_register_check_t *hdata)
{
return_if_fail(hdata != NULL);
return_if_fail(hdata->si != NULL);
if (level < 5)
{
command_fail(hdata->si, fault_badparams, _("Registrations are currently disabled on this network, please try again later."));
hdata->approved++;
}
}
static void defcon_nochanreg(hook_channel_register_check_t *hdatac)
{
return_if_fail(hdatac != NULL);
return_if_fail(hdatac->si != NULL);
if (level < 5)
{
command_fail(hdatac->si, fault_badparams, _("Registrations are currently disabled on this network, please try again later."));
hdatac->approved++;
}
}
static void defcon_useradd(hook_user_nick_t *data)
{
user_t *u = data->u;
if (!u)
return;
if (is_internal_client(u))
return;
if (level == 1)
{
slog(LG_INFO, "DEFCON:KLINE: %s!%s@%s", u->nick, u->user, u->host);
kline_sts("*", u->user, u->host, 900, "This network is currently not accepting connections, please try again later.");
}
}
static void defcon_svsignore(void)
{
svsignore_t *svsignore;
mowgli_node_t *n, *tn;
if (level <= 2)
{
MOWGLI_ITER_FOREACH(n, svs_ignore_list.head)
{
svsignore = (svsignore_t *)n->data;
if (!strcasecmp(svsignore->mask, "*@*"))
return;
}
slog(LG_INFO, "DEFCON:IGNORE:ADD");
svsignore = svsignore_add("*@*", "DEFCON Level 1 or 2 activated");
svsignore->setby = "DEFCON";
svsignore->settime = CURRTIME;
}
else if (level >= 3)
{
MOWGLI_ITER_FOREACH_SAFE(n, tn, svs_ignore_list.head)
{
svsignore = (svsignore_t *)n->data;
if (!strcasecmp(svsignore->mask,"*@*"))
{
slog(LG_INFO, "DEFCON:IGNORE:REMOVE");
svsignore_delete(svsignore);
}
}
}
}
static void defcon_forcechanmodes(void)
{
channel_t *chptr;
mowgli_patricia_iteration_state_t state;
service_t *svs;
char modesetbuf[256];
char modeunsetbuf[256];
svs = service_find("operserv");
if (level <= 3)
{
snprintf(modesetbuf, sizeof modesetbuf, "+%s", DEFCON_CMODE);
slog(LG_INFO, "DEFCON:MODE: %s", modesetbuf);
MOWGLI_PATRICIA_FOREACH(chptr, &state, chanlist)
{
channel_mode_va(svs->me, chptr, 1, modesetbuf);
}
}
else if (level >= 4)
{
snprintf(modeunsetbuf, sizeof modeunsetbuf, "-%s", DEFCON_CMODE);
slog(LG_INFO, "DEFCON:MODE: %s", modeunsetbuf);
MOWGLI_PATRICIA_FOREACH(chptr, &state, chanlist)
{
channel_mode_va(svs->me, chptr, 1, modeunsetbuf);
}
}
}
static void defcon_timeoutfunc(void *dummy)
{
service_t *svs;
char buf[BUFSIZE];
svs = service_find("operserv");
level = 5;
defcon_svsignore();
defcon_forcechanmodes();
slog(LG_INFO, "DEFCON:TIMEOUT");
snprintf(buf, sizeof buf, "The DEFCON level is now back to normal (\2%d\2). Sorry for any inconvenience this caused.", level);
notice_global_sts(svs->me, "*", buf);
}
static void os_cmd_defcon(sourceinfo_t *si, int parc, char *parv[])
{
char *defcon = parv[0];
char buf[BUFSIZE];
if (!defcon)
{
command_success_nodata(si, _("Defense condition is currently level \2%d\2."), level);
return;
}
level = atoi(defcon);
if ((level <= 0) || (level > 5))
{
command_fail(si, fault_badparams, _("Defcon level must be between 1 and 5"));
level = 5;
return;
}
/* Call the 2 functions that don't use hooks */
defcon_svsignore();
defcon_forcechanmodes();
if (level < 5)
{
snprintf(buf, sizeof buf, "The DEFCON level has been changed to \2%d\2. We apologize for any inconvenience.", level);
if (defcon_timer == NULL)
defcon_timer = mowgli_timer_add_once(base_eventloop, "defcon_timeout", defcon_timeoutfunc, NULL, defcon_timeout);
}
else
{
snprintf(buf, sizeof buf, "The DEFCON level is now back to normal (\2%d\2). Sorry for any inconvenience this caused.", level);
mowgli_timer_destroy(base_eventloop, defcon_timer);
defcon_timer = NULL;
}
notice_global_sts(si->service->me, "*", buf);
command_success_nodata(si, _("Defense condition set to level \2%d\2."), level);
wallops(_("\2%s\2 set Defense condition to level \2%d\2."), get_oper_name(si), level);
logcommand(si, CMDLOG_ADMIN, "DEFCON: \2%d\2", level);
}
/* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
* vim:ts=8
* vim:sw=8
* vim:noexpandtab
*/