1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
/*
* Copyright (c) 2011 Alexandria Wolcott
* Released under the same terms as Atheme itself.
*
* Netsplit monitor
*
*/
#include "atheme.h"
DECLARE_MODULE_V1("statserv/netsplit", false, _modinit, _moddeinit,
PACKAGE_STRING, "Alexandria Wolcott <alyx@sporksmoo.net>");
static void ss_cmd_netsplit(sourceinfo_t * si, int parc, char *parv[]);
static void ss_cmd_netsplit_list(sourceinfo_t * si, int parc, char *parv[]);
static void ss_cmd_netsplit_remove(sourceinfo_t * si, int parc, char *parv[]);
command_t ss_netsplit =
{ "NETSPLIT", N_("Monitor network splits."), PRIV_SERVER_AUSPEX, 2, ss_cmd_netsplit, {.path = "statserv/netsplit"} };
command_t ss_netsplit_list =
{ "LIST", N_("List currently split servers."), PRIV_SERVER_AUSPEX, 1, ss_cmd_netsplit_list, {.path = ""} };
command_t ss_netsplit_remove =
{ "REMOVE", N_("Remove a server from the netsplit list."), PRIV_JUPE, 2, ss_cmd_netsplit_remove, {.path = ""} };
mowgli_patricia_t *ss_netsplit_cmds;
mowgli_patricia_t *splitlist;
mowgli_heap_t *split_heap;
typedef struct {
char *name;
time_t disconnected_since;
unsigned int flags;
} split_t;
static void netsplit_delete_serv(split_t *s)
{
mowgli_patricia_delete(splitlist, s->name);
free(s->name);
mowgli_heap_free(split_heap, s);
}
static void netsplit_server_add(server_t *s)
{
split_t *serv = mowgli_patricia_retrieve(splitlist, s->name);
if (serv != NULL)
{
netsplit_delete_serv(serv);
}
}
static void netsplit_server_delete(hook_server_delete_t *serv)
{
split_t *s;
s = mowgli_heap_alloc(split_heap);
s->name = sstrdup(serv->s->name);
s->disconnected_since = CURRTIME;
s->flags = serv->s->flags;
mowgli_patricia_add(splitlist, s->name, s);
}
static void ss_cmd_netsplit(sourceinfo_t * si, int parc, char *parv[])
{
command_t *c;
char *cmd = parv[0];
if (!cmd)
{
command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "NETSPLIT");
command_fail(si, fault_needmoreparams,
_("Syntax: NETSPLIT [LIST|REMOVE] [parameters]"));
return;
}
c = command_find(ss_netsplit_cmds, cmd);
if (c == NULL)
{
command_fail(si, fault_badparams,
_("Invalid command. Use \2/%s%s help\2 for a command listing."),
(ircd->uses_rcommand == false) ? "msg " : "", si->service->disp);
return;
}
command_exec(si->service, si, c, parc - 1, parv + 1);
}
static void ss_cmd_netsplit_list(sourceinfo_t * si, int parc, char *parv[])
{
split_t *s;
mowgli_patricia_iteration_state_t state;
int i = 0;
MOWGLI_PATRICIA_FOREACH(s, &state, splitlist)
{
i++;
command_success_nodata(si, _("%d: %s [Split %s ago]"), i, s->name, time_ago(s->disconnected_since));
}
command_success_nodata(si, _("End of netsplit list."));
}
static void ss_cmd_netsplit_remove(sourceinfo_t * si, int parc, char *parv[])
{
char *name = parv[0];
split_t *s;
if (!name)
{
command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "NETSPLIT REMOVE");
command_fail(si, fault_needmoreparams,
_("Syntax: NETSPLIT REMOVE <server>"));
return;
}
s = mowgli_patricia_retrieve(splitlist, name);
if (s != NULL)
{
netsplit_delete_serv(s);
command_success_nodata(si, _("%s removed from the netsplit list."), name);
}
else
command_fail(si, fault_nosuch_target, _("The server \2%s\2 does is not a split server."), name);
}
void _modinit(module_t * m)
{
service_named_bind_command("statserv", &ss_netsplit);
ss_netsplit_cmds = mowgli_patricia_create(strcasecanon);
command_add(&ss_netsplit_list, ss_netsplit_cmds);
command_add(&ss_netsplit_remove, ss_netsplit_cmds);
hook_add_event("server_add");
hook_add_event("server_delete");
hook_add_server_add(netsplit_server_add);
hook_add_server_delete(netsplit_server_delete);
split_heap = mowgli_heap_create(sizeof(split_t), 30, BH_NOW);
if (split_heap == NULL)
{
slog(LG_INFO, "statserv/netsplit _modinit(): block allocator failure.");
exit(EXIT_FAILURE);
}
splitlist = mowgli_patricia_create(irccasecanon);
}
void _moddeinit(module_unload_intent_t intent)
{
mowgli_patricia_iteration_state_t state;
split_t *s;
MOWGLI_PATRICIA_FOREACH(s, &state, splitlist)
netsplit_delete_serv(s);
mowgli_heap_destroy(split_heap);
service_named_unbind_command("statserv", &ss_netsplit);
command_delete(&ss_netsplit_list, ss_netsplit_cmds);
command_delete(&ss_netsplit_remove, ss_netsplit_cmds);
hook_del_event("server_add");
hook_del_event("server_delete");
hook_del_server_add(netsplit_server_add);
hook_del_server_delete(netsplit_server_delete);
mowgli_patricia_destroy(ss_netsplit_cmds, NULL, NULL);
mowgli_patricia_destroy(splitlist, NULL, NULL);
}
|