haussli / rancid

RANCiD
Other
114 stars 42 forks source link

Some update on IOS and NXOS modules #38

Open earendilfr opened 2 years ago

earendilfr commented 2 years ago

Some proposal on IOS and NXOS modules:

Only for IOS, add the possiblity to launch the following commands

DarkNinja77 commented 2 years ago

I also experimented with including CDP neighbor info and came up with this code. I spent some time on sorting the output to avoid oscillation. I also tried to mimic the way Cisco sorts "show int" outputs: G0/11 stands after G0/2, etc. My code skips reporting softphones because they tend to oscillate as well.

# This routine processes "show cdp neighbors detail"
sub ShowCDPNeighbors {
    my($INPUT, $OUTPUT, $cmd) = @_;

    my $neighbor = 0;
    my $deviceID = '';
    my $ipAddress = '';
    my $localInterface = '';
    my $remoteInterface = '';

    print STDERR "    In ShowCDPNeighbors $_" if ($debug);
    while (<$INPUT>) {
        tr/\015//d;
        next if (/^(\s*|\s*$cmd\s*)$/);
        next if (/^\s+\^$/);
        return(1) if (/Line has invalid autocommand /);
        return(1) if (/(invalid (input|command) detected|type help or )/i);
        return(-1) if (/command authorization failed/i);

        last if (/^% CDP is not enabled/);
        last if (/^Total cdp entries displayed\s+:\s+0$/);

        if (/^-------------------------$/ && $neighbor == 0) {
          $neighbor++;
          next;
        }
        if (/^Device ID: (.*)$/) {
          $deviceID = $1;
          #$deviceID =~ s/\..*//i; # remove domain from device ID
          next;
        }
        if (/^  IP address: (.*)$/ && $ipAddress eq '') {
          $ipAddress = $1;
          next;
        }
        if (/^Interface: (..)[^0-9]*(.*),  Port ID \(outgoing port\): (..)[^0-9]*(.*)$/) {
          $localInterface = $1 . $2;
          $remoteInterface = $3 . $4;
          next;
        }
        if (/^-------------------------$/ || /^$prompt/) {
          my $sort = $neighbor; # fallback to neighbor number if nothing else to sort by
          # Sort by local Interface
          ## First: sort by ASCII code of first letter in Port description
          if ($localInterface ne '') {
            $sort = ord($localInterface);
            ## Second: sort by concatenated number from all numbers of Port description with up to 2 leading zeros
            (my $portnum = $localInterface) =~ s/(\d+)/sprintf('%03u',$1)/eg;
            $portnum =~ s/[^0-9]//g;
            $sort = $sort * 1000000000 + $portnum;
          }
          ## Third: sort by remote neighbor IP address converted to decimal
          if ($ipAddress ne '') {
            (my $a = $ipAddress) =~ s/(\d+)/sprintf('%02x',$1)/eg;
            $a =~ s/\.//g;
            $sort = $sort * 4228250626 + hex($a);
          }

          $ipAddress = '<unknown IP>' if ($ipAddress eq '');
          $remoteInterface = '<unknown remote Interface>' if ($remoteInterface eq '');
          my $pad = ' ' x (11 - length($localInterface));
          if ($deviceID !~ m/^(SEP|IPC_|ATA)/) { # skip VoIP phones (hardphones + softphones) and ATAs
            ProcessHistory("CDP","keynsort","$sort","!CDP:   $localInterface$pad$deviceID ($ipAddress, $remoteInterface)\n");
          }
          $deviceID = $ipAddress = $localInterface = $remoteInterface = '';
          $neighbor++;
          last if (/^$prompt/);
          next;
        }
    }
    ProcessHistory("CDP","","","!\n") if ($neighbor > 0);
    return(0);
}