/* vim: set shiftwidth=3 softtabstop=3 expandtab: */
/*
Copyright (C) 2002 Erik Fears
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
of the License, 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.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
*/
#include "setup.h"
#include <stdio.h>
#include <unistd.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#if HAVE_STRING_H
# include <string.h>
#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/resource.h> /* getrlimit */
#include <errno.h>
#include "irc.h"
#include "log.h"
#include "misc.h"
#include "stats.h"
#include "config.h"
#include "extern.h"
#include "opercmd.h"
#include "scan.h"
#include "stats.h"
#include "libopm/src/opm_types.h"
static time_t STATS_UPTIME;
static unsigned int STATS_CONNECTIONS;
static unsigned int STATS_DNSBLSENT;
static struct StatsHash STATS_PROXIES[] =
{
{OPM_TYPE_HTTP, 0, "HTTP" },
{OPM_TYPE_HTTPPOST, 0, "HTTPPOST" },
{OPM_TYPE_SOCKS4, 0, "SOCKS4" },
{OPM_TYPE_SOCKS5, 0, "SOCKS5" },
{OPM_TYPE_ROUTER, 0, "ROUTER" },
{OPM_TYPE_WINGATE, 0, "WINGATE" }
};
/* stats_init
*
* Perform initialization of bopm stats
*
* Parameters: NONE
* Return: NONE
*
*/
void stats_init(void)
{
time(&STATS_UPTIME);
}
/* stats_openproxy
*
* Record open proxy.
*
*
* Parameters: NONE
* Return: NONE
*
*/
void stats_openproxy(int type)
{
unsigned int i;
for(i = 0; i < (sizeof(STATS_PROXIES) / sizeof(struct StatsHash)); i++)
if(STATS_PROXIES[i].type == type)
STATS_PROXIES[i].count++;
}
/* stats_connect
*
* Record IRC connect.
*
*
* Parameters: NONE
* Return: NONE
*
*/
void stats_connect(void)
{
STATS_CONNECTIONS++;
}
/* stats_dnsblrecv
*
* Record that a user was found in the blacklist.
*
* Parameters: BlacklistConf structure
* Return: NONE
*
*/
void stats_dnsblrecv(struct BlacklistConf *bl)
{
bl->stats_recv++;
}
/* stats_dnsblsend
*
* Record a sent report
*
* Parameters: NONE
* Return: NONE
*
*/
void stats_dnsblsend(void)
{
STATS_DNSBLSENT++;
}
/* stats_output
*
* Output stats to target via privmsg
*
*
* Parameters: NONE
* Return: NONE
*
*/
void stats_output(char *target)
{
unsigned int i;
time_t present;
time_t uptime;
node_t *p;
struct BlacklistConf *bl;
time(&present);
uptime = present - STATS_UPTIME;
irc_send("PRIVMSG %s :Uptime: %s", target, dissect_time(uptime));
LIST_FOREACH(p, OpmItem->blacklists->head)
{
bl = p->data;
if(bl->stats_recv > 0)
{
irc_send("PRIVMSG %s :DNSBL: %u successful lookups from %s",
target, bl->stats_recv, bl->name);
}
}
if(STATS_DNSBLSENT > 0)
{
irc_send("PRIVMSG %s :DNSBL: %u reports sent", target,
STATS_DNSBLSENT);
}
for(i = 0; i < (sizeof(STATS_PROXIES) / sizeof(struct StatsHash)); i++)
{
if(STATS_PROXIES[i].count > 0)
{
irc_send("PRIVMSG %s :Found %u (%s) open.", target,
STATS_PROXIES[i].count, STATS_PROXIES[i].name);
}
}
irc_send("PRIVMSG %s :Number of connects: %u (%.2f/minute)",
target, STATS_CONNECTIONS, STATS_CONNECTIONS ?
(float)STATS_CONNECTIONS / ((float)uptime / 60.0) : 0.0);
}
/* fdstats_output
*
* Output file descriptor stats to target via privmsg
*
*
* Parameters: NONE
* Return: NONE
*
*/
void fdstats_output(char *target)
{
struct rlimit rlim;
unsigned total_fd_use, i;
int newfd;
/* Get file descriptor ceiling */
if(getrlimit(RLIMIT_NOFILE, &rlim) == -1)
{
log_printf("FDSTAT -> getrlimit() error retrieving RLIMIT_NOFILE (%s)", strerror(errno));
irc_send("PRIVMSG %s :FDSTAT -> getrlimit() error retrieving RLIMIT_NOFILE (%s)",
target, strerror(errno));
return;
}
/*
* Check which file descriptors are active, based on suggestions from:
* http://groups.google.com/groups?th=a48b9fe8ca43947c&rnum=1
*/
total_fd_use = 0;
for(i = 0; i < rlim.rlim_cur; i++)
{
newfd = dup(i);
if(newfd > 0) {
total_fd_use++;
close(newfd);
}
else
{
switch (errno)
{
case EMFILE:
/*
* We ran out of FDs whilst trying to dup an existing one,
* so all fds are open and we can stop checking here.
*/
i = total_fd_use = rlim.rlim_cur;
break;
case EBADF:
/* Not an FD in use. */
break;
case EINTR:
/* Try again. */
i--;
break;
default:
/* We don't expect any other errors. */
log_printf("fd %u errno = %u (%s)", i, errno, strerror(errno));
break;
}
}
}
irc_send("PRIVMSG %s :Total open FD: %u/%d", target, total_fd_use, rlim.rlim_cur);
}
syntax highlighted by Code2HTML, v. 0.9.1