Category: Network Management
Author/Contact Info andreas lamprechtandreas.a.lamprecht@siemens.com
Description: Looked for a tool to get a picture of my network, found cdppoll.pl, written by fingers, did a little bit of improvement and it works like a charm. Especially the csv-import into Visio is a real eye-opener. Thanks very much to fingers for this fantastic idea! Ah, yes: It works maybe only for Cisco-devices ... And of course, there could be a lot of command-line switches to control the behaviour. Maybe i have time one day ...
#!/usr/bin/perl -w
# cdppoll.pl
use strict;
no strict "subs";

use Net::SNMP;

# Oid for SysName
my($sysNameOID) = '1.3.6.1.2.1.1.5.0';
# Starting Oid for InterfaceName
my($interfaceNameOID) = '1.3.6.1.2.1.31.1.1.1.1';
# Starting OID for the whole CDP-Mib
my($cdp_mibOID) = "1.3.6.1.4.1.9.9.23.1.2.1.1";
# Starting OID for Interfaces to neighbors
my($cdp_mib_ifIndexesOID) = "$cdp_mibOID.3";

my($tmp,$sysName,%systems);

# Regex for interesting IP-Adresses
my($interesting) = "^192\.168\.198\.";

# should normal output be done?
my($putout) = 0;

# print some additional things that might be interesting
my($debug) = 0;

# write csv-File for Visio?
my($visio) = 1;

# All the used variables
my($error,$session,$community,$hostip,$i,$ipOID,$nameOID,$typeOID,$rpo
+rtOID,$lportOID);
my($ifIndex,$ifNIndex,$sys,$link,$fromlink,$tolink,$linktext,$linkdesc
+);
my(@todo,@ifIndexes,@ifNIndexes,@links);
my(%sortedlinks);

# Special trick to get a self-increasing variable
my($getnextid);
tie $getnextid, GetNextID;


#We need a startin point, get an IP from command line
die "usage: $0 seedip" unless ( @ARGV == 1 && $ARGV[0] =~ m{\d+\.\d+\.
+\d+\.\d+});
push(@todo, $ARGV[0]);


#Prompt for SNMP community string
print STDERR "community: ";
chomp($community = <STDIN>);

while(@todo){ #Grab a target and go to work

   $hostip= shift(@todo);

   next if($hostip !~ m!$interesting!);

   print STDERR "\ntrying host $hostip ...\n" if($debug);

   #Open SNMP session
   ($session,$error) = Net::SNMP->session(-hostname => $hostip, -commu
+nity => $community);
   return unless($session);

   # Ask for sysName
   $tmp = $session->get_request( -varbindlist => [$sysNameOID] );

   next if(! $tmp); # Cannot ask for sysName, seems to be down/unreach
+able

   $sysName = $tmp->{$sysNameOID};

   next if($systems{$sysName}->{"seen"}); # seen already

   $systems{$sysName}->{"hostip"} = $hostip if(!$systems{$sysName}->{"
+hostip"});
   $systems{$sysName}->{"id"} = $getnextid if(!$systems{$sysName}->{"i
+d"});
   $systems{$sysName}->{"seen"} = 1;

   # Get list of Interfaces with neighbors
   undef(@ifIndexes);
   $tmp = $session->get_table(-baseoid => $cdp_mib_ifIndexesOID);

   # split the interface-OIDs into two arrays (should be fixed ...)
   foreach $i (keys(%$tmp)) {
     $i =~ m!$cdp_mib_ifIndexesOID\.(([0-9]+)\.[0-9]+)!;
     push(@ifIndexes, $2);
     push(@ifNIndexes, $1);
   }

  # Are there any neighbors?
  if(@ifIndexes) {

    print "Neighbors of $sysName:\n" if($putout);
    printf("%-13s %-30s %-30s %-15s\n", "LocalPort", "RemotePort", "Re
+moteName", "RemoteIP") if($putout);
    while(@ifIndexes) {
      $ifIndex = shift(@ifIndexes);
      $ifNIndex = shift(@ifNIndexes);

      $ipOID    = "$cdp_mibOID.4.$ifNIndex";
      $nameOID  = "$cdp_mibOID.6.$ifNIndex";
      $rportOID  = "$cdp_mibOID.7.$ifNIndex";
      $typeOID  = "$cdp_mibOID.8.$ifNIndex";
      $lportOID = "$interfaceNameOID.$ifIndex";

      $session->debug(0x10) if($debug);
      $tmp = $session->get_request(-varbindlist => [$ipOID, $nameOID, 
+$rportOID, $typeOID, $lportOID] );

      next if(!$tmp);

      # Change FastEthernet and GigabitEthernet to shorter names
      $tmp->{$rportOID} =~ s/FastEthernet/Fa/i;
      $tmp->{$rportOID} =~ s/GigabitEthernet/Gi/i;
      $tmp->{$lportOID} =~ s/FastEthernet/Fa/i;
      $tmp->{$lportOID} =~ s/GigabitEthernet/Gi/i;

      if($tmp->{$nameOID} =~ m!\(([^\)]+)\)!) {
        $tmp->{$nameOID} = $1;
      }

      # Build remote host structure if not already done
      if(! $systems{ $tmp->{$nameOID} } ) {
        $systems{ $tmp->{$nameOID} }->{"hostip"} = Convert_IP($tmp->{$
+ipOID});
        $systems{ $tmp->{$nameOID} }->{"id"}   = $getnextid;
      }
      # Build link
      push(@links, [ $sysName,
                     $tmp->{$nameOID},
                     $systems{$sysName}->{"id"},
                     $systems{ $tmp->{$nameOID} }->{"id"},
                     $tmp->{$lportOID},
                     $tmp->{$rportOID}
                   ] );

      printf("%-13s %-30s %-30s %-15s\n",
                $tmp->{$lportOID},
                $tmp->{$rportOID},
                $tmp->{$nameOID},
                Convert_IP($tmp->{$ipOID})
      ) if($putout);

      push(@todo, Convert_IP($tmp->{$ipOID}) );

    } # while(@ifIndexes)
  } # if(@ifIndexes)

  $session->close;
}

# Generate output for Visio      
if($visio) {
  print "; Network connections\n";
  print "Template, \"Audit Diagram.vst\"\n";
  print "\n";

  print "; Systems:\n";

  foreach $sys (keys(%systems)) {
    print "; $sys: IP=";
    print "$systems{$sys}->{hostip}, ID=$systems{$sys}->{id}\n";
    printf("Shape,\"%s\",\"Ereignis\",\"%s\",,,,,,,\n", $systems{$sys}
+->{id}, "$sys - $systems{$sys}->{hostip}");
  }

  print "\n; Links:\n";
  foreach $link (@links) {

    if(${$link}[2] < ${$link}[3] ) {
      $linkdesc = "${$link}[0] (${$link}[4]) -> ${$link}[1] (${$link}[
+5])";
      $fromlink = ${$link}[2]; $tolink = ${$link}[3];
      $linktext = "${$link}[4] -> ${$link}[5]"
    } else {
      $linkdesc = "${$link}[1] (${$link}[5]) -> ${$link}[0] (${$link}[
+4])";
      $fromlink = ${$link}[3]; $tolink = ${$link}[2];
      $linktext = "${$link}[5] -> ${$link}[4]"
    }

    if(! $sortedlinks{$linkdesc} ) {
      $sortedlinks{$linkdesc} ++;
      printf("Link,,\"Dynamischer Verbinder\",\"%s\",\"%s\",\"%s\"\n",
+$linktext,$fromlink,$tolink);
    }
  }
}


##### End Of Main #####


sub Convert_IP{ #This sub converts a hex IP to standard xxx.xxx.xxx.xx
+x format

  if( $_[0] !~ m!^0x(..)(..)(..)(..)!) {
    return "0.0.0.0";
  }

  return sprintf("%s.%s.%s.%s", hex($1), hex($2), hex($3), hex($4) );

}

# Special trick to get a self-increasing var
package GetNextID;
sub TIESCALAR {
  my $class = $_[0];
  my $value = $_[1] || 0;
  # Leerzeichen weg
  $value =~ s/^\s*(.*?)\s*$/$1/;
  return bless \$value, $class;
}
sub FETCH {
  my $self = shift;
  $$self ++;
  return $$self;
}
sub STORE {
  my $self = shift;
  $$self = shift || 0;
  # Leerzeichen weg
  $$self =~ s/^\s*(.*?)\s*$/$1/;
}
Replies are listed 'Best First'.
Re: cdppoll.pl
by Aristotle (Chancellor) on Nov 21, 2003 at 15:14 UTC