Category: cisco serial
Author/Contact Info Brian Guinan
Description: Here is a Cisco config utility (web based) that will configure a router with a base config, suck down a config and code to it for deployment. It uses conserver (conserver.com). **NOTE** still in development!! sh!tload of bugs and rewriting to be done! (im not a programmer by trade - just take a look at the code for confirmation!).
#!/usr/bin/perl

######################################
#Haphazardly written by: 
#Brian Guinan
#Date:       5/5/03
$Version =     ".2";


use Expect;
use CGI;
$q = new CGI;

# $Expect::Debug=1
# $Expect::Exp_Internal=1;
# $Expect::Log_Stdout=0; # Turn off verbose client interaction 




#############################
#Script requires a whitespace delimited config file in the following f
+ormat:
#RouterName       CodeName        Username        UserPassword     Ena
+blePassword 
# with a new line for each router you wish to configure

#############################
###These settings reflect temporary addresses used during the config p
+rocess
############################
#$port = "ttyS0";
my $timeout = 5;
my $cmd = "show flash";
my @out;
my $router_name,$codename,$username,$user_password,$enable_password = 
+"";
$tftp_server = "153.2.255.205";
$porta = "ttyS0";
$portb = "ttyS1";
$porta_IP = "153.2.254.70";
$portb_IP = "153.2.254.69";
$subnet_mask = "255.255.252.0";
$gateway_IP = "153.2.255.1";
$g_upload_path='/var/www/data';
$configfile = "config.txt";
$readfile = "$g_upload_path" . "/" . "$configfile";
$tmpfile = "/var/www/data/logfile" . "/" . "config.txt.lock";
my $flag = "-Done";
my $IP = $porta_IP;
my $static_commands = "no logging on;!;int faste0/0;ip address $IP $su
+bnet_mask;duplex auto;speed auto;no shut;!;exit;ip route 0.0.0.0 0.0.
+0.0 $gateway_IP;!;partition flash 2 16 16;!;";

##############################
####Dont change anything below this line.... else dont come to me!
##############################


if (! $q->param())    #send the form
{
        #$ScriptLocation = $ENV{'SCRIPT_NAME'};
        #$ServerName = $ENV{'SERVER_NAME'};
        print "Content-type: text/html\n\n";
        print "<title> Config </title>";
        if (($ENV{'HTTP_HOST'} ne "") && ($ENV{'REQUEST_URI'} ne "")){
                print "<form method=\"POST\" action=\"https://$ENV{'HT
+TP_HOST'}$ENV{'REQUEST_URI'}\">";
        }
        else {
                print "<<form method=\"post\" action=\"https://$URI/cg
+i-bin/micro_config.cgi\">";
        };
print <<FORM;
<p>
<h2><font size=7 color="#0000ff"><u>C</u></font>isco <font size=7 colo
+r="#0000ff"><u>I</u></font>nitial <font size=7 color="#0000ff"><u>C</
+u></font>onfig <font size=7 color="#0001ff"><u>U</u></font>tility
</h2>

Version: $Version
<p>
Select router to configure:<br>
<form>
<select name="router">
FORM


open (CONFIGFILE, "$readfile")|| die "Cant open configfile: $readfile!
+\n";
while (<CONFIGFILE>){
       @data = split(/\s+/);
        if ((@data[0] !~ m/.*$flag$/)&&($bool != 1)){
                print "<option selected=\"@data[0]\">@data[0]\n";
                $bool = 1;
        } else {
        print("<option value=\"@data[0]\">@data[0]\n");
        }
};
close(CONFIGFILE);


print <<FORM;
</select><br>
Select the serial port to use<br>
<select name="port">
<option value="$porta;$porta_IP">com 1
<option value="$portb;$portb_IP">com 2
</select>
<p>
<input type="submit" value="Configure it!">
<input type="reset" value="Reset Form">
</form>
FORM

} 
else         #process the form data
{
print "Content-type: multipart/mixed;boundary=boundary\n\n";
$status = system("killall console");
sleep 2;


#uncommment this is you want the page to perpetually scroll down
#print <<SCRIPT;
#<script language="javascript"type="text/javascript">
#<!--
#var scrollMe = window.setInterval("window.scrollBy(0,1000);", 1000);
#-->
##</script>
#<pre>
#SCRIPT


print "<pre WRAP>\n\n...working....\n\n";   #give user some feedback t
+o blank screen

#get passed paramaters and make assignmants
$router_name = $q->param("router");
($router_name, $codename) = split(/;/,$router_name);
#$port = $q->param("port");

($port, $IP) = split(/;/,$q->param("port"));

#check running procesies
@array = `ps -ax | grep console`;
@split = split(/\s+/,@array[0]);

if (@split[5] eq $port){
#ENABLE IF PROCESS KEEPS STICKING
        warning("Killing a previous console session");
        $bla = `kill -9 @split[0]`;
        sleep 2;
};

unless ($console = Expect->spawn("/usr/local/bin/console $port")){
        warning("never got a console spawned");
        die "never got a console spawned\n ".$console->exp_error()."\n
+";
} #did we spawn the client ok?
$console->log_file("/var/www/data/logfile/logfile.console.txt");



($router_name,$codename,$username,$user_password,$enable_password) = r
+ead_config($readfile,$router_name,$flag);
#still_booting();
login($username,$user_password);
#$enable_password = "password";
getroot($enable_password);
#clean();
static_conf("$static_commands");
sleep 5;
#check_network($gateway_IP);
check_network();
if (flash("1") ne $codename){
        warning("Copying code to flash:1: from TFTP server");
        copy_flash("$tftp_server","flash","$codename");
}else{
        warning("Correct flash ($codename) already on first partition"
+);
};




if (flash("2") ne $codename){
        warning("Copying code to flash:2: from flash:1:");
        copy_flash("flash:1:","flash:2:","$codename");
}else{
        warning("Correct flash ($codename) already on second partition
+");
};
copy_flash("$tftp_server","start","$router_name.TXT");
#clean();
#logout();
reload();

login($username,$user_password);
getroot($enable_password);
run_cmd("write mem",30,"[#>]");
logout();

};

sub warning{
        my $warning = $_[0];
        print "\n\<HTML\>\<font size=\"\5\" color=\"#FF0000\" face=\"T
+imes\"\>$warning\<\/font\>\<\/html\>\<pre WRAP\>\n";
};


sub still_booting{
        foreach my $i (1..20){
                my $out = run_cmd("\r",10,"sername|dialog|RETURN");
                if ($out =~ m/sername|dialog|RETURN/){
                        return();
                };
        };
}

sub reload{
        warning("Reloading router");
        my $out = run_cmd("reload",5,":");
        if ($out =~ m/Save/){
                $out = run_cmd("no",5,"\]");
                if ($out =~ m/reload/){
                        $out = run_cmd("\r",600,"sername|dialog|RETURN
+");
                        return();
                };
        }elsif($out =~ m/reload/){
                $out = run_cmd("\r",600,"sername|dialog|RETURN");
                return();
        }else{
                warning("ERROR: Couldent issue reload");
                death();
        };
return();
}



sub clean{
        my $toclean = $_[0];
        warning("Erasing flash and start");
        my $out = run_cmd("erase $toclean",5,"\[confirm\]");
        $out = run_cmd("\r",60,"[#>]");
        if (($out !~ m/\[OK\]/)||($out !~ m/complete/)){
                warning("ERROR: could not erase $toclean");
                death();
        };
#       static_conf("no partition flash 2;");
#       print "Router config erased. Rebooting router to complete\n";
#       $out = run_cmd("reload",5,".*");
        return();
};


sub check_network{
        my $out, $icmp_dest;
        if ($_[0] =~ m/\d+\.\d+\.\d+\.\d+/){
                $icmp_dest = $_[0];
        }else{
                $icmp_dest = "";;
                $out = run_cmd("show ip route",5,"[#>]");
                my @parse = split(/S\*/,$out);
                my $size = @parse;
                my $counter = 1;
                while ($counter < $size){
                        if (@parse[$counter] =~ m/0\.0\.0\.0\/0/){
                                my @sub_parse = split(/\s+/,@parse[$co
+unter]);
                                $counter = 2;
                                $size = @sub_parse;
                                while ($counter < $size){
                                        if (@sub_parse[$counter] =~ m/
+\d+\.\d+\.\d+\.\d+/){
                                                $icmp_dest = @sub_pars
+e[$counter];
                                                $counter = 99;
                                        };
                                        $counter++;
                                };
                        }else{
                                warning("No default gateway to ping!")
+;
                        };
                        $counter++;
                };
        }
        if ($icmp_dest ne ""){
                $out = run_cmd("ping $icmp_dest",5,"[#>]");
        }else{
                warning("ERROR: No default gateway to ping!");
                death();
        };
        if ($out !~ m/\!/){
                warning("ERROR: Cant ping $icmp_dest");
                warning("Check network cabeling and that host is alive
+");
        }else{
                warning("Default gateway pingable, network working!");
        };
        return();
};

sub read_config{
        my $config_file = $_[0];
        my $router_name = $_[1];
        my $flag = $_[2];
        my $codename,$username,$user_password,$enable_password = "";
        open (CONFIGFILE, "$config_file")|| die "cant open configfile:
+ $config_file\n";
undef $_;
        while (defined($_ = <CONFIGFILE>)){
                if ($_ =~ m/$router_name($flag)*\s+/){
                        ($router_name,$codename,$username,$user_passwo
+rd,$enable_password) = split(/\s+/);
                        $router_name =~ s/$flag//g;
                        close (CONFIGFILE);
                        return ($router_name,$codename,$username,$user
+_password,$enable_password);
                };
        };
        close (CONFIGFILE);
        death();
        return();
};



sub logout{
        warning("Logging out... have a nice day!");
        my $out = run_cmd("exit",5,"RETURN");
        return();
};



sub static_conf{
        my @split_commands = split(/;/,$_[0]);
        my $size = @split_commands;
        my $counter = 0;
        my $out = run_cmd("conf t",5,"#");
        while ($counter < $size){
                $out = run_cmd("@split_commands[$counter]",5,"[#>]");
                if (@split_commands[$counter] =~ m/exit/){
                        sleep 3; #needed to let router digest
                };
                $counter++;
        };
        $out = run_cmd("end",5,"[#>]");
        return();
};



sub flash{
        my $partition = $_[0];
        my $out = run_cmd("show flash",5,"[#>]");
        my @split = split(/\s/,$out);
        my $size = @split;
        my $counter = 0;
        my $partition_count = 0;
        while ($counter < $size){
                if ((@split[$counter] =~ m/partition/)&&(@split[$count
+er+1] =~ m/$partition/)){
                        $partition_count++;
                }elsif((@split[$counter] =~ m/status/)&&($partition_co
+unt != 0)){
                        return(@split[$counter+9]);
                }elsif(@split[$counter] =~ m/invalid\s+checksum/){
                        warning("ERROR: flash:$partition has an invala
+d checksum!");
                        warning("Press cancel or will app will format 
+and reload flash in 10 seconds!");
                        sleep 10;       #told you so!
                        clean("flash:$partition");
                }elsif(@split[$counter] =~ m/No/){
                        warning("No files in flash:$partition:");
                        return();
                };
                $counter++;
        };
        warning("ERROR: Could not get codename on flash:$partition");
};


sub copy_flash{
        my $source = $_[0];
        my $destination = $_[1];
        my $filename = $_[2];
        my $out;
        if ($source =~ m/\d+\.\d+\.\d+\.\d+/){
                $out = run_cmd("copy tftp $destination",5,"\\?");
                if ($out =~ m/Address/){
                        $out = run_cmd("$source",5,"\\?");
                };
        }else{
                $out = run_cmd("copy $source $destination",5,"\\?");
        };
        if($out =~ m/Source/){
                $out = run_cmd("$filename",5,"\\?");
                if($out =~ m/estination/){
                        if($destination =~ m/start/){
                                $out = run_cmd("\r",60,"confirm|[#>]")
+;
                        }else{
                                $out = run_cmd("$filename",60,"confirm
+|[#>]");
                        };
                        if($out =~ m/Erase/){
                                $out = run_cmd("\r",300,"[#>\\?]");
                                if($out =~ m/Erasing/){
                                        $out = run_cmd("\r",300,"[#>]"
+);
                                };
                        };
                };
        }elsif($out =~ m/Error/){
                warning("ERROR: Error copying file. Please check that 
+file ($filename) on $source exists");
        }elsif($out =~ m/OK/){
                $out =~ s/.*OK//g;
                $out =~ s/\r?$//g;
                warning("SNIPPED OUT: $out");
        }else{
                warning("ERROR: Something took a dump here");
        };


        if ($out =~ m/Error/){
                warning("ERROR: Error copying file. Please check file 
+($filename) on $source exists");
                death();
        };
        if ($out =~ m/OK/){
                warning("Flash copied from $source to $destination OK"
+);
#               $out =~ s/.*OK//g;
#               $out =~ s/.*\r?$//;
#BROKEN         warning("Snipped Info: $out");
        }else{
                warning("Something FFU'd");
                death();
        };
        return();
}




sub getroot{
        my $enable = $_[0];
        #returns:
        #       0 if no
        #       1 of yes 
        my $out = run_cmd("sho privilege",5,"[#>]");
        if ($out !~ m/.*15.*/){
                $out = run_cmd("enable",5,":");
                if ($out =~ m/Password/){
                        $out = run_cmd("$enable",5,"[#:]");
                        if ($out =~ m/Password/){
                                warning("ERROR: Bad Enable Password");
                                die();
                        };
                };
                getroot();
        }else{
        return 1;
        };
} 




sub login{
        my $username = $_[0];
        my $password = $_[1];
        foreach my $i (1..5){
                my $out = run_cmd("\r",5,"no\]:|sername:|[#>]");
                if ($out !~ m/[#>]/){
                        if ($out =~ m/sername/){
                                $out = run_cmd("$username",2,"[#>:]");
                        };
                        if($out =~ m/assword/){
                                $out = run_cmd("$password",2,"[#>:]");
                        };
                        if($out =~ m/dialog/){
                                warning("A Virgin!");
                                $out = run_cmd("no",3,"[#>:]");
                                if ($out =~ m/terminate/){
                                        $out = run_cmd("yes",10,"[#>:]
+");
                                };
                        };
#                       if (@out[0] eq "1"){
#                               return (0);
#                       };
                }elsif ($out =~ m/dialog/){
                        $out = run_cmd("no",20,".*");
                }else{
                        return(0);
                };
                $i++;
        };
#       death();
};

sub prompt_cmd{
        my $command = $_[0];
        my $timeout = $_[1];
        my $prompt = ".*" . $_[2];
        print $console "\r";
        my @out = $console->expect($timeout,'-re',$prompt);
        if (@out[0] eq "1"){
                print $console "$command\r";
                @out = $console->expect($timeout,'-re',$prompt);
                if (@out[0] eq "1"){
                        @out[3] =~ s/$command//g;
                }else{
                        warning("ERROR: Got prompt... command hung?");
                        return;
                };
        }else{
                warning("ERROR: Router never gave prompt");
                return;
        };
        return @out[3];
}

sub run_cmd{
        my $command = $_[0];
        my $timeout = $_[1];
        my $prompt = ".*" . $_[2];
        $console->clear_accum();
        print $console "$command\r";
        my @out = $console->expect($timeout,'-re',$prompt);
#       if (@out[0] ne "1"){
#               print "ERROR: Didnt get specified prompt returned\n";
#                       return;
#       };
my $output = @out[3] . @out[2] . @out[4];
return $output;
#        return @out[3];
}

sub death{
        warning("UNEXPECTED ERROR: FFU!");
        # if no longer needed, do a soft_close to nicely shut down the
+ command - french style 
        $console->hard_close(undef);
        exit 1;
}