/************************************************************************
* IRC - Internet Relay Chat, modules/m_stats.c
*
* Copyright (C) 2000-2003 TR-IRCD Development
*
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Co Center
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* $Id: m_stats.c,v 1.3 2003/06/14 13:55:51 tr-ircd Exp $
*/
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "h.h"
#include "logtype.h"
#include "s_conf.h"
#include "hook.h"
#include "ircsprintf.h"
#include "listener.h"
#include "throttle.h"
#include "event.h"
static char *s_token = TOK1_STATS;
static char *u_token = TOK1_UPTIME;
static int hookid_stats = 0;
static struct Message s_msgtab[] = {
{MSG_STATS, 0, MAXPARA, M_SLOW, 0L,
m_unregistered, m_stats, m_stats, m_stats, m_stats}
};
static struct Message u_msgtab[] = {
{MSG_UPTIME, 0, MAXPARA, M_SLOW, 0L,
m_unregistered, m_uptime, m_uptime, m_uptime, m_uptime}
};
#ifndef STATIC_MODULES
char *_version = "$Revision: 1.3 $";
void _modinit(void)
{
mod_add_cmd(s_msgtab);
tok1_msgtab[(u_char) *s_token].msg = s_msgtab;
mod_add_cmd(u_msgtab);
tok1_msgtab[(u_char) *u_token].msg = u_msgtab;
hookid_stats = hook_add_event("doing stats");
}
void _moddeinit(void)
{
mod_del_cmd(s_msgtab);
tok1_msgtab[(u_char) *s_token].msg = NULL;
mod_del_cmd(u_msgtab);
tok1_msgtab[(u_char) *u_token].msg = NULL;
hook_del_event("doing stats");
}
#else
void m_stats_init(void)
{
mod_add_cmd(s_msgtab);
tok1_msgtab[(u_char) *s_token].msg = s_msgtab;
mod_add_cmd(u_msgtab);
tok1_msgtab[(u_char) *u_token].msg = u_msgtab;
hookid_stats = hook_add_event("doing stats");
}
#endif
static void stats_permission(aClient *cptr, char **parv)
{
send_me_numeric(cptr, ERR_NOPRIVILEGES);
}
static void stats_akills(aClient *cptr, char **parv)
{
report_maskitem_list_primary(cptr, NULL, MASKITEM_AUTOKILL, RPL_STATSKLINE, 'a');
}
static void stats_debugmem(aClient *cptr, char **parv)
{
count_memory(cptr, parv[0]);
}
static void stats_connects(aClient *cptr, char **parv)
{
report_connect_blocks(cptr, 1);
}
static void stats_connected(aClient *cptr, char **parv)
{
report_connect_blocks(cptr, 0);
}
static void stats_auth_ek(aClient *cptr, char **parv)
{
report_auth_blocks(cptr, CONF_FLAGS_EXEMPTKLINE);
}
static void stats_excludes(aClient *cptr, char **parv)
{
report_maskitem_list_primary(cptr, NULL, MASKITEM_EXCLUDE, RPL_STATSKLINE, 'e');
}
static void stats_fdlist(aClient *cptr, char **parv)
{
fd_dump(cptr);
}
static void stats_sglines(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_GECOS, RPL_STATSGLINE, 'g');
report_maskitem_list_secondary(cptr, NULL, MASKITEM_GECOS_REGEX, RPL_STATSGLINE, 'g');
}
static void stats_glines(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_GECOS_CONFIG, RPL_STATSGLINE, 'G');
}
static void stats_hooks(aClient *cptr, char **parv)
{
hook_dump(cptr);
}
static void stats_hubs(aClient *cptr, char **parv)
{
report_connect_blocks_flag(cptr, CONF_FLAGS_HUB, RPL_STATSHLINE, 'H');
}
static void stats_auth(aClient *cptr, char **parv)
{
report_auth_blocks(cptr, 0);
}
static void stats_jupiters(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_JUPITER, RPL_STATSJLINE, 'j');
report_maskitem_list_secondary(cptr, NULL, MASKITEM_JUPITER_REGEX, RPL_STATSJLINE, 'j');
}
static void stats_jupes(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_JUPITER_CONFIG, RPL_STATSJLINE, 'J');
}
static void stats_temp_klines(aClient *cptr, char **parv)
{
report_maskitem_list_primary(cptr, NULL, MASKITEM_KLINE, RPL_STATSKLINE, 'k');
report_maskitem_list_primary(cptr, NULL, MASKITEM_KLINE_REGEX, RPL_STATSKLINE, 'k');
}
static void stats_klines(aClient *cptr, char **parv)
{
report_maskitem_list_primary(cptr, NULL, MASKITEM_KLINE_CONFIG, RPL_STATSKLINE, 'K');
}
static void stats_messages(aClient *cptr, char **parv)
{
report_messages(cptr);
}
static void stats_netstat_std(aClient *cptr, char **parv)
{
send_me_numeric(cptr, RPL_STATSCOUNT, "User Connects Today: ", Count.today);
}
static void stats_netstat(aClient *cptr, char **parv)
{
send_me_numeric(cptr, RPL_STATSCOUNT, "User Connects Today: ", Count.today);
send_me_numeric(cptr, RPL_STATSCOUNT, "User Connects past week: ", Count.weekly);
send_me_numeric(cptr, RPL_STATSCOUNT, "User Connects past month: ", Count.monthly);
send_me_numeric(cptr, RPL_STATSCOUNT, "User Conects past year: ", Count.yearly);
}
static void stats_operator(aClient *cptr, char **parv)
{
report_operator_blocks(cptr);
}
static void stats_opered(aClient *cptr, char **parv)
{
show_opers(cptr, parv[0]);
}
static void stats_protocol(aClient *cptr, char **parv)
{
report_protocol(cptr);
}
static void stats_ports(aClient *cptr, char **parv)
{
show_ports(cptr);
}
static void stats_sqlines(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_QUARANTINE, RPL_STATSQLINE, 'q');
report_maskitem_list_secondary(cptr, NULL, MASKITEM_QUARANTINE_REGEX, RPL_STATSQLINE, 'q');
}
static void stats_quarantines(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_QUARANTINE_CONFIG, RPL_STATSQLINE, 'Q');
}
static void stats_auth_redir(aClient *cptr, char **parv)
{
report_auth_blocks(cptr, CONF_FLAGS_REDIR);
}
static void stats_services(aClient *cptr, char **parv)
{
report_service_blocks(cptr, 1);
}
static void stats_connected_services(aClient *cptr, char **parv)
{
report_service_blocks(cptr, 0);
}
static void stats_uptime(aClient *cptr, char **parv)
{
time_t now = timeofday - me.since;
send_me_numeric(cptr, RPL_STATSUPTIME, now / 86400,
(now / 3600) % 24, (now / 60) % 60, now % 60);
}
static void stats_ultimate(aClient *cptr, char **parv)
{
report_connect_blocks_flag(cptr, CONF_FLAGS_ULTIMATE, RPL_STATSULINE, 'U');
}
static void stats_dccblock(aClient *cptr, char **parv)
{
int i;
char tempbuf[500]; /* who knows */
strcpy(tempbuf, "Blocked extensions are:");
for (i = 0; exploits_2char[i]; i++) {
strncat(tempbuf, exploits_2char[i], 2);
strncat(tempbuf, " ", 1);
}
for (i = 0; exploits_3char[i]; i++) {
strncat(tempbuf, exploits_3char[i], 3);
strncat(tempbuf, " ", 1);
}
for (i = 0; exploits_4char[i]; i++) {
strncat(tempbuf, exploits_4char[i], 4);
strncat(tempbuf, " ", 1);
}
send_me_debug(cptr, tempbuf);
}
static void stats_autoconnect(aClient *cptr, char **parv)
{
report_connect_blocks_flag(cptr, CONF_FLAGS_ALLOW_AUTO_CONN, RPL_STATSSLINE, 'V');
}
static void stats_eventdump(aClient *cptr, char **parv)
{
show_events(cptr);
}
static void stats_servers(aClient *cptr, char **parv)
{
show_servers(cptr, parv[0]);
}
static void stats_throttle(aClient *cptr, char **parv)
{
throttle_stats(cptr, parv[0]);
}
static void stats_classes(aClient *cptr, char **parv)
{
report_classes(cptr);
}
static void stats_szlines(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_ZAPLINE, RPL_STATSZLINE, 'z');
}
static void stats_zaplines(aClient *cptr, char **parv)
{
report_maskitem_list_secondary(cptr, NULL, MASKITEM_ZAPLINE_CONFIG, RPL_STATSZLINE, 'Z');
}
static void stats_servinfo(aClient *cptr, char **parv)
{
serv_info(cptr, parv[0]);
}
static void stats_usage(aClient *cptr, char **parv)
{
send_usage(cptr, parv[0]);
}
static void stats_stats(aClient *cptr, char **parv)
{
tstats(cptr, parv[0]);
}
static void stats_logevents(aClient *cptr, char **parv)
{
dump_logevents(cptr);
}
static void stats_adns(aClient *cptr, char **parv)
{
report_adns_servers(cptr);
}
static void stats_more(aClient *cptr, char **parv)
{
struct hook_data thisdata;
thisdata.client_p = cptr;
thisdata.parv = parv;
hook_call_event(hookid_stats, &thisdata);
}
static void stats_linkinfo(aClient *cptr, char **parv)
{
static char Lformat[] = ":%C %N %s %s %u %u %u %u %u :%u %u %s";
static char Sformat[] =
":%C %N %s Name SendQ SendM SendBytes RcveM RcveBytes :Open_since Idle TS";
aClient *acptr;
int doall = 0, wilds = 0;
char *name;
time_t sincetime;
dlink_node *ptr;
if (parv[2]) {
name = parv[2];
if (!irc_strcmp(name, me.name))
doall = 2;
else if (match(name, me.name) == 0)
doall = 1;
if (strchr(name, '*') || strchr(name, '?'))
wilds = 1;
} else
name = me.name;
sendto_one(cptr, Sformat, &me, RPL_STATSLINKINFO, parv[0]);
if ((parv[2]) && !(doall || wilds)) { /* Single client lookup
*/
if (!IsAnOper(cptr)) {
send_me_numeric(cptr, ERR_NOPRIVILEGES);
return;
}
if (!(acptr = find_person(name)))
return;
/*
* sincetime might be greater than timeofday,
* store a new value here to avoid sending
* negative since-times. -Rak
*/
sincetime = (acptr->since > timeofday) ? 0 : timeofday - acptr->since;
sendto_one(cptr, Lformat, &me, RPL_STATSLINKINFO, parv[0],
get_client_name(acptr, TRUE),
(int) linebuf_len(&acptr->sendQ), (int) acptr->sendM,
(int) acptr->sendK, (int) acptr->receiveM,
(int) acptr->receiveK, timeofday - acptr->firsttime,
sincetime, IsServer(acptr) ? (DoesTS(acptr) ? "TS" : "NoTS") : "-");
} else {
for (ptr = lclient_list.head; ptr; ptr = ptr->next) {
if (!(acptr = ptr->data))
continue;
if (!IsServer(acptr))
continue; /* nothing but servers */
if (ServicesConf.hide_ulined_servers && IsULine(acptr) && !IsSeeHidden(cptr))
continue;
sincetime = (acptr->since > timeofday) ? 0 : timeofday - acptr->since;
sendto_one(cptr, Lformat, &me, RPL_STATSLINKINFO,
parv[0], get_client_name(acptr, HIDEME),
(int) linebuf_len(&acptr->sendQ),
(int) acptr->sendM, (int) acptr->sendK,
(int) acptr->receiveM, (int) acptr->receiveK,
timeofday - acptr->firsttime, sincetime,
IsServer(acptr) ? (DoesTS(acptr) ? "TS" : "NoTS")
: "-");
}
}
}
/*
* /stats command has merely almost 52 different ways of usage.
* these are listed in this table.
* -TimeMr14C
*/
struct StatsFunc {
int exists;
void (*sf_user) ();
void (*sf_oper) ();
};
struct StatsFunc statstab[] = {
{0, NULL, NULL}, /* #0 */
{0, NULL, NULL}, /* #1 */
{0, NULL, NULL}, /* #2 */
{0, NULL, NULL}, /* #3 */
{0, NULL, NULL}, /* #4 */
{0, NULL, NULL}, /* #5 */
{0, NULL, NULL}, /* #6 */
{0, NULL, NULL}, /* #7 */
{0, NULL, NULL}, /* #8 */
{0, NULL, NULL}, /* #9 */
{0, NULL, NULL}, /* #10 */
{0, NULL, NULL}, /* #11 */
{0, NULL, NULL}, /* #12 */
{0, NULL, NULL}, /* #13 */
{0, NULL, NULL}, /* #14 */
{0, NULL, NULL}, /* #15 */
{0, NULL, NULL}, /* #16 */
{0, NULL, NULL}, /* #17 */
{0, NULL, NULL}, /* #18 */
{0, NULL, NULL}, /* #19 */
{0, NULL, NULL}, /* #20 */
{0, NULL, NULL}, /* #21 */
{0, NULL, NULL}, /* #22 */
{0, NULL, NULL}, /* #23 */
{0, NULL, NULL}, /* #24 */
{0, NULL, NULL}, /* #25 */
{0, NULL, NULL}, /* #26 */
{0, NULL, NULL}, /* #27 */
{0, NULL, NULL}, /* #28 */
{0, NULL, NULL}, /* #29 */
{0, NULL, NULL}, /* #30 */
{0, NULL, NULL}, /* #31 */
{0, NULL, NULL}, /* #32 */
{0, NULL, NULL}, /* ! */
{0, NULL, NULL}, /* " */
{0, NULL, NULL}, /* # */
{0, NULL, NULL}, /* $ */
{0, NULL, NULL}, /* % */
{0, NULL, NULL}, /* & */
{0, NULL, NULL}, /* ' */
{0, NULL, NULL}, /* ( */
{0, NULL, NULL}, /* ) */
{0, NULL, NULL}, /* * */
{0, NULL, NULL}, /* + */
{0, NULL, NULL}, /* , */
{0, NULL, NULL}, /* - */
{0, NULL, NULL}, /* . */
{0, NULL, NULL}, /* / */
{0, NULL, NULL}, /* 0 */
{0, NULL, NULL}, /* 1 */
{0, NULL, NULL}, /* 2 */
{0, NULL, NULL}, /* 3 */
{0, NULL, NULL}, /* 4 */
{0, NULL, NULL}, /* 5 */
{0, NULL, NULL}, /* 6 */
{0, NULL, NULL}, /* 7 */
{0, NULL, NULL}, /* 8 */
{0, NULL, NULL}, /* 9 */
{0, NULL, NULL}, /* : */
{0, NULL, NULL}, /* ; */
{0, NULL, NULL}, /* < */
{0, NULL, NULL}, /* = */
{0, NULL, NULL}, /* > */
{1, stats_servinfo, stats_servinfo}, /* ? */
{0, NULL, NULL}, /* @ */
{1, stats_permission, stats_akills}, /* A */
{1, stats_permission, stats_dccblock}, /* B */
{1, stats_permission, stats_connects}, /* C */
{1, stats_dccblock, stats_debugmem}, /* D */
{1, stats_excludes, stats_excludes}, /* E */
{1, stats_permission, stats_fdlist}, /* F */
{1, stats_glines, stats_glines}, /* G */
{1, stats_permission, stats_hubs}, /* H */
{1, stats_auth, stats_auth}, /* I */
{1, stats_jupes, stats_jupes}, /* J */
{1, stats_permission, stats_klines}, /* K */
{1, stats_permission, stats_logevents}, /* L */
{1, stats_messages, stats_messages}, /* M */
{1, stats_netstat_std, stats_netstat}, /* N */
{1, stats_opered, stats_opered}, /* O */
{1, stats_permission, stats_ports}, /* P */
{1, stats_quarantines, stats_quarantines}, /* Q */
{1, stats_permission, stats_auth_redir}, /* R */
{1, stats_permission, stats_connected_services}, /* S */
{1, stats_permission, stats_stats}, /* T */
{1, stats_ultimate, stats_ultimate}, /* U */
{1, stats_servers, stats_servers}, /* V */
{1, stats_more, stats_more}, /* W */
{1, stats_permission, stats_eventdump}, /* X */
{1, stats_classes, stats_classes}, /* Y */
{1, stats_permission, stats_zaplines}, /* Z */
{0, NULL, NULL}, /* [ */
{0, NULL, NULL}, /* \ */
{0, NULL, NULL}, /* ] */
{0, NULL, NULL}, /* ^ */
{0, NULL, NULL}, /* _ */
{0, NULL, NULL}, /* ` */
{1, stats_permission, stats_akills}, /* a */
{1, stats_permission, stats_usage}, /* b */
{1, stats_connected, stats_connected}, /* c */
{1, stats_permission, stats_debugmem}, /* d */
{1, stats_permission, stats_auth_ek}, /* e */
{1, stats_permission, stats_fdlist}, /* f */
{1, stats_sglines, stats_sglines}, /* g */
{1, stats_permission, stats_hooks}, /* h */
{1, stats_auth, stats_auth}, /* i */
{1, stats_jupiters, stats_jupiters}, /* j */
{1, stats_permission, stats_temp_klines}, /* k */
{1, stats_linkinfo, stats_linkinfo}, /* l */
{1, stats_messages, stats_messages}, /* m */
{1, stats_netstat_std, stats_netstat_std}, /* n */
{1, stats_permission, stats_operator}, /* o */
{1, stats_protocol, stats_protocol}, /* p */
{1, stats_sqlines, stats_sqlines}, /* q */
{1, stats_permission, stats_auth_redir}, /* r */
{1, stats_permission, stats_services}, /* s */
{1, stats_permission, stats_throttle}, /* t */
{1, stats_uptime, stats_uptime}, /* u */
{1, stats_permission, stats_autoconnect}, /* v */
{1, stats_more, stats_more}, /* w */
{1, stats_permission, stats_eventdump}, /* x */
{1, stats_classes, stats_classes}, /* y */
{1, stats_permission, stats_szlines}, /* z */
{0, NULL, NULL}, /* { */
{0, NULL, NULL}, /* | */
{0, NULL, NULL}, /* } */
{1, stats_permission, stats_adns}, /* ~ */
{0, NULL, NULL}, /* #127 */
};
/*
*
* m_stats
* parv[0] = sender prefix
* parv[1] = statistics selector (defaults to Message frequency)
* parv[2] = server name (current server defaulted, if omitted)
*/
int m_stats(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
char stat = parc > 1 ? parv[1][0] : '\0';
int s = stat;
struct StatsFunc *thisfunc;
if (hunt_server(cptr, sptr, ":%s %s %s :%s", TOK1_STATS, 2, parc, parv) != HUNTED_ISME)
return 0;
if (stat != (char) 0)
sendto_lev(SPY_LEV, "STATS %c requested by %^C [%s]", stat, sptr, sptr->user->server);
if (s > 127 || s <= 0) {
send_me_numeric(sptr, RPL_ENDOFSTATS, stat);
return 0;
}
thisfunc = &statstab[(int) stat];
if (thisfunc->exists) {
if (IsAnOper(sptr))
(*thisfunc->sf_oper) (sptr, parv);
else
(*thisfunc->sf_user) (sptr, parv);
}
send_me_numeric(sptr, RPL_ENDOFSTATS, stat);
return 0;
}
int m_uptime(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
if (hunt_server(cptr, sptr, ":%s %s %s", TOK1_UPTIME, 1, parc, parv) != HUNTED_ISME)
return 0;
sendto_lev(SPY_LEV, "UPTIME requested by %^C [%s]", sptr, sptr->user->server);
stats_uptime(sptr, parv);
send_me_numeric(sptr, RPL_ENDOFSTATS, 'u');
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1