/* 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 <sys/stat.h>
#include <utmp.h>
#include <fcntl.h>
#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 <sys/time.h>
#include <sys/resource.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1