#!/usr/bin/perl -w # ########################################################################### # tntstat.pl # Version 1.0 # # Chris Adams # http://ro.com/~cadams/files/ # ########################################################################### # This program may be distributed under the terms of either the GNU # General Public License or the Artistic License, as specified in the # Perl README file. # ########################################################################### # # READ ALL OF THIS TO MAKE THIS PROGRAM WORK!! # -------------------------------------------- # # Requires the Perl SNMP module version 1.8 or higher (see # http://www.perl.com/CPAN/modules/by-module/SNMP/) and UCD SNMP # (ftp://ftp.ece.ucdavis.edu:/pub/snmp/). # # Queries one (or more) TNTs via SNMP to get connection information. # Usage: # pmstat.pl [-f] [-u ] [ ...] # -f run a little faster (no header or hostname lookups) # -u only show info for logins of this username # # You can specify as many TNT hostnames as you want, or none at all to get # the default list. # # Configuration: # -------------- # Change $MAXNAMELEN to the longest username you will be showing. # Longer usernames take away from hostname display. # # Change $MYDOMAIN below if you don't want to see your own domain name # in hostname lookups. # # Put hostnames in the @DEFAULT list so you don't have to specify them on # the command line. The list should look like # @DEFAULT = qw(tnt1 tnt2 tnt3); # ########################################################################### # VERSION HISTORY - you don't have to read this # # Version 1.0 - 1 July 1999 # - initial version # use integer; use SNMP; use Socket; use Getopt::Std; use POSIX; #use strict; #use diagnostics; ########################################################################### # User settable variables # use vars qw($MAXNAMELEN $MYDOMAIN @DEFAULT); $MAXNAMELEN = 16; $MYDOMAIN = ""; #$MYDOMAIN = "ro.com"; #@DEFAULT = qw(tnt1); ########################################################################### # Parse the options # $Getopt::Std::opt_u = ""; $Getopt::Std::opt_f = 0; getopts ('fu:'); use vars qw($getuser $fastrun); $getuser = $Getopt::Std::opt_u; $fastrun = $Getopt::Std::opt_f; ########################################################################### # Figure the column sizes # use vars qw($hostlen); $hostlen = 37 - $MAXNAMELEN; $MAXNAMELEN *= -1; $hostlen *= -1; ########################################################################### # SNMP initialization # $SNMP::use_long_names = 0; $SNMP::auto_init_mib = 0; ########################################################################### # Print the header # if (! $fastrun) { printf "%-${MAXNAMELEN}s %-${hostlen}s %-11s %-11s %-15s\n", "Username", "Hostname", "Start Time", "Spd In/Out", "Port"; print "-" x 78, "\n"; $MYDOMAIN =~ s/^([^\.])/.$1/; $MYDOMAIN = quotemeta ($MYDOMAIN); } ########################################################################### # For each host on the command line, get the stats. # if (@ARGV) { foreach my $tnt (@ARGV) { tntstat ($tnt); } } else { foreach my $tnt (@DEFAULT) { tntstat ($tnt); } } exit; ########################################################################### # The main function # sub tntstat { my ($tnt) = @_; ################################################################### # Open an SNMP session # my $sess = new SNMP::Session (DestHost => $tnt, Community => 'public') or die "can't open SNMP session: $!"; my $sess_err = \$sess->{ErrorStr}; my ($first, $len, $vars); ################################################################### # Get the uptime # $vars = new SNMP::VarList ( ['.1.3.6.1.2.1.1.3',0] # sysUpTime ); my ($uptime) = $sess->get ($vars); my $sys_start = time () - ($uptime / 100); ################################################################### # Get the active session list # $vars = new SNMP::VarList ( ['.1.3.6.1.4.1.529.12.3.1.2',0], # ssnActiveIndex ['.1.3.6.1.4.1.529.12.3.1.4',0], # ssnActiveUserName ['.1.3.6.1.4.1.529.12.3.1.5',0], # ssnActiveIPAddress ['.1.3.6.1.4.1.529.12.3.1.6',0] # ssnActiveSubnetMask ); $first = $vars->[0]->[0] . "."; $len = length ($first); my %sess = (); for (my ($ind, $user, $ip, $mask) = $sess->getnext ($vars); ($$sess_err eq "") && (substr ($vars->[0]->[0], 0, $len) eq $first); ($ind, $user, $ip, $mask) = $sess->getnext ($vars)) { next if ($user eq ""); next if ($getuser && ($user ne $getuser)); # Figure the netmask in bits if ($MASKS{$mask}) { $mask = $MASKS{$mask}; } else { my $n = 0; foreach my $byte (split (/\./, $mask)) { $n <<= 8; $n |= $byte; } my $m = 32; $m -- while (($n >>= 1) == 0); $MASKS{$mask} = $m; $mask = $m; } $sess{$ind}{user} = $user; $sess{$ind}{ip} = $ip; $sess{$ind}{mask} = $mask; } ################################################################### # Get the active call list # $vars = new SNMP::VarList ( ['.1.3.6.1.4.1.529.11.16.1.4',0], # callActiveStartingTimeStamp ['.1.3.6.1.4.1.529.11.16.1.5',0], # callActiveDataRate ['.1.3.6.1.4.1.529.11.16.1.6',0], # callActiveSlotNumber ['.1.3.6.1.4.1.529.11.16.1.7',0], # callActiveSlotLineNumber ['.1.3.6.1.4.1.529.11.16.1.8',0], # callActiveSlotChannelNumber ['.1.3.6.1.4.1.529.11.16.1.9',0], # callActiveModemSlotNumber ['.1.3.6.1.4.1.529.11.16.1.10',0], # callActiveModemOnSlot ['.1.3.6.1.4.1.529.11.16.1.12',0], # callActiveSessionIndex ['.1.3.6.1.4.1.529.11.16.1.14',0], # callActiveXmitRate ['.1.3.6.1.4.1.529.11.16.1.15',0] # callActivePortType ); $first = $vars->[0]->[0] . "."; $len = length ($first); for (my ($start, $rcv, $chslot, $chline, $chchan, $modslot, $modnum, $ind, $xmit, $type) = $sess->getnext ($vars); ($$sess_err eq "") && (substr ($vars->[0]->[0], 0, $len) eq $first); ($start, $rcv, $chslot, $chline, $chchan, $modslot, $modnum, $ind, $xmit, $type) = $sess->getnext ($vars)) { next if (! defined ($sess{$ind})); $sess{$ind}{start} = $start + $sys_start; $sess{$ind}{xmit} = $xmit; $sess{$ind}{rcv} = $rcv; $sess{$ind}{ch}{slot} = $chslot; $sess{$ind}{ch}{line} = $chline; $sess{$ind}{ch}{chan} = $chchan; $sess{$ind}{o} = ((($chslot * 1000) + $chline) * 1000) + $chchan; # $sess{$ind}{mod}{slot} = $modslot; # $sess{$ind}{mod}{num} = $modnum; } foreach my $ind (sort {$sess{$a}{o} <=> $sess{$b}{o}} keys %sess) { my $hostname = host_lookup ($sess{$ind}{ip}); my $mask = "/" . $sess{$ind}{mask}; $mask = "" if ($sess{$ind}{mask} == 33); $hostname .= $mask; my $start = strftime ("%m/%d %H:%M", localtime ($sess{$ind}{start})); $start =~ s!(^| )0!$1 !g; $start =~ s!/0(\d)!/$1 !; my $port = join ("/", (split (/\./, $tnt))[0], $sess{$ind}{ch}{slot}, $sess{$ind}{ch}{line}, $sess{$ind}{ch}{chan}); my $con_info; if (($sess{$ind}{rcv} == $sess{$ind}{xmit}) >= 56000) { $con_info = " " . $sess{$ind}{rcv} . " "; } else { $con_info = sprintf "%5s/%-5s", $sess{$ind}{rcv}, $sess{$ind}{xmit}; } printf "%-${MAXNAMELEN}s %-${hostlen}s %11s %11s %-15s\n", $sess{$ind}{user}, $hostname, $start, $con_info, $port; } } ########################################################################### # host_lookup - Lookup a hostname, either in the builtin cache or from # DNS (and then cache it) # sub host_lookup { my ($addr) = @_; ################################################################### # Initialize the cache to empty except for a telnet login # use vars qw(%host_hash); BEGIN { %host_hash = (); $host_hash{0} = "(telnet)"; } my $ret; if (defined ($host_hash{$addr})) { $ret = $host_hash{$addr}; } else { my $name = gethostbyaddr (inet_aton ($addr), AF_INET) if (! $fastrun); if ($name) { $ret = $name; } else { $ret = $addr; } $host_hash{$addr} = $ret; } $ret =~ s/$MYDOMAIN$//io; $ret = substr ($ret, 0, (-1 * $hostlen)); return ($ret); }