- indentation
This commit is contained in:
parent
8ef5f2e9d2
commit
d94abab5ed
255
ifstatd.c
255
ifstatd.c
@ -52,28 +52,29 @@
|
||||
#define RESOLUTION 10
|
||||
|
||||
struct iftot {
|
||||
u_long ift_ip; /* input packets */
|
||||
u_long ift_ie; /* input errors */
|
||||
u_long ift_id; /* input drops */
|
||||
u_long ift_op; /* output packets */
|
||||
u_long ift_oe; /* output errors */
|
||||
u_long ift_od; /* output drops */
|
||||
u_long ift_co; /* collisions */
|
||||
u_long ift_ib; /* input bytes */
|
||||
u_long ift_ob; /* output bytes */
|
||||
u_long ift_ip; /* input packets */
|
||||
u_long ift_ie; /* input errors */
|
||||
u_long ift_id; /* input drops */
|
||||
u_long ift_op; /* output packets */
|
||||
u_long ift_oe; /* output errors */
|
||||
u_long ift_od; /* output drops */
|
||||
u_long ift_co; /* collisions */
|
||||
u_long ift_ib; /* input bytes */
|
||||
u_long ift_ob; /* output bytes */
|
||||
};
|
||||
|
||||
/* Globals */
|
||||
char *program_name = "ifstatd_";
|
||||
char *interface;
|
||||
char *pid_filename;
|
||||
char *cache_filename;
|
||||
struct pidfh *pfh;
|
||||
char *program_name = "ifstatd_";
|
||||
char *interface;
|
||||
char *pid_filename;
|
||||
char *cache_filename;
|
||||
struct pidfh *pfh;
|
||||
|
||||
/*
|
||||
* Prepare for a clean shutdown
|
||||
*/
|
||||
void daemon_shutdown()
|
||||
void
|
||||
daemon_shutdown()
|
||||
{
|
||||
pidfile_remove(pfh);
|
||||
}
|
||||
@ -81,95 +82,97 @@ void daemon_shutdown()
|
||||
/*
|
||||
* Act upon receiving signals
|
||||
*/
|
||||
void signal_handler(int sig)
|
||||
void
|
||||
signal_handler(int sig)
|
||||
{
|
||||
switch(sig) {
|
||||
switch (sig) {
|
||||
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
daemon_shutdown();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
daemon_shutdown();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain stats for interface(s).
|
||||
*/
|
||||
static void fill_iftot(struct iftot *st)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
bool found = false;
|
||||
|
||||
if (getifaddrs(&ifap) != 0)
|
||||
err(EX_OSERR, "getifaddrs");
|
||||
|
||||
bzero(st, sizeof(*st));
|
||||
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
if (interface) {
|
||||
if (strcmp(ifa->ifa_name, interface) == 0)
|
||||
found = true;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
st->ift_ip += IFA_STAT(ipackets);
|
||||
st->ift_ib += IFA_STAT(ibytes);
|
||||
st->ift_op += IFA_STAT(opackets);
|
||||
st->ift_ob += IFA_STAT(obytes);
|
||||
}
|
||||
static void
|
||||
fill_iftot(struct iftot *st)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
bool found = false;
|
||||
|
||||
if (interface && found == false)
|
||||
err(EX_DATAERR, "interface %s not found", interface);
|
||||
if (getifaddrs(&ifap) != 0)
|
||||
err(EX_OSERR, "getifaddrs");
|
||||
|
||||
freeifaddrs(ifap);
|
||||
bzero(st, sizeof(*st));
|
||||
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
if (interface) {
|
||||
if (strcmp(ifa->ifa_name, interface) == 0)
|
||||
found = true;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
st->ift_ip += IFA_STAT(ipackets);
|
||||
st->ift_ib += IFA_STAT(ibytes);
|
||||
st->ift_op += IFA_STAT(opackets);
|
||||
st->ift_ob += IFA_STAT(obytes);
|
||||
}
|
||||
|
||||
if (interface && found == false)
|
||||
err(EX_DATAERR, "interface %s not found", interface);
|
||||
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out munin plugin configuration
|
||||
*/
|
||||
int config(char *iface)
|
||||
int
|
||||
config(char *iface)
|
||||
{
|
||||
printf(
|
||||
"graph_order rbytes obytes\n"
|
||||
"graph_title %s Interface (%d seconds sampling)\n"
|
||||
"graph_category network\n"
|
||||
"graph_vlabel bits per second\n"
|
||||
"update_rate %d\n"
|
||||
"graph_data_size custom 1d, %ds for 1w, 1m for 1t, 5m for 1y\n"
|
||||
"rbytes.label received\n"
|
||||
"rbytes.type DERIVE\n"
|
||||
"rbytes.graph no\n"
|
||||
"rbytes.cdef rbytes,8,*\n"
|
||||
"rbytes.min 0\n"
|
||||
"obytes.label bps\n"
|
||||
"obytes.type DERIVE\n"
|
||||
"obytes.negative rbytes\n"
|
||||
"obytes.cdef obytes,8,*\n"
|
||||
"obytes.min 0\n"
|
||||
"obytes.draw AREA\n"
|
||||
,iface,RESOLUTION,RESOLUTION,RESOLUTION
|
||||
);
|
||||
printf("graph_order rbytes obytes\n"
|
||||
"graph_title %s Interface (%d seconds sampling)\n"
|
||||
"graph_category network\n"
|
||||
"graph_vlabel bits per second\n"
|
||||
"update_rate %d\n"
|
||||
"graph_data_size custom 1d, %ds for 1w, 1m for 1t, 5m for 1y\n"
|
||||
"rbytes.label received\n"
|
||||
"rbytes.type DERIVE\n"
|
||||
"rbytes.graph no\n"
|
||||
"rbytes.cdef rbytes,8,*\n"
|
||||
"rbytes.min 0\n"
|
||||
"obytes.label bps\n"
|
||||
"obytes.type DERIVE\n"
|
||||
"obytes.negative rbytes\n"
|
||||
"obytes.cdef obytes,8,*\n"
|
||||
"obytes.min 0\n"
|
||||
"obytes.draw AREA\n", iface, RESOLUTION, RESOLUTION, RESOLUTION);
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for a certain amount of time
|
||||
*/
|
||||
time_t wait_for(int seconds) {
|
||||
time_t
|
||||
wait_for(int seconds)
|
||||
{
|
||||
|
||||
struct timespec tp;
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
|
||||
time_t current_epoch = tp.tv_sec;
|
||||
long nsec_to_sleep = 1000*1000*1000 - tp.tv_nsec;
|
||||
time_t current_epoch = tp.tv_sec;
|
||||
long nsec_to_sleep = 1000 * 1000 * 1000 - tp.tv_nsec;
|
||||
|
||||
/* Only sleep if needed */
|
||||
if (nsec_to_sleep > 0) {
|
||||
@ -184,24 +187,24 @@ time_t wait_for(int seconds) {
|
||||
/*
|
||||
* Daemonize and persist pid
|
||||
*/
|
||||
int daemon_start()
|
||||
int
|
||||
daemon_start()
|
||||
{
|
||||
struct iftot ift, *tot;
|
||||
time_t epoch;
|
||||
struct iftot ift, *tot;
|
||||
time_t epoch;
|
||||
struct sigaction sig_action;
|
||||
sigset_t sig_set;
|
||||
pid_t otherpid;
|
||||
sigset_t sig_set;
|
||||
pid_t otherpid;
|
||||
|
||||
tot = &ift;
|
||||
|
||||
char* no_fork = getenv("no_fork");
|
||||
if (! no_fork || strcmp("1", no_fork)) {
|
||||
char *no_fork = getenv("no_fork");
|
||||
if (!no_fork || strcmp("1", no_fork)) {
|
||||
|
||||
/* Check if parent process id is set */
|
||||
if (getppid() == 1)
|
||||
{
|
||||
if (getppid() == 1) {
|
||||
/* PPID exists, therefore we are already a daemon */
|
||||
return(EXIT_FAILURE);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Check if we can acquire the pid file */
|
||||
@ -209,15 +212,16 @@ int daemon_start()
|
||||
|
||||
if (pfh == NULL) {
|
||||
if (errno == EEXIST) {
|
||||
errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", (intmax_t)otherpid);
|
||||
errx(EXIT_FAILURE,
|
||||
"Daemon already running, pid: %jd.",
|
||||
(intmax_t) otherpid);
|
||||
}
|
||||
warn("Cannot open or create pidfile: %s", pid_filename);
|
||||
}
|
||||
|
||||
/* fork ourselves if not asked otherwise */
|
||||
if (fork())
|
||||
{
|
||||
return(EXIT_SUCCESS);
|
||||
if (fork()) {
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* we are the child, complete the daemonization */
|
||||
@ -229,11 +233,13 @@ int daemon_start()
|
||||
|
||||
/* Block unnecessary signals */
|
||||
sigemptyset(&sig_set);
|
||||
sigaddset(&sig_set, SIGCHLD); /* ignore child - i.e. we don't need to wait for it */
|
||||
sigaddset(&sig_set, SIGTSTP); /* ignore Tty stop signals */
|
||||
sigaddset(&sig_set, SIGTTOU); /* ignore Tty background writes */
|
||||
sigaddset(&sig_set, SIGTTIN); /* ignore Tty background reads */
|
||||
sigprocmask(SIG_BLOCK, &sig_set, NULL); /* Block the above specified signals */
|
||||
sigaddset(&sig_set, SIGCHLD); /* ignore child - i.e. we don't need
|
||||
* to wait for it */
|
||||
sigaddset(&sig_set, SIGTSTP); /* ignore Tty stop signals */
|
||||
sigaddset(&sig_set, SIGTTOU); /* ignore Tty background writes */
|
||||
sigaddset(&sig_set, SIGTTIN); /* ignore Tty background reads */
|
||||
sigprocmask(SIG_BLOCK, &sig_set, NULL); /* Block the above specified
|
||||
* signals */
|
||||
|
||||
/* Catch necessary signals */
|
||||
sig_action.sa_handler = signal_handler;
|
||||
@ -246,42 +252,44 @@ int daemon_start()
|
||||
|
||||
/* create new session and process group */
|
||||
setsid();
|
||||
|
||||
|
||||
/* persist pid */
|
||||
pidfile_write(pfh);
|
||||
|
||||
}
|
||||
|
||||
FILE *cache_file = fopen(cache_filename, "a");
|
||||
FILE *cache_file = fopen(cache_filename, "a");
|
||||
|
||||
/* looping to collect traffic stat every RESOLUTION seconds */
|
||||
while(1) {
|
||||
while (1) {
|
||||
|
||||
epoch=wait_for(RESOLUTION);
|
||||
epoch = wait_for(RESOLUTION);
|
||||
|
||||
flockfile(cache_file);
|
||||
|
||||
fill_iftot(tot);
|
||||
fprintf(cache_file, "obytes.value %ld:%lu\nrbytes.value %ld:%lu\n", epoch, tot->ift_ob, epoch, tot->ift_ib);
|
||||
fprintf(cache_file, "obytes.value %ld:%lu\nrbytes.value %ld:%lu\n",
|
||||
epoch, tot->ift_ob, epoch, tot->ift_ib);
|
||||
fflush(cache_file);
|
||||
|
||||
funlockfile(cache_file);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(cache_file);
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int fetch()
|
||||
int
|
||||
fetch()
|
||||
{
|
||||
/* this should return data from cache file */
|
||||
FILE* cache_file = fopen(cache_filename, "r+");
|
||||
FILE *cache_file = fopen(cache_filename, "r+");
|
||||
|
||||
/* lock */
|
||||
flockfile(cache_file);
|
||||
|
||||
/* cat the cache_file to stdout */
|
||||
char buffer[1024];
|
||||
char buffer[1024];
|
||||
while (fgets(buffer, 1024, cache_file)) {
|
||||
printf("%s", buffer);
|
||||
}
|
||||
@ -289,46 +297,47 @@ int fetch()
|
||||
ftruncate(fileno(cache_file), 0);
|
||||
fclose(cache_file);
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argv[0] && argv[0][0])
|
||||
program_name = argv[0];
|
||||
|
||||
/* figure out program name */
|
||||
while (strchr(program_name, '/')) {
|
||||
program_name=strchr(program_name, '/')+1;
|
||||
}
|
||||
|
||||
/* extract interface name from plugin name */
|
||||
if (strchr(program_name,'_')) {
|
||||
interface=strchr(program_name,'_')+1;
|
||||
program_name = strchr(program_name, '/') + 1;
|
||||
}
|
||||
|
||||
/* program should always run with a valid
|
||||
executable name */
|
||||
/* extract interface name from plugin name */
|
||||
if (strchr(program_name, '_')) {
|
||||
interface = strchr(program_name, '_') + 1;
|
||||
}
|
||||
|
||||
/* program should always run with a valid executable name */
|
||||
if (strlen(interface) < 1) {
|
||||
errx(EX_USAGE, "Please run from symlink");
|
||||
}
|
||||
|
||||
/* resolve paths */
|
||||
char *MUNIN_PLUGSTATE = getenv("MUNIN_PLUGSTATE");
|
||||
char *MUNIN_PLUGSTATE = getenv("MUNIN_PLUGSTATE");
|
||||
|
||||
/* Default is current directory */
|
||||
if (!MUNIN_PLUGSTATE) MUNIN_PLUGSTATE = ".";
|
||||
if (!MUNIN_PLUGSTATE)
|
||||
MUNIN_PLUGSTATE = ".";
|
||||
|
||||
asprintf(&pid_filename, "%s/%s.pid", MUNIN_PLUGSTATE, program_name);
|
||||
asprintf(&pid_filename, "%s/%s.pid", MUNIN_PLUGSTATE, program_name);
|
||||
asprintf(&cache_filename, "%s/%s.value", MUNIN_PLUGSTATE, program_name);
|
||||
|
||||
if (argc > 1) {
|
||||
char* first_arg = argv[1];
|
||||
if (! strcmp(first_arg, "config")) {
|
||||
char *first_arg = argv[1];
|
||||
if (!strcmp(first_arg, "config")) {
|
||||
return config(interface);
|
||||
}
|
||||
|
||||
if (! strcmp(first_arg, "acquire")) {
|
||||
if (!strcmp(first_arg, "acquire")) {
|
||||
return daemon_start();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user