#!/usr/bin/perl
#
# This little script forces a bind stats dump, reads the stat info from
# named.stats and returns the results for mrtg
#
# Version: $Id: bindstats,v 1.6 2003/04/18 18:28:41 als Exp $
#
# Author: Alexander Schreiber <als@thangorodrim.de>
#
# note: works with BIND8 only

$STAT_FILE = '/var/cache/bind/named.stats';
$OLD_FILE = '/var/cache/bind/oldvalues';
$MEM_STATS = '/var/cache/bind/named.memstats';

$VALUE_1 = 'A queries';
$VALUE_2 = 'PTR queries';

$NDC = '/usr/sbin/ndc';

@OldStats;
@CurrentStats;
@Delta;
$Uptime;

use Sys::Syslog;

sub nuke_old_files {
# nuke the old files - simply to save diskspace

    unlink($STAT_FILE);
    unlink($MEM_STATS);

}


sub dump_bind_stats {
# dump bind stats using ndc

    system("$NDC stats 2> /dev/null > /dev/null");

}

sub get_old_values {
# get the old values 

    my $line;
    my $error = 0;

    open(OLD, "<$OLD_FILE") or $error = 1;
    unless ( $error ) {
        $line = <OLD>;
        $line =~ s/\n//;
        $OldStats[0] = $line;
        $line = <OLD>;
        $line =~ s/\n//;
        $OldStats[1] = $line;
    } else {
        @OldStats = (0, 0);
    }
    close(OLD);
}


sub get_new_values {
# get the new stat values from $STAT_FILE

    my $error = 0;
    my $line;
    my ($data, $junk);
    my $days, $hours, $min, $remainder;

    open(STAT, "<$STAT_FILE") or $error = 1;
    unless ( $error ) {
        while ( $line = <STAT> ) {
            $line =~ s/\n//;
            if ( $line =~ /\s+$VALUE_1$/ ) {
                ($data, $junk) = split(/\s+/, $line);
                $CurrentStats[0] = $data;
            }
            if ( $line =~ /\s+$VALUE_2$/ ) {
                ($data, $junk) = split(/\s+/, $line);
                $CurrentStats[1] = $data;
            }
            if ( $line =~ /^(\d+)\s+time since boot/ ) {
                $Uptime = $1;
            }
        }
    } else {
        $CurrentStats[0] = 0;
        $CurrentStats[1] = 0;
    }
    close(STAT);
    $days = $Uptime / 3600 / 24;
    $days =~ s/\..+$//; # ill and twisted, I know
    $Uptime = $Uptime % (3600 * 24);
    $hours = $Uptime / 3600;
    $hours =~ s/\..+$//; # ill and twisted, I know
    $Uptime = $Uptime % 3600;
    $min = $Uptime / 60;
    $min =~ s/\..+$//; # ill and twisted, I know

    $Uptime = sprintf("%d days, %02d:%02d", $days , $hours,$min);
}


sub compute_delta {
# computes the delta between old and new values, does sanity checking

    $Delta[0] = $CurrentStats[0] - $OldStats[0];
    $Delta[1] = $CurrentStats[1] - $OldStats[1];



    if ( $Delta[0] < 0 ) {   # shouldn't be negative, bind restart?
        $Delta[0] = $CurrentStats[0];  # should be correct
    }


    if ( $Delta[1] < 0 ) {   # shouldn't be negative, bind restart?
        $Delta[1] = $CurrentStats[1];  # should be correct
    }
}


sub update_old_values {
# updates the OLD file

    my $error = 0;

    open(OLD, ">$OLD_FILE") or $error = 1;
    unless ( $error ) {
        print OLD "$CurrentStats[0]\n";
        print OLD "$CurrentStats[1]\n";
    } else {
        syslog('warning', "cannot update OLD file");
    }
}


##MAIN##

openlog('bindstats', 'cons, pid', 'user');

&nuke_old_files();
&dump_bind_stats();
&get_old_values();
&get_new_values();
&compute_delta();
&update_old_values();

print "$Delta[0]\n";
print "$Delta[1]\n";
print "$Uptime\n";
print "bind\n";

closelog();

