# Add in extended interface stats
#
#
# Set name of Module, and the OID to check to run this module
#
$MODULENAME = "ExtendedIf";
$VERSION = '0.1';

# Module requires a subroutine called process_module_$MODULENAME to exist.
#
sub process_module_ExtendedIf($$$);

#
# Local sub-routines
#
sub add_extended($$);

# We check for interfaces.ifTable.ifEntry.ifIndex.1
$MIB_TO_CHECK = ".1.3.6.1.2.1.2.2.1.1.1";


# Set this so it's in the main hash
$main::snmp_modules{$MODULENAME} = $MIB_TO_CHECK;


$main::table_map{'MIBII-netpktNU'} = [ qw(ifInNUcastPkts ifOutNUcastPkts) ];
$main::table_options{'MIBII-netpktNU'} = [ qw(factor=1 units=pkts/s) ];

$main::table_map{'MIBII-discards'} = [ qw(ifInDiscards ifOutDiscards) ];
$main::table_options{'MIBII-discards'} = [ qw(factor=1 units=pkts impulses=on) ];

$main::table_map{'MIBII-errors'} = [ qw(ifInErrors ifOutErrors) ];
$main::table_options{'MIBII-errors'} = [ qw(factor=1 units=pkts impulses=on) ];

#
# Local vars
#
%mibs_of_interest_extif= (
	"ifInNUcastPkts" => ".1.3.6.1.2.1.2.2.1.12.",
	"ifOutNUcastPkts" => ".1.3.6.1.2.1.2.2.1.18.",
	"ifInDiscards"   => ".1.3.6.1.2.1.2.2.1.13.",
	"ifOutDiscards"  => ".1.3.6.1.2.1.2.2.1.19.",
	"ifInErrors"     => ".1.3.6.1.2.1.2.2.1.14.",
	"ifOutErrors"    => ".1.3.6.1.2.1.2.2.1.20."
);

$normal_extif = [
	[ 1, 3, 6, 1, 2, 1, 2,  2, 1, 1 ],        # ifIndex
	[ 1, 3, 6, 1, 2, 1, 2,  2, 1, 2 ],        # ifDescr
	[ 1, 3, 6, 1, 2, 1, 2,  2, 1, 5 ],        # ifSpeed
	[ 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 18 ],    # ifAlias
	[ 1, 3, 6, 1, 2, 1, 2,  2, 1, 7 ],        # ifAdminStatus
	[ 1, 3, 6, 1, 2, 1, 2,  2, 1, 8 ]         # ifOperStatus
];

$catalyst_extif = [
    [ 1, 3, 6, 1, 2, 1, 2,  2, 1, 1 ],             # ifIndex
    [ 1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 1 ],          # ifXEntry.ifName
    [ 1, 3, 6, 1, 2, 1, 2,  2, 1, 5 ],             # ifSpeed
    [ 1, 3, 6, 1, 4, 1, 9,  5, 1, 4, 1, 1, 4 ],    # CiscoCatalystPortName
    [ 1, 3, 6, 1, 2, 1, 2,  2, 1, 7 ],             # ifAdminStatus
    [ 1, 3, 6, 1, 2, 1, 2,  2, 1, 8 ]              # ifOperStatus
];



sub process_module_ExtendedIf($$$) {
	my ($router,$community,$sess) = @_;

	debug("$router supports Extended Interfaces");

	if ( $system eq "Catalyst" ) {
            $sess->map_table( $catalyst_extif, \&process_ext );
        }
        else {
            $sess->map_table( $normal_extif, \&process_ext );
        }


	return 1;
}

sub process_ext() {
    my $reserved = 0;
    my ($rowindex, $index, $ifdescr, $ifspeed, $ifalias,
        $ifadminstatus, $ifoperstatus ) = @_;
    grep ( defined $_ && ( $_ = pretty_print $_),
      ( $index, $ifdescr, $ifspeed, $ifalias, $ifadminstatus, $ifoperstatus ) );

    # Compaq likes to put a null at the end....
    $ifdescr =~ s/\x00//g;
    $bits = 32;

    # Check for "reserved" interfaces, i.e. those we don't want to 
    # include in RTG
    foreach $resv (@reserved) {
        if ( $ifdescr =~ /$resv/ ) {
            $reserved = 1;
        }
    }
    if ($ifdescr) {
        if ( $system eq "Catalyst" ) {
            if ( $ifdescr =~ /(\d+)\/(\d+)/ ) {
                $catalystoid = ".1.3.6.1.4.1.9.5.1.4.1.1.4.".$1.".". $2;
		$SNMP_Session::suppress_warnings=2;
                @result = snmpget( "$communities{$router}\@$router", "$catalystoid" );
		$SNMP_Session::suppress_warnings=0;
                $ifalias = join ( ' ', @result );
            }
        }
        if ( $ifadminstatus == 1 && $ifoperstatus == 1 && $reserved == 0 ) {
            if ( !$DBOFF ) {
                $iid = &find_interface_id( $rid, $ifdescr, $ifalias, $ifspeed );
            }
            foreach $mib ( keys %mibs_of_interest_extif ) {

		if ( !$DBOFF ) {	
			$sql = "SHOW TABLE STATUS LIKE '$mib"."_$rid'";
			my $sth = $dbh->prepare($sql)
				or die "Can't prepare $sql: $dbh->errstr\n";
			my $rv = $sth->execute
				or die "can't execute the query: $sth->errstr\n";

			if ( $sth->rows == 0 ) {
				$sql = "CREATE TABLE $mib"."_$rid (id INT NOT NULL, dtime DATETIME NOT NULL, counter BIGINT NOT NULL, KEY $mib"."_$rid". "_idx (dtime))";
				&sql_insert($sql);
			}
		}
	
		# we want to make sure the device supports the requested stat, not all do
		$SNMP_Session::suppress_warnings=2;
		@result = snmpget ("$communities{$router}\@$router", "$mibs_of_interest_extif{$mib}$index");
		$SNMP_Session::suppress_warnings=0;

		if(defined $result[0]) {
	                ($a,$a,$a,$a,@addrs) = gethostbyname($router);
			printf CFG "%d.%d.%d.%d\t", unpack('C4',$addrs[0]);
			print CFG "$mibs_of_interest_extif{$mib}$index\t";
			print CFG "$bits\t";
			print CFG "$communities{$router}\t";
			print CFG "$mib" . "_$rid\t";
			print CFG "$iid\t";
			print CFG "$ifalias ($ifdescr)\n";
		}
            }
        }
        else {
            if ($DEBUG) {
		$debug_line = "Ignoring $router $ifalias ($ifdescr) ";
                $debug_line .= "[admin = up] "     if $ifadminstatus == 1;
                $debug_line .= "[admin = down] "   if $ifadminstatus != 1;
                $debug_line .= "[oper = up] "      if $ifoperstatus == 1;
                $debug_line .= "[oper = down] "    if $ifoperstatus != 1;
                $debug_line .= "[reserved = yes] " if $reserved == 1;
                $debug_line .= "[reserved = no] "  if $reserved != 1;
		debug($debug_line);
            }
        }
    }
}


# have to end with a 1
1;

