/* m_stats.c * Copyright (c) 2004, The Bahamut Development Team and Aaron Wiebe * * See file AUTHORS in IRC package for additional names of * the programmers. * * This program is free softwmare; 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 1, 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.6 2006/03/12 19:47:50 sheik Exp $ */ #include "struct.h" #include "common.h" #include "sys.h" #include "numeric.h" #include "msg.h" #include "channel.h" #include #include #include #include "h.h" #include "zlink.h" #include "userban.h" #include "blalloc.h" #include "throttle.h" #include "whowas.h" #include "res.h" #include "sbuf.h" #include "clones.h" #include "memcount.h" #if defined(DEBUGMODE) && defined(HAVE_GETRUSAGE) #include #include #endif extern float curSendK, curRecvK; extern aWhowas WHOWAS[]; extern aCache *cachetop; #ifdef DEBUGMODE extern void report_fds(aClient *); #endif /* internal function defines */ static void show_opers(aClient *, char *); static void show_servers(aClient *, char *); #ifdef DEBUGMODE static void send_usage(aClient *, char *); #endif static void serv_info(aClient *, char *); static void tstats(aClient *, char *); #ifdef DEBUGMODE static void send_usage(aClient *cptr, char *nick) { #if defined( HAVE_GETRUSAGE ) struct rusage rus; time_t secs, rup; #ifdef hz #define hzz hz #else #ifdef HZ #define hzz HZ #else int hzz = 1; #endif #endif if (getrusage(RUSAGE_SELF, &rus) == -1) { sendto_one(cptr, ":%s NOTICE %s :Getruseage error: %s.", me.name, nick, sys_errlist[errno]); return; } secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec; rup = timeofday - me.since; if (secs == 0) secs = 1; sendto_one(cptr, ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d", me.name, RPL_STATSDEBUG, nick, secs / 60, secs % 60, rus.ru_utime.tv_sec / 60, rus.ru_utime.tv_sec % 60, rus.ru_stime.tv_sec / 60, rus.ru_stime.tv_sec % 60); sendto_one(cptr, ":%s %d %s :RSS %d ShMem %d Data %d Stack %d", me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss, rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz), rus.ru_isrss / (rup * hzz)); sendto_one(cptr, ":%s %d %s :Swaps %d Reclaims %d Faults %d", me.name, RPL_STATSDEBUG, nick, rus.ru_nswap, rus.ru_minflt, rus.ru_majflt); sendto_one(cptr, ":%s %d %s :Block in %d out %d", me.name, RPL_STATSDEBUG, nick, rus.ru_inblock, rus.ru_oublock); sendto_one(cptr, ":%s %d %s :Msg Rcv %d Send %d", me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd); sendto_one(cptr, ":%s %d %s :Signals %d Context Vol. %d Invol %d", me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #else #if defined( HAVE_TIMES ) struct tms tmsbuf; time_t secs, mins; int hzz = 1, ticpermin; int umin, smin, usec, ssec; ticpermin = hzz * 60; umin = tmsbuf.tms_utime / ticpermin; usec = (tmsbuf.tms_utime % ticpermin) / (float) hzz; smin = tmsbuf.tms_stime / ticpermin; ssec = (tmsbuf.tms_stime % ticpermin) / (float) hzz; secs = usec + ssec; mins = (secs / 60) + umin + smin; secs %= hzz; if (times(&tmsbuf) == -1) { sendto_one(cptr, ":%s %d %s :times(2) error: %s.", me.name, RPL_STATSDEBUG, nick, strerror(errno)); return; } secs = tmsbuf.tms_utime + tmsbuf.tms_stime; sendto_one(cptr, ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d", me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec, smin, ssec); #endif /* HAVE_TIMES */ #endif /* HAVE_GETRUSAGE */ sendto_one(cptr, ":%s %d %s :Reads %d Writes %d", me.name, RPL_STATSDEBUG, nick, readcalls, writecalls); /* sendto_one(cptr, ":%s %d %s :DBUF alloc %d used %d", me.name, RPL_STATSDEBUG, nick, DBufCount, DBufUsedCount); */ sendto_one(cptr, ":%s %d %s :Writes: <0 %d 0 %d <16 %d <32 %d <64 %d", me.name, RPL_STATSDEBUG, nick, writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]); sendto_one(cptr, ":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d", me.name, RPL_STATSDEBUG, nick, writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]); return; } #endif /* DEBUGMODE */ /* Thanks goes to bamaboy for contributing this code. on 15/05/2005 * This will show the available ports on the ircd including ssl ports if any. * */ #ifdef STATS_P_ENABLED static void show_ports(aClient *cptr) { aPort *ptptr; int ptc = 0; for (ptptr = ports; ptptr; ptptr = ptptr->next) { ptc++; sendto_one(cptr,":%s %d %s :Port - %i (%s)",me.name,RPL_STATSDEBUG,cptr->name,ptptr->port,ptptr->ptype ? "SSL Port" : "NON-SSL Port"); } sendto_one(cptr,":%s %d %s :Total Listening Ports: %i",me.name,RPL_STATSDEBUG,cptr->name,ptc); return; } #endif static void show_opers(aClient *cptr, char *name) { aClient *cptr2; DLink *lp; int j = 0; for (lp = oper_list; lp; lp = lp->next) { cptr2 = lp->value.cptr; if (!IsAnOper(cptr)) { if (cptr2->umode & UMODE_h) { sendto_one(cptr, ":%s %d %s :%s (%s@%s) Idle: %d", me.name, RPL_STATSDEBUG, name, cptr2->name, cptr2->user->username, cptr2->user->host, timeofday - cptr2->user->last); j++; } } else { sendto_one(cptr, ":%s %d %s :%s (%s@%s) Idle: %d", me.name, RPL_STATSDEBUG, name, cptr2->name, cptr2->user->username, cptr2->user->host, timeofday - cptr2->user->last); j++; } } sendto_one(cptr, ":%s %d %s :%d OPER%s", me.name, RPL_STATSDEBUG, name, j, (j == 1) ? "" : "s"); } /* show_servers * replies to stats v requests */ static void show_servers(aClient *cptr, char *name) { aClient *cptr2; DLink *lp; int j = 0; for (lp = server_list; lp; lp = lp->next) { cptr2 = lp->value.cptr; #ifdef HIDEULINEDSERVS if(IsULine(cptr2) && !IsAnOper(cptr)) continue; #endif j++; sendto_one(cptr, ":%s %d %s :%s (%s!%s@%s) Idle: %d", me.name, RPL_STATSDEBUG, name, cptr2->name, (cptr2->serv->bynick[0] ? cptr2->serv->bynick : "Remote."), (cptr2->serv->byuser[0] ? cptr2->serv->byuser : "*"), (cptr2->serv->byhost[0] ? cptr2->serv->byhost : "*"), timeofday - cptr2->lasttime); } sendto_one(cptr, ":%s %d %s :%d Server%s", me.name, RPL_STATSDEBUG, name, j, (j == 1) ? "" : "s"); } /* serv_info * replies to stats ? requests */ #define _1MEG (1024.0) #define _1GIG (1024.0*1024.0) #define _1TER (1024.0*1024.0*1024.0) #define _GMKs(x) ((x > _1TER) ? "Terabytes" : ((x > _1GIG) ? \ "Gigabytes" : \ ((x > _1MEG) ? "Megabytes" : "Kilobytes"))) #define _GMKv(x) ( (x > _1TER) ? (float)(x/_1TER) : ((x > _1GIG) ? \ (float)(x/_1GIG) : ((x > _1MEG) ? (float)(x/_1MEG) :\ (float)x))) static void serv_info(aClient *cptr, char *name) { static char Lformat[] = ":%s %d %s %s %u %u %u %u %u :%u %u %s"; long sendK, receiveK, uptime; aClient *acptr; DLink *lp; int i = 0; sendK = receiveK = 0; for (lp = server_list; lp; lp = lp->next) { acptr = lp->value.cptr; #ifdef HIDEULINEDSERVS if (IsULine(acptr) && !IsAnOper(cptr)) continue; #endif sendK += acptr->sendK; receiveK += acptr->receiveK; sendto_one(cptr, Lformat, me.name, RPL_STATSLINKINFO, name, ( (MyClient(cptr) && IsAdmin(cptr)) ? get_client_name(acptr, FALSE) : get_client_name(acptr, HIDEME) ), (int) SBufLength(&acptr->sendQ), (int) acptr->sendM, (int) acptr->sendK, (int) acptr->receiveM, (int) acptr->receiveK, timeofday - acptr->firsttime, timeofday - acptr->since, IsServer(acptr) ? (DoesTS(acptr) ? "TS" : "NoTS") : "-"); if(RC4EncLink(acptr)) sendto_one(cptr, ":%s %d %s : - RC4 encrypted", me.name, RPL_STATSDEBUG, name); if(ZipOut(acptr)) { unsigned long ib, ob; double rat; zip_out_get_stats(acptr->serv->zip_out, &ib, &ob, &rat); if(ib) { sendto_one(cptr, ":%s %d %s : - [O] Zip inbytes %d, " "outbytes %d (%3.2f%%)", me.name, RPL_STATSDEBUG, name, ib, ob, rat); } } if(ZipIn(acptr)) { unsigned long ib, ob; double rat; zip_in_get_stats(acptr->serv->zip_in, &ib, &ob, &rat); if(ob) { sendto_one(cptr, ":%s %d %s : - [I] Zip inbytes %d, " "outbytes %d (%3.2f%%)", me.name, RPL_STATSDEBUG, name, ib, ob, rat); } } i++; } sendto_one(cptr, ":%s %d %s :%u total server%s", me.name, RPL_STATSDEBUG, name, i, (i == 1) ? "" : "s"); sendto_one(cptr, ":%s %d %s :Sent total : %7.2f %s", me.name, RPL_STATSDEBUG, name, _GMKv(sendK), _GMKs(sendK)); sendto_one(cptr, ":%s %d %s :Recv total : %7.2f %s", me.name, RPL_STATSDEBUG, name, _GMKv(receiveK), _GMKs(receiveK)); uptime = (timeofday - me.since); sendto_one(cptr, ":%s %d %s :Server send: %7.2f %s (%4.1f K/s total," " %4.1f K/s current)", me.name, RPL_STATSDEBUG, name, _GMKv(me.sendK), _GMKs(me.sendK), (float) ((float) me.sendK / (float) uptime), curSendK); sendto_one(cptr, ":%s %d %s :Server recv: %7.2f %s (%4.1f K/s total," " %4.1f K/s current)", me.name, RPL_STATSDEBUG, name, _GMKv(me.receiveK), _GMKs(me.receiveK), (float) ((float) me.receiveK / (float) uptime), curRecvK); } /* tstats * responced to stats t requests (oddly enough) */ static void tstats(aClient *cptr, char *name) { aClient *acptr; int i; struct stats *sp; struct stats tmp; sp = &tmp; memcpy((char *) sp, (char *) ircstp, sizeof(*sp)); for (i = 0; i < highest_fd; i++) { if (!(acptr = local[i])) continue; if (IsServer(acptr)) { sp->is_sbs += acptr->sendB; sp->is_sbr += acptr->receiveB; sp->is_sks += acptr->sendK; sp->is_skr += acptr->receiveK; sp->is_sti += timeofday - acptr->firsttime; sp->is_sv++; if (sp->is_sbs > 1023) { sp->is_sks += (sp->is_sbs >> 10); sp->is_sbs &= 0x3ff; } if (sp->is_sbr > 1023) { sp->is_skr += (sp->is_sbr >> 10); sp->is_sbr &= 0x3ff; } } else if (IsClient(acptr)) { sp->is_cbs += acptr->sendB; sp->is_cbr += acptr->receiveB; sp->is_cks += acptr->sendK; sp->is_ckr += acptr->receiveK; sp->is_cti += timeofday - acptr->firsttime; sp->is_cl++; if (sp->is_cbs > 1023) { sp->is_cks += (sp->is_cbs >> 10); sp->is_cbs &= 0x3ff; } if (sp->is_cbr > 1023) { sp->is_ckr += (sp->is_cbr >> 10); sp->is_cbr &= 0x3ff; } } else if (IsUnknown(acptr)) sp->is_ni++; } sendto_one(cptr, ":%s %d %s :accepts %u refused %u", me.name, RPL_STATSDEBUG, name, sp->is_ac, sp->is_ref); sendto_one(cptr, ":%s %d %s :unknown commands %u prefixes %u", me.name, RPL_STATSDEBUG, name, sp->is_unco, sp->is_unpf); sendto_one(cptr, ":%s %d %s :nick collisions %u unknown closes %u", me.name, RPL_STATSDEBUG, name, sp->is_kill, sp->is_ni); sendto_one(cptr, ":%s %d %s :wrong direction %u empty %u", me.name, RPL_STATSDEBUG, name, sp->is_wrdi, sp->is_empt); sendto_one(cptr, ":%s %d %s :numerics seen %u mode fakes %u", me.name, RPL_STATSDEBUG, name, sp->is_num, sp->is_fake); sendto_one(cptr, ":%s %d %s :auth successes %u fails %u", me.name, RPL_STATSDEBUG, name, sp->is_asuc, sp->is_abad); sendto_one(cptr, ":%s %d %s :local connections %u udp packets %u", me.name, RPL_STATSDEBUG, name, sp->is_loc, sp->is_udp); sendto_one(cptr, ":%s %d %s :drones refused %u throttled rejections %u", me.name, RPL_STATSDEBUG, name, sp->is_drone, sp->is_throt); sendto_one(cptr, ":%s %d %s :banned users refused before ident/dns" " %u after ident/dns %u", me.name, RPL_STATSDEBUG, name, sp->is_ref_1, sp->is_ref_2); sendto_one(cptr, ":%s %d %s :Client Server", me.name, RPL_STATSDEBUG, name); sendto_one(cptr, ":%s %d %s :connected %u %u", me.name, RPL_STATSDEBUG, name, sp->is_cl, sp->is_sv); sendto_one(cptr, ":%s %d %s :bytes sent %u.%uK %u.%uK", me.name, RPL_STATSDEBUG, name, sp->is_cks, sp->is_cbs, sp->is_sks, sp->is_sbs); sendto_one(cptr, ":%s %d %s :bytes recv %u.%uK %u.%uK", me.name, RPL_STATSDEBUG, name, sp->is_ckr, sp->is_cbr, sp->is_skr, sp->is_sbr); sendto_one(cptr, ":%s %d %s :time connected %u %u", me.name, RPL_STATSDEBUG, name, sp->is_cti, sp->is_sti); #ifdef FLUD sendto_one(cptr, ":%s %d %s :CTCP Floods Blocked %u", me.name, RPL_STATSDEBUG, name, sp->is_flud); #endif /* FLUD */ } /* m_stats and friends * Carved off from s_serv.c in Feb04 by epiphani * This mess of routines seemed to go better by themselves, seeing * as how s_serv.c is getting massive. * * 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[]) { static char Lformat[] = ":%s %d %s %s %u %u %u %u %u :%u %u %s"; static char Sformat[] = ":%s %d %s Name SendQ SendM SendBytes RcveM " "RcveBytes :Open_since Idle TS"; struct Message *mptr; aClient *acptr; char stat = parc > 1 ? parv[1][0] : '\0'; int i, doall = 0, wilds = 0; char *name; time_t sincetime; static time_t last_used = 0L; #ifdef NO_USER_STATS if (!IsAnOper(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } #else #ifdef NO_LOCAL_USER_STATS if (!IsAnOper(sptr) && !MyConnect(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } #endif #endif if (hunt_server(cptr, sptr, ":%s STATS %s :%s", 2, parc, parv) != HUNTED_ISME) return 0; if (IsSquelch(sptr)) return 0; if (!IsAnOper(sptr) && !IsULine(sptr)) { /* allow remote stats p l ? u */ if (!((stat == 'p') || (stat == 'P') || (stat=='?') || (stat=='u') || (stat=='l') || (stat=='L')) && !MyConnect(sptr)) return 0; /* if they're my user, penalize them. */ if (MyConnect(sptr)) sptr->since += 5; if ((last_used + MOTD_WAIT) > NOW) return 0; else last_used = NOW; } if (parc > 2) { name = parv[2]; if (!mycmp(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; if (stat != (char) 0 && !IsULine(sptr) && !IsServer(sptr)) sendto_realops_lev(SPY_LEV, "STATS %c requested by %s (%s@%s) [%s]", stat, sptr->name, sptr->user->username, sptr->user->host, sptr->user->server); switch (stat) { case 'L': case 'l': /* changed behavior totally. This is what we do now: * #1: if the user is not opered, never return ips for anything * #2: we DON'T deny /stats l for opers. Ever heard of /sping? * it's easy to see if you're lagging a server, why restrict * something used 99% of the time for good when you're not * doing any harm? * #3: NEVER return all users on a server, UGH, just like * /trace, this was fiercely obnoxious. If you don't * add an argument, you get all SERVER links. */ sendto_one(sptr, Sformat, me.name, RPL_STATSLINKINFO, parv[0]); if ((parc > 2) && !(doall || wilds)) { /* Single client lookup */ if (!(acptr = find_person(name, NULL))) break; /* * 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(sptr, Lformat, me.name, RPL_STATSLINKINFO, parv[0], get_client_name(acptr, TRUE), (int) SBufLength(&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 (i = 0; i <= highest_fd; i++) { if (!(acptr = local[i])) continue; if(!IsServer(acptr)) continue; /* nothing but servers */ #ifdef HIDEULINEDSERVS if(IsULine(acptr) && !IsAnOper(sptr)) continue; #endif sincetime = (acptr->since > timeofday) ? 0 : timeofday - acptr->since; sendto_one(sptr, Lformat, me.name, RPL_STATSLINKINFO, parv[0], ( (MyClient(sptr) && IsAdmin(sptr)) ? get_client_name(acptr, FALSE) : get_client_name(acptr, HIDEME) ), (int) SBufLength(&acptr->sendQ), (int) acptr->sendM, (int) acptr->sendK, (int) acptr->receiveM, (int) acptr->receiveK, timeofday - acptr->firsttime, sincetime, IsServer(acptr) ? (DoesTS(acptr) ? "TS" : "NoTS") : "-"); } } break; case 'C': case 'c': /* this should be fixed and combined into a more reasonable * single responce. Will work on this later -epi */ /* Only Server Administrators should see this information -Sheik 02-jan-2006*/ #ifdef RESTRICT_C_LINES_ADMINONLY if (!IsAdmin(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } #endif #ifdef HIDEULINEDSERVS if (!IsAnOper(sptr)) sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); else #endif { aConnect *tmp; if(!connects) break; for(tmp = connects; tmp; tmp = tmp->next) { if (tmp->legal == -1) continue; if(IsULine(sptr) || (MyClient(sptr) && IsAdmin(sptr))) { sendto_one(sptr, rpl_str(RPL_STATSCLINE), me.name, sptr->name, "C", tmp->host, tmp->name, tmp->port, tmp->class->name); sendto_one(sptr, rpl_str(RPL_STATSNLINE), me.name, sptr->name, "N", tmp->host, tmp->name, tmp->flags, tmp->class->name); } else { sendto_one(sptr, rpl_str(RPL_STATSCLINE), me.name, sptr->name, "C", "*", tmp->name, tmp->port, tmp->class->name); sendto_one(sptr, rpl_str(RPL_STATSNLINE), me.name, sptr->name, "N", "*", tmp->name, tmp->flags, tmp->class->name); } } } break; case 'D': if (!IsAnOper(sptr)) sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); else { CloneEnt *ce; for (ce = clones_list; ce; ce = ce->next) if (ce->limit || ce->sllimit || ce->sglimit) sendto_one(sptr, rpl_str(RPL_STATSCLONE), me.name, parv[0], ce->ent, ce->sllimit, ce->sglimit, ce->limit); } break; case 'd': if (!IsAnOper(sptr)) sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); else { CloneEnt *ce; int entries = 0; #ifdef THROTTLE_ENABLE int sllimits = 0; int sglimits = 0; int hlimits = 0; int active = 0; int sites = 0; unsigned long rtot; #endif for (ce = clones_list; ce; ce = ce->next) { entries++; #ifdef THROTTLE_ENABLE if (ce->sllimit) sllimits++; if (ce->sglimit) sglimits++; if (ce->limit) hlimits++; if (ce->gcount) { active++; /* blah, but not important enough for its own flag */ if (!ce->clients) sites++; } #endif } #ifdef THROTTLE_ENABLE rtot = clones_stat.rlh + clones_stat.rls + clones_stat.rgh + clones_stat.rgs; sendto_one(sptr, ":%s %d %s :Default local host limit: %d" " site: %d", me.name, RPL_STATSDEBUG, parv[0], local_ip_limit, local_ip24_limit); sendto_one(sptr, ":%s %d %s :Default global host limit: %d" " site: %d", me.name, RPL_STATSDEBUG, parv[0], global_ip_limit, global_ip24_limit); #endif sendto_one(sptr, ":%s %d %s :Clone entries: %d", me.name, RPL_STATSDEBUG, parv[0], entries); #ifdef THROTTLE_ENABLE sendto_one(sptr, ":%s %d %s : Active hosts: %d sites: %d", me.name, RPL_STATSDEBUG, parv[0], active-sites, sites); sendto_one(sptr, ":%s %d %s : Soft local limits: %d" " global: %d", me.name, RPL_STATSDEBUG, parv[0], sllimits, sglimits); sendto_one(sptr, ":%s %d %s : Hard global limits: %d", me.name, RPL_STATSDEBUG, parv[0], hlimits); sendto_one(sptr, ":%s %d %s :Rejected connections: %lu", me.name, RPL_STATSDEBUG, parv[0], rtot); sendto_one(sptr, ":%s %d %s : Local hosts: %lu sites: %lu", me.name, RPL_STATSDEBUG, parv[0], clones_stat.rlh, clones_stat.rls); sendto_one(sptr, ":%s %d %s : Global hosts: %lu sites: %lu", me.name, RPL_STATSDEBUG, parv[0], clones_stat.rgh, clones_stat.rgs); #endif } break; case 'G': if(IsAnOper(sptr)) report_simbans_match_flags(sptr, SBAN_GCOS|SBAN_LOCAL, 0); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'g': if(IsAnOper(sptr)) report_simbans_match_flags(sptr, SBAN_GCOS|SBAN_NETWORK, 0); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'I': case 'i': { aAllow *tmp; if(!allows) break; for(tmp = allows; tmp; tmp = tmp->next) { if (tmp->passwd && !(IsAnOper(sptr) || IsULine(sptr))) continue; sendto_one(sptr, rpl_str(RPL_STATSILINE), me.name, sptr->name, (tmp->legal == -1 ? "Ix" : "I"), tmp->ipmask, tmp->flags, tmp->hostmask, tmp->port, tmp->class->name); } break; } case 'k': if(IsAnOper(sptr)) report_userbans_match_flags(sptr, UBAN_TEMPORARY|UBAN_LOCAL, 0); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'K': if (IsAnOper(sptr)) report_userbans_match_flags(sptr, UBAN_LOCAL, UBAN_TEMPORARY); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; /* Added G-line Stats -Sheik 4/12/2005 */ case 'b': if(IsAnOper(sptr)) report_userbans_match_flags(sptr, UBAN_GLINE, 0); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; break; case 'A': case 'a': if(IsAnOper(sptr)) report_userbans_match_flags(sptr, UBAN_NETWORK, 0); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'M': case 'm': /* * original behaviour was not to report the command, if * the command hadn't been used. I'm going to always * report the command instead -Dianora * Why would users want to see this? Made Oper only. */ if(IsAnOper(sptr)) for (mptr = msgtab; mptr->cmd; mptr++) sendto_one(sptr, rpl_str(RPL_STATSCOMMANDS), me.name, parv[0], mptr->cmd, mptr->count, mptr->bytes); break; case 'N': case 'n': sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0], "User Connects Today: ", Count.today); sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0], "User Connects past week: ", Count.weekly); sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0], "User Connects past month: ", Count.monthly); sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0], "User Connects past year: ", Count.yearly); break; case 'o': case 'O': { aOper *tmp; int i = 0; if(!opers) break; if (IsAnOper(sptr) || IsULine(sptr)) { for(tmp = opers; tmp; tmp = tmp->next) for(i = 0; tmp->hosts[i]; i++) sendto_one(sptr, rpl_str(RPL_STATSOLINE), me.name, sptr->name, (tmp->legal == -1 ? "Ox" : "O"), tmp->hosts[i], tmp->nick, tmp->flags, tmp->class->name); } else { for(tmp = opers; tmp; tmp = tmp->next) { if (tmp->legal == -1) continue; sendto_one(sptr, rpl_str(RPL_STATSOLINE), me.name, sptr->name, "O", "*", tmp->nick, tmp->flags, tmp->class->name); } } break; } case 'P': /* Thanks goes to bamaboy for contributing this code. on 15/05/2005 * This will show the available ports on the ircd including ssl ports if any. * */ #ifdef STATS_P_ENABLED #ifdef STATS_P_OPERONLY if (IsAnOper(sptr)) show_ports(sptr); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); #else show_ports(sptr); #endif break; #endif case 'p': show_opers(sptr, parv[0]); break; case 'Q': if(IsAnOper(sptr)) { report_simbans_match_flags(sptr, SBAN_NICK|SBAN_LOCAL, 0); report_simbans_match_flags(sptr, SBAN_CHAN|SBAN_LOCAL, 0); } else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'q': if(IsAnOper(sptr)) { report_simbans_match_flags(sptr, SBAN_NICK|SBAN_NETWORK, 0); report_simbans_match_flags(sptr, SBAN_CHAN|SBAN_NETWORK, 0); } else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'R': case 'r': #ifdef DEBUGMODE send_usage(sptr, parv[0]); #endif break; case 'S': case 's': if (IsAnOper(sptr)) list_scache(cptr, sptr, parc, parv); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'T': if (IsAnOper(sptr)) throttle_stats(sptr, parv[0]); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 't': if (IsAnOper(sptr)) tstats(sptr, parv[0]); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'U': #ifdef HIDEULINEDSERVS if (!IsOper(sptr)) sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); else #endif { int i; for(i = 0; uservers[i]; i++) sendto_one(sptr, rpl_str(RPL_STATSULINE), me.name, sptr->name, "U", "*", uservers[i], 0, 0); } break; case 'u': { time_t now; now = timeofday - me.since; sendto_one(sptr, rpl_str(RPL_STATSUPTIME), me.name, parv[0], now / 86400, (now / 3600) % 24, (now / 60) % 60, now % 60); break; } case 'v': case 'V': show_servers(sptr, parv[0]); break; #ifdef DEBUGMODE case 'w': case 'W': if(IsAnOper(sptr)) report_fds(sptr); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; #endif case 'x': case 'X': if(IsAnOper(sptr)) report_userbans_match_flags(sptr, UBAN_SHUN, 0); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'Y': case 'y': { aClass *tmp; if(!classes) break; for(tmp = classes; tmp; tmp = tmp->next) sendto_one(sptr, rpl_str(RPL_STATSYLINE), me.name, sptr->name, 'Y', tmp->name, tmp->pingfreq, tmp->connfreq, tmp->ip24clones, tmp->maxlinks, tmp->maxsendq); break; } case 'Z': if (IsAnOper(sptr)) report_memory_usage(sptr, 1); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case 'z': if (IsAnOper(sptr)) report_memory_usage(sptr, 0); else sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); break; case '?': serv_info(sptr, parv[0]); break; default: stat = '*'; break; } sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, parv[0], stat); return 0; }