#cccp - Cisco Console Command Parser #A utility for batch processing of IOS commands. #Meant to work with Cisco Catalyst Express 500 series switches. #version 0.003 #Cedric Nelson, January 2008 use WWW::Mechanize; use Crypt::SSLeay; #use strict; #use diagnostics; my ($realm, $url, $default_username, $default_password, $flags, $dirty, @commands, @switches, $username, $password, $protocol, $port, $mode, $verbosity); $realm = 'level_15_access'; $url = '/ios_web_exec/commandset'; $default_username = ''; $default_password = ''; $dirty = 0; #NOTE: MODE 0 IS EXEC, MODE 1 IS CONFIG $mode = 0; $verbosity = 'default'; #Parse invokation options. if (@ARGV) { $flags = analyze_options(@ARGV); foreach my $flag (keys %{$flags}) { if ($flag !~ /^-([cseupiqh])$/) { print "Unrecognized option: $flag\n\n"; $dirty = 1; } } if ($dirty == 1) {show_help();} else { if (${$flags}{'-h'}) {show_help();} if (${$flags}{'-q'}) {$verbosity = 'quiet';} if (${$flags}{'-c'}) { foreach my $item (@{${$flags}{'-c'}}) { if (-e $item) {push @commands, parse_files_macro($item);} else {push @commands, $item;} } } if (${$flags}{'-s'}) { foreach my $item (@{${$flags}{'-s'}}) { if (-e $item) {push @switches, parse_files_macro($item);} else {push @switches, $item;} } } if (${$flags}{'-e'}) {$port = '443';$protocol = 'https';} else {$port = '80';$protocol = 'http';} if (${$flags}{'-u'}) {$username = @{${$flags}{'-u'}}[0];} if (${$flags}{'-p'}) {$password = @{${$flags}{'-p'}}[0];} unless (${$flags}{'-u'}) {$username = $default_username;} unless (${$flags}{'-p'}) {$password = $default_password;} if (${$flags}{'-c'}) { my @input = parse_commands(@commands); my $count = @switches; foreach my $ip (@switches) { print ">>Output for switch ($ip):\n" if ($count > 1); foreach my $input (@input) { my $output = ios_commandset($ip, $port, $realm, $username, $ +password, $input); print_output($output); } } } if (${$flags}{'-i'}) { my $command = ''; my $count = @switches; print "Entering interactive mode. Type 'quit' to exit.\n"; until ($command =~ /^quit$/i) { if ($mode == 1) {print "(config)#";} else {print "#";} my @command_list = (chomp($command = <STDIN>)); exit if ($command =~ /^quit$/i); my @input = parse_commands($command); my $input = shift(@input); foreach my $ip (@switches) { print ">>Output for switch ($ip):\n" if ($count > 1); my $output = ios_commandset($ip, $port, $realm, $username, $ +password, $input); print_output($output); } } } } } #Display help if there are no options. else {show_help();} ### Macros Section ### #Parse Files Macro #Make an array of items by reading them from file(s) sub parse_files_macro { my (@files) = @_; my (@items); foreach my $file (@files) { open FH, ($file) or warn "Can't open $file for parsing. Skipping i +t.\n"; while (<FH>) { chomp($_); push @items, $_; } close FH; } return @items; } ### Subroutine Section ### #Anonymous code block for scoping %options, @list properly in recursiv +e callbacks. { my %options; my @list; #Defines relationship of invokation arguments as a hash. sub analyze_options { my ($element); ($element, @list) = @_; #Add new options to the hash. unless ($options{$element}) {$options{$element} = [];} #Parse the list of arguments. while (@list) { my $item = shift(@list); #If the element is an option, parse it with remaining arguments. if ($item =~ /^-/) {analyze_options($item, @list);} #If the element is an argument, it belongs to the preceding opti +on. else {push @{$options{$element}}, $item;} } #Return a reference to your hash of options. return \%options; } #End analyze_options } #End anonymous code block. #Formats individual commands into an IOS Commandset script #Note: This subroutine could use some optimizing sub parse_commands { my (@commands) = @_; my @command_sets; my @command_list; ##NOTE: MODE 0 IS EXEC, MODE 1 IS CONFIG ##NOTE: You can't enter config from exec mode (configure terminal) ## But you can enter exec from config mode (exit only, not end) ## Because of this one-way dependancy, command sets are seperated ## into different modes and executed seperately but in-sequence. my $header_exec = <<END; ! COMMANDSET VERSION="1.0" ! OPTIONS BEGIN ! ACTION_ON_FAILURE="0" MODE="0" ! OPTIONS END END my $header_config = <<END; ! COMMANDSET VERSION="1.0" ! OPTIONS BEGIN ! ACTION_ON_FAILURE="0" MODE="1" ! OPTIONS END END my $footer = <<END; ! END ! COMMANDSET END END ##Parse commands, and seperate into sections of exec, and config mod +es while (@commands) { my $command = shift(@commands); if ($command =~ /^con(\w+)? t(\w+)?/) { #If the commandset doesn't start with a config term command #Finish the current set and start a new one under mode 1. if (@command_list) { my $formatted_commands = join("\n", @command_list) . "\n"; my $command_set; if ($mode == 0) {$command_set = $header_exec . $formatted_comm +ands . $footer;} else {$command_set = $header_config . $formatted_commands . $f +ooter;} push @command_sets, $command_set; @command_list = (); $mode = 1; } else { $command = '!'; push @command_list, $command;$mode = 1; } } #If the command is 'end', finish the current set and start a new o +ne under mode 0. elsif ($command =~ /^end$/) { push @command_list, $command; my $formatted_commands = join("\n", @command_list) . "\n"; my $command_set; if ($mode == 0) {$command_set = $header_exec . $formatted_comman +ds . $footer;} else {$command_set = $header_config . $formatted_commands . $foo +ter;} push @command_sets, $command_set; @command_list = (); $mode = 0; } #The command is added to the commandset for the current mode. else {push @command_list, $command;} } #Add header & footer for the last section if (@command_list) { my $formatted_commands = join("\n", @command_list) . "\n"; my $command_set; if ($mode == 0) {$command_set = $header_exec . $formatted_commands + . $footer;} else {$command_set = $header_config . $formatted_commands . $foote +r;} push @command_sets, $command_set; } ##Return list of formatted sections, to be executed seperately but i +n sequence return @command_sets; } #End parse_commands sub print_output { my ($output) = @_; if ($verbosity eq 'quiet') { my $error = $1 if ($output =~ /PARSE_ERROR="(\d)"/); if ($error == 0) {print "Success\n";} else {print "[[FAIL]] - Parse Error $error\n";} } else {print "$output\n";} } #End parse_output #Passes formatted IOS Commandset script to an http server, and returns + output sub ios_commandset { my ($ip, $port, $realm, $username, $password, $content) = @_; my $mecha; my $uri = "$protocol://$ip$url"; $mecha = WWW::Mechanize->new(autocheck => 1); $mecha->timeout(10); $mecha->credentials("$ip:$port", $realm, $username, $password); #$mecha->post($uri, Content => $content); #Catch WWW::Mechanize errors. eval{$mecha->post($uri, Content => $content);}; if ($@) { if (${$flags}{'-e'}) { $uri = "http://$ip$url"; $mecha->credentials("$ip:80", $realm, $username, $password); $mecha->post($uri, Content => $content); } else { $uri = "https://$ip$url"; $mecha->credentials("$ip:443", $realm, $username, $password); $mecha->post($uri, Content => $content); } } return $mecha->content(); } #End ios_commandset sub show_help { my ($error) = @_; if ($error) {print "$error\n\n";} my ($help) = <<END; cccp - Cisco Console Command Parser Version 0.003 Cedric Nelson, January 2008 A utility for batch processing of IOS commands. Usage: cccp <options> Options: -c <cmd | file>... Command(s) to execute. -s <sw | file>... Execute commands on the specified switch +(es). -e Establish encrypted connection to switch +(es). -u <...> Username for connection to switch(es). -p <...> Password for connection to switch(es). -i Use interactive mode. -q Quiet verbosity (Succcess/Fail) -h Display help. END print "$help\n"; } #End show_help

In reply to cccp - Cisco Console Command Parser by colakong

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.