/************************************************************************ * 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; }