summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorunknown <unknown@unknown>2008-12-17 03:43:51 +0000
committerunknown <unknown@unknown>2008-12-17 03:43:51 +0000
commit09f0f026fd4931b90016d0090778983da01c294a (patch)
treed47c450de794595ce6395bde6ff084d75dac48a4 /bin
parentb73f299e731fbddae095c0b5eff04717b6dce1af (diff)
downloadrancid-09f0f026fd4931b90016d0090778983da01c294a.tar.gz
rancid-09f0f026fd4931b90016d0090778983da01c294a.tar.xz
rancid-09f0f026fd4931b90016d0090778983da01c294a.zip
Imported from rancid-2.3.2a9.tar.gz.rancid-2.3.2a9
Diffstat (limited to 'bin')
-rw-r--r--bin/Makefile.am13
-rw-r--r--bin/Makefile.in74
-rw-r--r--bin/agmrancid.in5
-rw-r--r--bin/alogin.in32
-rw-r--r--bin/arancid.in27
-rw-r--r--bin/avologin.in351
-rw-r--r--bin/avorancid.in48
-rw-r--r--bin/blogin.in41
-rw-r--r--bin/brancid.in2
-rw-r--r--bin/cat5rancid.in2
-rw-r--r--bin/clogin.in151
-rw-r--r--bin/control_rancid.in22
-rw-r--r--bin/cssrancid.in20
-rw-r--r--bin/elogin.in27
-rw-r--r--bin/erancid.in2
-rw-r--r--bin/f10rancid.in44
-rw-r--r--bin/f5rancid.in645
-rw-r--r--bin/flogin.in54
-rw-r--r--bin/fnrancid.in2
-rw-r--r--bin/francid.in20
-rw-r--r--bin/hlogin.in51
-rw-r--r--bin/hpuifilter.c4
-rw-r--r--bin/hrancid.in16
-rw-r--r--bin/htlogin.in33
-rw-r--r--bin/htrancid.in2
-rw-r--r--bin/jerancid.in14
-rw-r--r--bin/jlogin.in33
-rw-r--r--bin/jrancid.in2
-rw-r--r--bin/lg.cgi.in2
-rw-r--r--bin/lgform.cgi.in2
-rw-r--r--bin/mrancid.in2
-rw-r--r--bin/mrvlogin.in774
-rw-r--r--bin/mrvrancid.in522
-rw-r--r--bin/nlogin.in37
-rw-r--r--bin/nrancid.in2
-rw-r--r--bin/nslogin.in124
-rw-r--r--bin/nsrancid.in42
-rw-r--r--bin/nxrancid.in1835
-rw-r--r--bin/par.in2
-rwxr-xr-xbin/prancid.in2
-rw-r--r--bin/rancid-cvs.in6
-rw-r--r--bin/rancid-fe.in8
-rw-r--r--bin/rancid-run.in2
-rw-r--r--bin/rancid.in109
-rw-r--r--bin/rivlogin.in18
-rw-r--r--bin/rivrancid.in2
-rw-r--r--bin/rrancid.in2
-rwxr-xr-xbin/srancid.in2
-rw-r--r--bin/tlogin.in815
-rw-r--r--bin/tntlogin.in33
-rw-r--r--bin/tntrancid.in2
-rw-r--r--bin/trancid.in300
-rw-r--r--bin/xrancid.in11
-rwxr-xr-xbin/zrancid.in2
54 files changed, 5543 insertions, 852 deletions
diff --git a/bin/Makefile.am b/bin/Makefile.am
index 16ad0c1..3ad2a93 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -3,7 +3,7 @@
## $Id$
##
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -49,12 +49,13 @@
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS = hpuifilter
-bin_SCRIPTS = agmrancid alogin arancid blogin brancid cat5rancid clogin \
- control_rancid cssrancid elogin erancid f10rancid \
+bin_SCRIPTS = agmrancid alogin arancid avologin avorancid blogin brancid \
+ cat5rancid clogin control_rancid cssrancid elogin erancid f10rancid \
flogin fnrancid francid hlogin hrancid htlogin htrancid \
- jerancid jlogin jrancid mrancid nlogin nrancid nslogin \
- nsrancid par prancid rancid-fe rancid rivlogin rivrancid \
- rrancid srancid tntlogin tntrancid xrancid zrancid
+ jerancid jlogin jrancid mrancid mrvlogin mrvrancid nlogin nrancid \
+ nslogin nsrancid nxrancid par prancid rancid-fe rancid rivlogin \
+ rivrancid rrancid srancid tlogin tntlogin tntrancid trancid xrancid \
+ zrancid
bin_SCRIPTS += lg.cgi lgform.cgi rancid-cvs rancid-run
EXTRA_DIST= lg.cgi.in lgform.cgi.in rancid-cvs.in rancid-run.in
diff --git a/bin/Makefile.in b/bin/Makefile.in
index e5f4cd1..51a47bf 100644
--- a/bin/Makefile.in
+++ b/bin/Makefile.in
@@ -1,8 +1,8 @@
-# Makefile.in generated by automake 1.10 from Makefile.am.
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -47,16 +47,19 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/clogin.in $(srcdir)/control_rancid.in \
$(srcdir)/cssrancid.in $(srcdir)/elogin.in \
$(srcdir)/erancid.in $(srcdir)/f10rancid.in \
- $(srcdir)/flogin.in $(srcdir)/fnrancid.in $(srcdir)/francid.in \
- $(srcdir)/hlogin.in $(srcdir)/hrancid.in $(srcdir)/htlogin.in \
+ $(srcdir)/f5rancid.in $(srcdir)/flogin.in \
+ $(srcdir)/fnrancid.in $(srcdir)/francid.in $(srcdir)/hlogin.in \
+ $(srcdir)/hrancid.in $(srcdir)/htlogin.in \
$(srcdir)/htrancid.in $(srcdir)/jerancid.in \
$(srcdir)/jlogin.in $(srcdir)/jrancid.in $(srcdir)/mrancid.in \
+ $(srcdir)/mrvlogin.in $(srcdir)/mrvrancid.in \
$(srcdir)/nlogin.in $(srcdir)/nrancid.in $(srcdir)/nslogin.in \
- $(srcdir)/nsrancid.in $(srcdir)/par.in $(srcdir)/prancid.in \
- $(srcdir)/rancid-fe.in $(srcdir)/rancid.in \
- $(srcdir)/rivlogin.in $(srcdir)/rivrancid.in \
- $(srcdir)/rrancid.in $(srcdir)/srancid.in \
- $(srcdir)/tntlogin.in $(srcdir)/tntrancid.in \
+ $(srcdir)/nsrancid.in $(srcdir)/nxrancid.in $(srcdir)/par.in \
+ $(srcdir)/prancid.in $(srcdir)/rancid-fe.in \
+ $(srcdir)/rancid.in $(srcdir)/rivlogin.in \
+ $(srcdir)/rivrancid.in $(srcdir)/rrancid.in \
+ $(srcdir)/srancid.in $(srcdir)/tlogin.in $(srcdir)/tntlogin.in \
+ $(srcdir)/tntrancid.in $(srcdir)/trancid.in \
$(srcdir)/xrancid.in $(srcdir)/zrancid.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
@@ -67,11 +70,11 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = control_rancid par rancid-fe agmrancid alogin \
arancid avologin avorancid blogin brancid cat5rancid clogin \
- rancid cssrancid elogin erancid f10rancid flogin francid \
- fnrancid hlogin hrancid htlogin htrancid jlogin jrancid \
- jerancid mrancid nlogin nrancid nslogin nsrancid prancid \
- rivlogin rivrancid rrancid srancid tntlogin tntrancid xrancid \
- zrancid
+ rancid cssrancid elogin erancid f5rancid f10rancid flogin \
+ francid fnrancid hlogin hrancid htlogin htrancid jlogin \
+ jrancid jerancid mrancid mrvlogin mrvrancid nlogin nrancid \
+ nslogin nsrancid nxrancid prancid rivlogin rivrancid rrancid \
+ srancid tlogin tntlogin tntrancid trancid xrancid zrancid
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
@@ -80,7 +83,7 @@ hpuifilter_OBJECTS = $(am_hpuifilter_OBJECTS)
hpuifilter_LDADD = $(LDADD)
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
SCRIPTS = $(bin_SCRIPTS)
-DEFAULT_INCLUDES = -I. -I$(top_builddir)/include@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@@ -208,18 +211,20 @@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
#AUTOMAKE_OPTIONS=foreign no-dependencies
AUTOMAKE_OPTIONS = foreign
-bin_SCRIPTS = agmrancid alogin arancid blogin brancid cat5rancid \
- clogin control_rancid cssrancid elogin erancid f10rancid \
- flogin fnrancid francid hlogin hrancid htlogin htrancid \
- jerancid jlogin jrancid mrancid nlogin nrancid nslogin \
- nsrancid par prancid rancid-fe rancid rivlogin rivrancid \
- rrancid srancid tntlogin tntrancid xrancid zrancid lg.cgi \
- lgform.cgi rancid-cvs rancid-run
+bin_SCRIPTS = agmrancid alogin arancid avologin avorancid blogin \
+ brancid cat5rancid clogin control_rancid cssrancid elogin \
+ erancid f10rancid flogin fnrancid francid hlogin hrancid \
+ htlogin htrancid jerancid jlogin jrancid mrancid mrvlogin \
+ mrvrancid nlogin nrancid nslogin nsrancid nxrancid par prancid \
+ rancid-fe rancid rivlogin rivrancid rrancid srancid tlogin \
+ tntlogin tntrancid trancid xrancid zrancid lg.cgi lgform.cgi \
+ rancid-cvs rancid-run
EXTRA_DIST = lg.cgi.in lgform.cgi.in rancid-cvs.in rancid-run.in
#dist_bin_SCRIPTS= $(bin_SCRIPTS:%=%.in)
CLEANFILES = lg.cgi lgform.cgi rancid-cvs rancid-run
@@ -319,6 +324,8 @@ elogin: $(top_builddir)/config.status $(srcdir)/elogin.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
erancid: $(top_builddir)/config.status $(srcdir)/erancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+f5rancid: $(top_builddir)/config.status $(srcdir)/f5rancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
f10rancid: $(top_builddir)/config.status $(srcdir)/f10rancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
flogin: $(top_builddir)/config.status $(srcdir)/flogin.in
@@ -343,6 +350,10 @@ jerancid: $(top_builddir)/config.status $(srcdir)/jerancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
mrancid: $(top_builddir)/config.status $(srcdir)/mrancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+mrvlogin: $(top_builddir)/config.status $(srcdir)/mrvlogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+mrvrancid: $(top_builddir)/config.status $(srcdir)/mrvrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
nlogin: $(top_builddir)/config.status $(srcdir)/nlogin.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
nrancid: $(top_builddir)/config.status $(srcdir)/nrancid.in
@@ -351,6 +362,8 @@ nslogin: $(top_builddir)/config.status $(srcdir)/nslogin.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
nsrancid: $(top_builddir)/config.status $(srcdir)/nsrancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+nxrancid: $(top_builddir)/config.status $(srcdir)/nxrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
prancid: $(top_builddir)/config.status $(srcdir)/prancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
rivlogin: $(top_builddir)/config.status $(srcdir)/rivlogin.in
@@ -361,10 +374,14 @@ rrancid: $(top_builddir)/config.status $(srcdir)/rrancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
srancid: $(top_builddir)/config.status $(srcdir)/srancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+tlogin: $(top_builddir)/config.status $(srcdir)/tlogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
tntlogin: $(top_builddir)/config.status $(srcdir)/tntlogin.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
tntrancid: $(top_builddir)/config.status $(srcdir)/tntrancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+trancid: $(top_builddir)/config.status $(srcdir)/trancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
xrancid: $(top_builddir)/config.status $(srcdir)/xrancid.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
zrancid: $(top_builddir)/config.status $(srcdir)/zrancid.in
@@ -442,8 +459,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
@@ -455,8 +472,8 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
@@ -466,13 +483,12 @@ ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
- here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
diff --git a/bin/agmrancid.in b/bin/agmrancid.in
index af6e807..09429cd 100644
--- a/bin/agmrancid.in
+++ b/bin/agmrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -462,7 +462,7 @@ if ($ENV{"FILTER_PWDS"} =~ /no/i) {
$filter_pwds = 1;
}
-ProcessHistory("","","","!RANCID-CONTENT-TYPE: riverhead\n!\n");
+ProcessHistory("","","","!RANCID-CONTENT-TYPE: AGM\n!\n");
ProcessHistory("COMMENTS","keysort","B0","!\n");
ProcessHistory("COMMENTS","keysort","C0","!\n");
TOP: while(<INPUT>) {
@@ -520,7 +520,6 @@ if (scalar(%commands) || !$clean_run || !$found_end) {
printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
}
if (!$clean_run || !$found_end) {
-print STDOUT $clean_run . " " . $found_end . "\n";
print STDOUT "$host: End of run not found\n";
print STDERR "$host: End of run not found\n" if ($debug);
system("/usr/bin/tail -1 $host.new");
diff --git a/bin/alogin.in b/bin/alogin.in
index c21b49f..a17bd2a 100644
--- a/bin/alogin.in
+++ b/bin/alogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -385,16 +385,16 @@ proc login { router user userpswd passwd prompt cmethod cyphertype } {
return 1 }
-re "$u_prompt" {
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -425,24 +425,14 @@ proc run_commands { prompt command } {
regsub -all "\[)(]" $prompt {\\&} reprompt
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
- expect {
- -re "^\[^\n\r]*$reprompt" {}
- -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue }
- -re "\[\n\r]+" { exp_continue }
- }
- }
- } else {
- send "[subst -nocommands $command]\r"
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
expect {
- -re "^\[^\n\r]*$reprompt" {}
- -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue }
- -re "\[\n\r]+" { exp_continue }
+ -re "^\[^\n\r]*$reprompt" {}
+ -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue }
+ -re "\[\n\r]+" { exp_continue }
}
}
send "exit\r"
diff --git a/bin/arancid.in b/bin/arancid.in
index 1ff5f64..366fdd9 100644
--- a/bin/arancid.in
+++ b/bin/arancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -178,11 +178,14 @@ sub ShowVersion {
/^(ACEdirector.*|ACEswitch.*|Alteon.*)/i &&
ProcessHistory("COMMENTS","keysort","A1", "\/\*Model: $1\n") && next;
/^Software Version\s+(.*?)\s\((.*)\)/i &&
- ProcessHistory("COMMENTS","keysort","B1", "\/\*Image: Software: $1 ($2)\n") && next;
+ ProcessHistory("COMMENTS","keysort","B1",
+ "\/\*Image: Software: $1 ($2)\n") && next;
/^Hardware Part No:\s+(.*?)\s+/i &&
- ProcessHistory("COMMENTS","keysort","A2", "\/\*Hardware part no: $1\n") && next;
+ ProcessHistory("COMMENTS","keysort","A2",
+ "\/\*Hardware part no: $1\n") && next;
/^MAC address:\s+([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})/i &&
- ProcessHistory("COMMENTS","keysort","C1", "\/\*Base MAC address: $1\n") && next;
+ ProcessHistory("COMMENTS","keysort","C1",
+ "\/\*Base MAC address: $1\n") && next;
}
return(0);
}
@@ -208,11 +211,11 @@ sub WriteTerm {
next if (/^\/\* Configuration dump taken/i);
next if (/^\/\* Version.*Base MAC.*/i);
- if (/^\/?script end/) {
- $found_end = 1;
- ProcessHistory("","","","$_\n");
- return(1);
- }
+ if (/^\/?script end/) {
+ $found_end = 1;
+ ProcessHistory("","","","$_\n");
+ return(1);
+ }
ProcessHistory("","","","$_\n");
}
@@ -232,8 +235,8 @@ sub DoNothing {print STDOUT;}
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);
-$cisco_cmds=join(";",@commands);
-$cmds_regexp=join("|",@commands);
+$cisco_cmds = join(";",@commands);
+$cmds_regexp = join("|",@commands);
if (length($host) == 0) {
if ($file) {
@@ -289,7 +292,7 @@ ProcessHistory("COMMENTS","keysort","F0","\/\*\n");
TOP: while(<INPUT>) {
tr/\015//d;
if (/^>>.*$prompt exit/) {
- $clean_run=1;
+ $clean_run = 1;
last;
}
diff --git a/bin/avologin.in b/bin/avologin.in
index ed2617f..b51f841 100644
--- a/bin/avologin.in
+++ b/bin/avologin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (C) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (C) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
@@ -22,9 +22,9 @@
#
# The login expect scripts were based on Erik Sherk's gwtn, by permission.
#
-# avologin - Cisco login
+# avologin - Avocent login
#
-# Most options are intuitive for logging into a Cisco router.
+# Most options are intuitive for logging into a Avocent/Cyclades term server.
# The default is to enable (thus -noenable). Some folks have
# setup tacacs to have a user login at priv-lvl = 15 (enabled)
# so the -autoenable flag was added for this case (don't go through
@@ -51,31 +51,32 @@ set do_script 0
set avenable 1
# The default is that you login non-enabled (tacacs can have you login already
# enabled)
-set avautoenable 1
+set avautoenable 0
# The default is to look in the password file to find the passwords. This
# tracks if we receive them on the command line.
set do_passwd 1
set do_enapasswd 1
-# attempt at platform switching.
-set platform ""
# Find the user in the ENV, or use the unix userid.
-if {[ info exists env(CISCO_USER) ]} {
+if {[info exists env(CISCO_USER)]} {
set default_user $env(CISCO_USER)
-} elseif {[ info exists env(USER) ]} {
+} elseif {[info exists env(USER)]} {
set default_user $env(USER)
-} elseif {[ info exists env(LOGNAME) ]} {
+} elseif {[info exists env(LOGNAME)]} {
set default_user $env(LOGNAME)
} else {
# This uses "id" which I think is portable. At least it has existed
# (without options) on all machines/OSes I've been on recently -
# unlike whoami or id -nu.
- if [ catch {exec id} reason ] {
+ if [catch {exec id} reason] {
send_error "\nError: could not exec id: $reason\n"
exit 1
}
regexp {\(([^)]*)} "$reason" junk default_user
}
+if {[info exists env(CLOGINRC)]} {
+ set password_file $env(CLOGINRC)
+}
# Sometimes routers take awhile to answer (the default is 10 sec)
set timeout 45
@@ -91,24 +92,24 @@ for {set i 0} {$i < $argc} {incr i} {
# Username
} -u* -
-U* {
- if {! [ regexp .\[uU\](.+) $arg ignore user]} {
+ if {! [regexp .\[uU\](.+) $arg ignore user]} {
incr i
- set username [ lindex $argv $i ]
+ set username [lindex $argv $i]
}
# VTY Password
} -p* -
-P* {
- if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} {
+ if {! [regexp .\[pP\](.+) $arg ignore userpasswd]} {
incr i
- set userpasswd [ lindex $argv $i ]
+ set userpasswd [lindex $argv $i]
}
set do_passwd 0
# VTY Password
} -v* -
-v* {
- if {! [ regexp .\[vV\](.+) $arg ignore passwd]} {
+ if {! [regexp .\[vV\](.+) $arg ignore passwd]} {
incr i
- set passwd [ lindex $argv $i ]
+ set passwd [lindex $argv $i]
}
set do_passwd 0
# Version string
@@ -118,14 +119,14 @@ for {set i 0} {$i < $argc} {incr i} {
# Enable Username
} -w* -
-W* {
- if {! [ regexp .\[wW\](.+) $arg ignore enauser]} {
+ if {! [regexp .\[wW\](.+) $arg ignore enauser]} {
incr i
- set enausername [ lindex $argv $i ]
+ set enausername [lindex $argv $i]
}
# Environment variable to pass to -s scripts
} -E*
{
- if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ if {[regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
send_user "\nError: invalid format for -E in $arg\n"
@@ -134,27 +135,27 @@ for {set i 0} {$i < $argc} {incr i} {
# Enable Password
} -e*
{
- if {! [ regexp .\[e\](.+) $arg ignore enapasswd]} {
+ if {! [regexp .\[e\](.+) $arg ignore enapasswd]} {
incr i
- set enapasswd [ lindex $argv $i ]
+ set enapasswd [lindex $argv $i]
}
set do_enapasswd 0
# Command to run.
} -c* -
-C* {
- if {! [ regexp .\[cC\](.+) $arg ignore command]} {
+ if {! [regexp .\[cC\](.+) $arg ignore command]} {
incr i
- set command [ lindex $argv $i ]
+ set command [lindex $argv $i]
}
set do_command 1
# Expect script to run.
} -s* -
-S* {
- if {! [ regexp .\[sS\](.+) $arg ignore sfile]} {
+ if {! [regexp .\[sS\](.+) $arg ignore sfile]} {
incr i
- set sfile [ lindex $argv $i ]
+ set sfile [lindex $argv $i]
}
- if { ! [ file readable $sfile ] } {
+ if { ! [file readable $sfile] } {
send_user "\nError: Can't read $sfile\n"
exit 1
}
@@ -162,32 +163,32 @@ for {set i 0} {$i < $argc} {incr i} {
# 'ssh -c' cypher type
} -y* -
-Y* {
- if {! [ regexp .\[eE\](.+) $arg ignore cypher]} {
+ if {! [regexp .\[eE\](.+) $arg ignore cypher]} {
incr i
- set cypher [ lindex $argv $i ]
+ set cypher [lindex $argv $i]
}
# alternate cloginrc file
} -f* -
-F* {
- if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
+ if {! [regexp .\[fF\](.+) $arg ignore password_file]} {
incr i
- set password_file [ lindex $argv $i ]
+ set password_file [lindex $argv $i]
}
# Timeout
} -t* -
-T* {
- if {! [ regexp .\[tT\](.+) $arg ignore timeout]} {
+ if {! [regexp .\[tT\](.+) $arg ignore timeout]} {
incr i
- set timeout [ lindex $argv $i ]
+ set timeout [lindex $argv $i]
}
# Command file
} -x* -
-X {
- if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} {
+ if {! [regexp .\[xX\](.+) $arg ignore cmd_file]} {
incr i
- set cmd_file [ lindex $argv $i ]
+ set cmd_file [lindex $argv $i]
}
- if [ catch {set cmd_fd [open $cmd_file r]} reason ] {
+ if [catch {set cmd_fd [open $cmd_file r]} reason] {
send_user "\nError: $reason\n"
exit 1
}
@@ -253,7 +254,7 @@ proc add {var args} { global int_$var ; lappend int_$var $args}
proc include {args} {
global env
regsub -all "(^{|}$)" $args {} args
- if { [ regexp "^/" $args ignore ] == 0 } {
+ if {[regexp "^/" $args ignore] == 0} {
set args $env(HOME)/$args
}
source_password_file $args
@@ -287,16 +288,16 @@ proc source_password_file { password_file } {
send_user "\nError: $password_file must not be world readable/writable\n"
exit 1
}
- if [ catch {source $password_file} reason ] {
+ if [catch {source $password_file} reason] {
send_user "\nError: $reason\n"
exit 1
}
}
# Log into the router.
-# returns: 0 on success, 1 on failure, -1 if rsh was used successfully
+# returns: 0 on success, 1 on failure
proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
- global spawn_id in_proc do_command do_script platform
+ global spawn_id in_proc do_command do_script
global prompt u_prompt p_prompt e_prompt sshcmd
set in_proc 1
set uprompt_seen 0
@@ -308,9 +309,9 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
if [string match "telnet*" $prog] {
regexp {telnet(:([^[:space:]]+))*} $prog command suffix port
if {"$port" == ""} {
- set retval [ catch {spawn telnet $router} reason ]
+ set retval [catch {spawn telnet $router} reason]
} else {
- set retval [ catch {spawn telnet $router $port} reason ]
+ set retval [catch {spawn telnet $router $port} reason]
}
if { $retval } {
send_user "\nError: telnet failed: $reason\n"
@@ -319,89 +320,15 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
} elseif [string match "ssh*" $prog] {
regexp {ssh(:([^[:space:]]+))*} $prog command suffix port
if {"$port" == ""} {
- set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ]
+ set retval [catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason]
} else {
- set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user -p $port $router} reason ]
+ set retval [catch {spawn $sshcmd -c $cyphertype -x -l $user -p $port $router} reason]
}
if { $retval } {
send_user "\nError: $sshcmd failed: $reason\n"
return 1
}
- } elseif ![string compare $prog "rsh"] {
- global command
-
- if { ! $do_command } {
- if { [llength $cmethod] == 1 } {
- send_user "\nError: rsh is an invalid method for -x and "
- send_user "interactive logins\n"
- }
- if { $progs == 0 } {
- return 1
- }
- continue;
- }
-
- set commands [split $command \;]
- set num_commands [llength $commands]
- set rshfail 0
- for {set i 0} {$i < $num_commands && !$rshfail} { incr i} {
- log_user 0
- set retval [ catch {spawn rsh $user@$router [lindex $commands $i] } reason ]
- if { $retval } {
- send_user "\nError: rsh failed: $reason\n"
- log_user 1; return 1
- }
- send_user "$router# [lindex $commands $i]\n"
-
- # rcmd does not get a pager and no prompts, so we just have to
- # look for failures & lines.
- expect {
- "Connection refused" { catch {close}; catch {wait};
- send_user "\nError: Connection\
- Refused ($prog): $router\n"
- set rshfail 1
- }
- -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
- catch {close}; catch {wait};
- send_user "\nError: Connection\
- closed ($prog): $router\n"
- set rshfail 1
- }
- "Host is unreachable" { catch {close}; catch {wait};
- send_user "\nError: Host Unreachable:\
- $router\n"
- set rshfail 1
- }
- "No address associated with" {
- catch {close}; catch {wait};
- send_user "\nError: Unknown host\
- $router\n"
- set rshfail 1
- }
- -re "\b+" { exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
- exp_continue
- }
- timeout { catch {close}; catch {wait};
- send_user "\nError: TIMEOUT reached\n"
- set rshfail 1
- }
- eof { catch {close}; catch {wait}; }
- }
- log_user 1
- }
- if { $rshfail } {
- if { !$progs } {
- return 1
- } else {
- continue
- }
- }
- # fake the end of the session for rancid.
- send_user "$router# exit\n"
- # return rsh "success"
- return -1
} else {
send_user "\nError: unknown connection method: $prog\n"
return 1
@@ -488,34 +415,23 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
send_user "\nError: Check your passwd for $router\n"
return 1
}
- "Press any key to continue." {
- # send_user "Pressing the ANY key\n"
- send "\r"
- exp_continue
- }
- -re "Enter Selection: " {
- # Catalyst 1900s have some lame menu. Enter
- # K to reach a command-line.
- send "K\r"
- exp_continue;
- }
-re "@\[^\r\n]+ $p_prompt" {
# ssh pwd prompt
sleep 1
- send "$userpswd\r"
+ send -- "$userpswd\r"
exp_continue
}
-re "$u_prompt" {
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -537,13 +453,16 @@ proc do_enable { enauser enapasswd } {
global u_prompt e_prompt
set in_proc 1
- send "enable\r"
+ send "/bin/su\r"
expect {
- -re "$u_prompt" { send "$enauser\r"; exp_continue}
- -re "$e_prompt" { send "$enapasswd\r"; exp_continue}
+ -re "$u_prompt" { send -- "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send -- "$enapasswd\r"; exp_continue}
"#" { set prompt "#" }
- "(enable)" { set prompt "> (enable) " }
- -re "(denied|Sorry|Incorrect)" {
+ -re "su: User not allowed access" {
+ send_user "\nError: Enable access not allowed\n";
+ return 1
+ }
+ -re "(denied|Sorry|Incorrect)" {
# % Access denied - from local auth and poss. others
send_user "\nError: Check your Enable passwd\n";
return 1
@@ -565,109 +484,58 @@ proc do_enable { enauser enapasswd } {
# Run commands given on the command line.
proc run_commands { prompt command } {
- global in_proc platform
+ global in_proc
set in_proc 1
- # If the prompt is (enable), then we are on a switch and the
- # command is "set length 0"; otherwise its "term length 0".
- # skip if its an extreme (since the pager can not be disabled on a
- # per-vty basis).
- if { [ string compare "extreme" "$platform" ] } {
- if [ regexp -- ".*> .*enable" "$prompt" ] {
- send "set length 0\r"
- # This is ugly, but reduces code duplication, allowing the
- # subsequent expects to handle everything as normal.
- set command "set logging session disable;$command"
- } else {
- #send "term length 0\r"
- send "\r"
- }
- # escape any parens in the prompt, such as "(enable)"
- regsub -all {[)(]} $prompt {\\&} reprompt
- # match cisco config mode prompts too, such as router(config-if)#,
- # but catalyst does not change in this fashion.
- regsub -all {^(.{1,14}).*([#>])$} $reprompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt
- expect {
- -re $reprompt {}
- -re "\[\n\r]+" { exp_continue }
- }
- } else {
- regsub -all "\[)(]" $prompt {\\&} reprompt
+ # The pager cant be completely disabled
+ send "stty rows 1024\r"
+ # escape any parens in the prompt, such as "(enable)"
+ regsub -all {[)(]} $prompt {\\&} reprompt
+# XXX
+# match cisco config mode prompts too, such as router(config-if)#,
+# but catalyst does not change in this fashion.
+regsub -all {^(.{1,14}).*([#>])$} $reprompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt
+ expect {
+ -re $reprompt {}
+ -re "\[\n\r]+" { exp_continue }
}
# this is the only way i see to get rid of more prompts in o/p..grrrrr
log_user 0
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
- # the pager can not be turned off on the PIX, so we have to look
- # for the "More" prompt. the extreme is equally obnoxious, with a
- # global switch in the config.
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
- expect {
- -re "\b+" { exp_continue }
- -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
- }
- -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
- send " "
- # bloody ^[[2K after " "
- expect {
- -re "^\[^\r\n]*\r" {}
- }
- exp_continue
- }
- -re "^ *--More--\[^\n\r]*" {
- send " "
- exp_continue }
- -re "^<-+ More -+>\[^\n\r]*" {
- send_user -- "$expect_out(buffer)"
- send " "
- exp_continue }
- }
- }
- } else {
- # the pager can not be turned off on the PIX, so we have to look
- # for the "More" prompt. the extreme is equally obnoxious, with a
- # global switch in the config.
- send "[subst -nocommands $command]\r"
+
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ # the pager can not be turned off on the PIX, so we have to look
+ # for the "More" prompt. the extreme is equally obnoxious, with a
+ # global switch in the config.
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
expect {
- -re "\b+" { exp_continue }
- -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
- }
- -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
- send " "
- # bloody ^[[2K after " "
- expect {
- -re "^\[^\r\n]*\r" {}
- }
- exp_continue
- }
- -re "^ *--More--\[^\n\r]*" {
- send " "
- exp_continue }
- -re "^<-+ More -+>\[^\n\r]*" {
- send_user -- "$expect_out(buffer)"
- send " "
- exp_continue }
+ -re "\b+" { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)" }
+ -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
+ exp_continue }
+ -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
+ exp_continue }
+ -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
+ send " "
+ # bloody ^[[2K after " "
+ expect {
+ -re "^\[^\r\n]*\r" {}
+ }
+ exp_continue
+ }
+ -re "^ *--More--\[^\n\r]*" { send " "
+ exp_continue }
+ -re "^<-+ More -+>\[^\n\r]*" {
+ send_user -- "$expect_out(buffer)"
+ send " "
+ exp_continue }
}
}
log_user 1
- if { [ string compare "extreme" "$platform" ] } {
- send "exit\r"
- } else {
- send "quit\r"
- }
+ send "exit\r"
expect {
-re "^\[^\n\r *]*$reprompt" {
# the Cisco CE and Jnx ERX
@@ -704,17 +572,17 @@ foreach router [lrange $argv $i end] {
if $avautoenable {
set autoenable 1
set enable 0
- set prompt "(#| \\(enable\\))"
+ set prompt "#"
} else {
set ae [find autoenable $router]
if { "$ae" == "1" } {
set autoenable 1
set enable 0
- set prompt "(#| \\(enable\\))"
+ set prompt "#"
} else {
set autoenable 0
set enable $avenable
- set prompt ">"
+ set prompt "\\\$"
}
}
@@ -804,7 +672,7 @@ foreach router [lrange $argv $i end] {
# Login to the router
if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype]} {
- # if login failed or rsh was successful, move on to the next device
+ # if login failed, move on to the next device
incr exitval
continue
}
@@ -821,20 +689,8 @@ foreach router [lrange $argv $i end] {
send "\r"
expect {
-re "\[\r\n]+" { exp_continue; }
- -re "^(.+:)1 $prompt" { # stoopid extreme cmd-line numbers and
- # prompt based on state of config changes,
- # which may have an * at the beginning.
- set junk $expect_out(1,string)
- regsub -all "^\\\* " $expect_out(1,string) {} junk
- set prompt ".? ?$junk\[0-9]+ $expect_out(2,string)";
- set platform "extreme"
- }
-re "^.+$prompt" { set junk $expect_out(0,string);
- regsub -all "\[\]\[]" $junk {\\&} prompt;
- }
- -re "^.+> \\\(enable\\\)" {
- set junk $expect_out(0,string);
- regsub -all "\[\]\[]" $junk {\\&} prompt;
+ regsub -all "\[\]\[\$]" $junk {\\&} prompt;
}
}
@@ -844,9 +700,10 @@ foreach router [lrange $argv $i end] {
continue
}
} elseif { $do_script } {
+ # XXX
# If the prompt is (enable), then we are on a switch and the
# command is "set length 0"; otherwise its "term length 0".
- if [ regexp -- ".*> .*enable" "$prompt" ] {
+ if [regexp -- ".*> .*enable" "$prompt"] {
#send "set length 0\r"
#send "set logging session disable\r"
} else {
diff --git a/bin/avorancid.in b/bin/avorancid.in
index 511eb80..33b77d3 100644
--- a/bin/avorancid.in
+++ b/bin/avorancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (C) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (C) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
@@ -147,21 +147,21 @@ sub sortbyipaddr {
}
# This routine parses "cat"
-sub CatFiles {
- print STDERR " In CatFiles: $_" if ($debug);
+sub CatFile {
+ print STDERR " In CatFile: $_" if ($debug);
- $catfile=$1;
- $catfile=~s/cat //;
+ $catfile = $1;
+ $catfile =~ s/cat //;
ProcessHistory("COMMENTS","","","! $catfile\n");
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
-# return(1) if /Line has invalid autocommand /;
+ return(-1) if /: Permission denied/;
ProcessHistory("COMMENTS","","","$_");
}
ProcessHistory("COMMENTS","","","!\n");
- if ( $catfile == "/etc/security.opts" ) { $found_end=1;$clean_run=1;};
+ if ( $catfile == "/etc/security.opts" ) { $found_end = 1; $clean_run = 1;};
return(0);
}
@@ -170,23 +170,23 @@ sub DoNothing {print STDOUT;}
# Main
@commandtable = (
- {'cat /etc/hostname' => 'CatFiles'},
- {'cat /etc/domainname.conf' => 'CatFiles'},
- {'cat /etc/resolv.conf' => 'CatFiles'},
- {'cat /etc/portslave/pslave.conf' => 'CatFiles'},
- {'cat /etc/passwd' => 'CatFiles'},
- {'cat /etc/snmp/snmpd.conf' => 'CatFiles'},
- {'cat /etc/network/ifcfg_eth0' => 'CatFiles'},
- {'cat /etc/network/st_routes' => 'CatFiles'},
- {'cat /etc/security.opts' => 'CatFiles'},
+ {'cat /etc/hostname' => 'CatFile'},
+ {'cat /etc/domainname.conf' => 'CatFile'},
+ {'cat /etc/resolv.conf' => 'CatFile'},
+ {'cat /etc/portslave/pslave.conf' => 'CatFile'},
+ {'cat /etc/passwd' => 'CatFile'},
+ {'cat /etc/snmp/snmpd.conf' => 'CatFile'},
+ {'cat /etc/network/ifcfg_eth0' => 'CatFile'},
+ {'cat /etc/network/st_routes' => 'CatFile'},
+ {'cat /etc/security.opts' => 'CatFile'},
);
# Use an array to preserve the order of the commands and a hash for mapping
# commands to the subroutine and track commands that have been completed.
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);
-$cisco_cmds=join(";",@commands);
-$cmds_regexp=join("|",@commands);
+$cisco_cmds = join(";",@commands);
+$cmds_regexp = join("|",@commands);
open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
select(OUTPUT);
@@ -235,21 +235,21 @@ ProcessHistory("COMMENTS","keysort","F0","!\n");
ProcessHistory("COMMENTS","keysort","G0","!\n");
TOP: while(<INPUT>) {
tr/\015//d;
- if (/[>#]\s?exit$/) {
- $clean_run=1;
+ if (/[#\$] exit$/) {
+ $clean_run = 1;
last;
}
if (/^Error:/) {
print STDOUT ("$host avologin error: $_");
print STDERR ("$host avologin error: $_") if ($debug);
- $clean_run=0;
+ $clean_run = 0;
last;
}
- while (/#\s*($cmds_regexp)\s*$/) {
+ while (/[#\$]\s*($cmds_regexp)\s*$/) {
$cmd = $1;
if (!defined($prompt)) {
- $prompt = ($_ =~ /^([^#]+#)/)[0];
- $prompt =~ s/([][}{)(\\])/\\$1/g;
+ $prompt = ($_ =~ /^([^#\$]+[#\$] )/)[0];
+ $prompt =~ s/([][}{)(\\\$])/\\$1/g;
print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
diff --git a/bin/blogin.in b/bin/blogin.in
index 9851493..27b89b2 100644
--- a/bin/blogin.in
+++ b/bin/blogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -405,26 +405,26 @@ proc login { router user userpswd passwd enapasswd prompt cmethod cyphertype } {
send "no\r"
send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n"
return 1 }
- -re "$u_prompt" { send "$user\r"
+ -re "$u_prompt" { send -- "$user\r"
expect {
eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
"Login invalid" { send_user "\nError: Invalid login\n";
catch {close}; catch {wait};
return 1 }
- -re "$p_prompt" { send "$userpswd\r" }
+ -re "$p_prompt" { send -- "$userpswd\r" }
"$prompt" { set in_proc 0; return 0 }
}
exp_continue
}
-re "$p_prompt" {
if ![string compare $prog "ssh"] {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
expect {
eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
- -re "$e_prompt" { send "$enapasswd\r" }
+ -re "$e_prompt" { send -- "$enapasswd\r" }
"$prompt" { set in_proc 0; return 0 }
}
exp_continue
@@ -448,8 +448,8 @@ proc do_enable { enauser enapasswd } {
send "enable\r"
expect {
- -re "$u_prompt" { send "$enauser\r"; exp_continue}
- -re "$e_prompt" { send "$enapasswd\r"; exp_continue}
+ -re "$u_prompt" { send -- "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send -- "$enapasswd\r"; exp_continue}
"#" { set prompt "#" }
"(enable)" { set prompt "> (enable) " }
denied { send_user "\nError: Check your Enable passwd\n"
@@ -477,25 +477,14 @@ proc run_commands { prompt command } {
regsub -all "\[)(]" $prompt {\\&} reprompt
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
-
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
- expect {
- -re "^\[^\n\r *]*$reprompt" {}
- -re "^\[^\n\r]*$reprompt." { exp_continue }
- -re "\[\n\r]+" { exp_continue }
- }
- }
- } else {
- send "[subst -nocommands $command]\r"
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
expect {
- -re "^\[^\n\r *]*$reprompt" {}
- -re "^\[^\n\r]*$reprompt." { exp_continue }
- -re "\[\n\r]+" { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" {}
+ -re "^\[^\n\r]*$reprompt." { exp_continue }
+ -re "\[\n\r]+" { exp_continue }
}
}
send "logout\r"
diff --git a/bin/brancid.in b/bin/brancid.in
index 27bb0ff..5419808 100644
--- a/bin/brancid.in
+++ b/bin/brancid.in
@@ -4,7 +4,7 @@
## hacked version of Hank's rancid - this one tries to deal with Bay's.
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/cat5rancid.in b/bin/cat5rancid.in
index 5c8b65d..9dc8103 100644
--- a/bin/cat5rancid.in
+++ b/bin/cat5rancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/clogin.in b/bin/clogin.in
index 4431f63..b3e4c81 100644
--- a/bin/clogin.in
+++ b/bin/clogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -114,21 +114,21 @@ for {set i 0} {$i < $argc} {incr i} {
# Username
} -u* -
-U* {
- if {! [ regexp .\[uU\](.+) $arg ignore user]} {
+ if {! [regexp .\[uU\](.+) $arg ignore user]} {
incr i
set username [ lindex $argv $i ]
}
# VTY Password
} -p* -
-P* {
- if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} {
+ if {! [regexp .\[pP\](.+) $arg ignore userpasswd]} {
incr i
set userpasswd [ lindex $argv $i ]
}
set do_passwd 0
# VTY Password
} -v* {
- if {! [ regexp .\[vV\](.+) $arg ignore passwd]} {
+ if {! [regexp .\[vV\](.+) $arg ignore passwd]} {
incr i
set passwd [ lindex $argv $i ]
}
@@ -140,14 +140,14 @@ for {set i 0} {$i < $argc} {incr i} {
# Enable Username
} -w* -
-W* {
- if {! [ regexp .\[wW\](.+) $arg ignore enauser]} {
+ if {! [regexp .\[wW\](.+) $arg ignore enauser]} {
incr i
set enausername [ lindex $argv $i ]
}
# Environment variable to pass to -s scripts
} -E*
{
- if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ if {[regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
send_user "\nError: invalid format for -E in $arg\n"
@@ -156,7 +156,7 @@ for {set i 0} {$i < $argc} {incr i} {
# Enable Password
} -e*
{
- if {! [ regexp .\[e\](.+) $arg ignore enapasswd]} {
+ if {! [regexp .\[e\](.+) $arg ignore enapasswd]} {
incr i
set enapasswd [ lindex $argv $i ]
}
@@ -164,7 +164,7 @@ for {set i 0} {$i < $argc} {incr i} {
# Command to run.
} -c* -
-C* {
- if {! [ regexp .\[cC\](.+) $arg ignore command]} {
+ if {! [regexp .\[cC\](.+) $arg ignore command]} {
incr i
set command [ lindex $argv $i ]
}
@@ -172,7 +172,7 @@ for {set i 0} {$i < $argc} {incr i} {
# Expect script to run.
} -s* -
-S* {
- if {! [ regexp .\[sS\](.+) $arg ignore sfile]} {
+ if {! [regexp .\[sS\](.+) $arg ignore sfile]} {
incr i
set sfile [ lindex $argv $i ]
}
@@ -184,28 +184,28 @@ for {set i 0} {$i < $argc} {incr i} {
# 'ssh -c' cypher type
} -y* -
-Y* {
- if {! [ regexp .\[eE\](.+) $arg ignore cypher]} {
+ if {! [regexp .\[eE\](.+) $arg ignore cypher]} {
incr i
set cypher [ lindex $argv $i ]
}
# alternate cloginrc file
} -f* -
-F* {
- if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
+ if {! [regexp .\[fF\](.+) $arg ignore password_file]} {
incr i
set password_file [ lindex $argv $i ]
}
# Timeout
} -t* -
-T* {
- if {! [ regexp .\[tT\](.+) $arg ignore timeout]} {
+ if {! [regexp .\[tT\](.+) $arg ignore timeout]} {
incr i
set timeout [ lindex $argv $i ]
}
# Command file
} -x* -
-X {
- if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} {
+ if {! [regexp .\[xX\](.+) $arg ignore cmd_file]} {
incr i
set cmd_file [ lindex $argv $i ]
}
@@ -259,7 +259,7 @@ proc label { host } {
}
# take host from ENV(TERM)
if [info exists env(TERM)] {
- if [regexp \^(xterm|vs) $env(TERM) ignore ] {
+ if [ regexp \^(xterm|vs) $env(TERM) ignore ] {
send_user "\033]1;[lindex [split $host "."] 0]\a"
send_user "\033]2;$host\a"
}
@@ -473,16 +473,19 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
}
eof { send_user "\nError: Couldn't login: $router\n"; wait; return 1 }
-nocase "unknown host\r" {
+ send_user "\nError: Unknown host $router\n";
catch {close}; catch {wait};
- send_user "\nError: Unknown host $router\n"; wait; return 1
+ return 1
}
"Host is unreachable" {
+ send_user "\nError: Host Unreachable: $router\n";
catch {close}; catch {wait};
- send_user "\nError: Host Unreachable: $router\n"; wait; return 1
+ return 1
}
"No address associated with name" {
+ send_user "\nError: Unknown host $router\n";
catch {close}; catch {wait};
- send_user "\nError: Unknown host $router\n"; wait; return 1
+ return 1
}
-re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
send "yes\r"
@@ -491,22 +494,26 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
-re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
send "no\r"
send_user "\nError: The host key for $router has changed. Update the SSH known_hosts file accordingly.\n"
- return 1 }
+ catch {close}; catch {wait};
+ return 1
+ }
-re "Offending key for .* \(yes\/no\)\?" {
send "no\r"
send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n"
- return 1 }
+ catch {close}; catch {wait};
+ return 1
+ }
-re "(denied|Sorry)" {
send_user "\nError: Check your passwd for $router\n"
catch {close}; catch {wait}; return 1
}
"Login failed" {
send_user "\nError: Check your passwd for $router\n"
- return 1
+ catch {close}; catch {wait}; return 1
}
-re "% (Bad passwords|Authentication failed)" {
send_user "\nError: Check your passwd for $router\n"
- return 1
+ catch {close}; catch {wait}; return 1
}
"Press any key to continue" {
# send_user "Pressing the ANY key\n"
@@ -525,20 +532,20 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
-re "@\[^\r\n]+ $p_prompt" {
# ssh pwd prompt
sleep 1
- send "$userpswd\r"
+ send -- "$userpswd\r"
exp_continue
}
-re "$u_prompt" {
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -562,8 +569,8 @@ proc do_enable { enauser enapasswd } {
send "enable\r"
expect {
- -re "$u_prompt" { send "$enauser\r"; exp_continue}
- -re "$e_prompt" { send "$enapasswd\r"; exp_continue}
+ -re "$u_prompt" { send -- "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send -- "$enapasswd\r"; exp_continue}
"#" { set prompt "#" }
"(enable)" { set prompt "> (enable) " }
-re "(denied|Sorry|Incorrect)" {
@@ -592,7 +599,7 @@ proc run_commands { prompt command } {
set in_proc 1
# If the prompt is (enable), then we are on a switch and the
- # command is "set length 0"; otherwise its "term length 0".
+ # command is "set length 0"; otherwise its "terminal length 0".
# skip if its an extreme (since the pager can not be disabled on a
# per-vty basis).
if { [ string compare "extreme" "$platform" ] } {
@@ -602,7 +609,7 @@ proc run_commands { prompt command } {
# subsequent expects to handle everything as normal.
set command "set logging session disable;$command"
} else {
- send "term length 0\r"
+ send "terminal length 0\r"
}
# escape any parens in the prompt, such as "(enable)"
regsub -all {[)(]} $prompt {\\&} reprompt
@@ -619,60 +626,29 @@ proc run_commands { prompt command } {
# this is the only way i see to get rid of more prompts in o/p..grrrrr
log_user 0
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
- # the pager can not be turned off on the PIX, so we have to look
- # for the "More" prompt. the extreme is equally obnoxious, with a
- # global switch in the config.
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
- expect {
- -re "\b+" { exp_continue }
- -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
+
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ # the pager can not be turned off on the PIX, so we have to look
+ # for the "More" prompt. the extreme is equally obnoxious, with a
+ # global switch in the config.
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
+ expect {
+ -re "\b+" { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
}
- -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "^--More--\[\r\n]+" { # specific match c1900 pager
- send " "
- exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
- send " "
- # bloody ^[[2K after " "
- expect {
- -re "^\[^\r\n]*\r" {}
- }
+ -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
exp_continue
}
- -re "^ *--More--\[^\n\r]*" {
+ -re "^--More--\[\r\n]+" { # specific match c1900 pager
send " "
- exp_continue }
- -re "^<-+ More -+>\[^\n\r]*" {
- send_user -- "$expect_out(buffer)"
- send " "
- exp_continue }
- }
- }
- } else {
- # the pager can not be turned off on the PIX, so we have to look
- # for the "More" prompt. the extreme is equally obnoxious, with a
- # global switch in the config.
- send "[subst -nocommands $command]\r"
- expect {
- -re "\b+" { exp_continue }
- -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
+ exp_continue
}
- -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "^--More--\r\n" { # specific match c1900 pager
- send " "
- exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
+ -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
+ exp_continue
+ }
+ -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
send " "
# bloody ^[[2K after " "
expect {
@@ -680,10 +656,10 @@ proc run_commands { prompt command } {
}
exp_continue
}
- -re "^ *--More--\[^\n\r]*" {
+ -re "^ *--More--\[^\n\r]*" {
send " "
exp_continue }
- -re "^<-+ More -+>\[^\n\r]*" {
+ -re "^<-+ More -+>\[^\n\r]*" {
send_user -- "$expect_out(buffer)"
send " "
exp_continue }
@@ -704,11 +680,16 @@ proc run_commands { prompt command } {
send -h "exit\r"
exp_continue;
}
+ "The system has unsaved changes" { # Force10 SFTOS
+ send "n\r"
+ exp_continue
+ }
"Would you like to save them now" { # Force10
send "n\r"
exp_continue
}
- "Configuration changes have occurred.*" { # Cisco CSS
+ -re "(Profile|Configuration) changes have occurred.*" {
+ # Cisco CSS
send "n\r"
exp_continue
}
@@ -811,7 +792,7 @@ foreach router [lrange $argv $i end] {
# Figure out prompts
set u_prompt [find userprompt $router]
if { "$u_prompt" == "" } {
- set u_prompt "(Username|Login|login|user name):"
+ set u_prompt "(Username|Login|login|user name|User):"
} else {
set u_prompt [join [lindex $u_prompt 0] ""]
}
@@ -877,7 +858,7 @@ foreach router [lrange $argv $i end] {
}
-re "^.+> \\\(enable\\\)" {
set junk $expect_out(0,string);
- regsub -all "\[\]\[]" $junk {\\&} prompt;
+ regsub -all "\[\]\[\(\)]" $junk {\\&} prompt;
}
}
@@ -888,12 +869,12 @@ foreach router [lrange $argv $i end] {
}
} elseif { $do_script } {
# If the prompt is (enable), then we are on a switch and the
- # command is "set length 0"; otherwise its "term length 0".
+ # command is "set length 0"; otherwise its "terminal length 0".
if [ regexp -- ".*> .*enable" "$prompt" ] {
send "set length 0\r"
send "set logging session disable\r"
} else {
- send "term length 0\r"
+ send "terminal length 0\r"
}
expect -re $prompt {}
source $sfile
diff --git a/bin/control_rancid.in b/bin/control_rancid.in
index 13b15f8..2e39068 100644
--- a/bin/control_rancid.in
+++ b/bin/control_rancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -419,8 +419,8 @@ do
done
echo
-# Make sure that no empty configs are accepted. Those that are non-empty
-# are renamed from device_name.new -> device_name.
+# Make sure that no empty/truncated configs are accepted. The remainder are
+# renamed from device_name.new -> device_name.
for router in `cat $devlistfile`
do
OFS=$IFS
@@ -433,9 +433,19 @@ do
then
rm -f $router.new
else
- mv $router.new $router
- if [ $? -ne 0 ]; then
- echo "Error: could not rename $router.new to $router"
+ lines=`awk '{if (/^([-*!;#]|\/\*)/) { next; } lines++; \
+ if (lines > 10) { print "1"; exit;}} \
+ END { if (lines < 10) {print "0";}}' $router.new`
+
+ if [ ! $lines ]
+ then
+ rm -f $router.new
+ else
+ mv $router.new $router
+ if [ $? -ne 0 ]; then
+ echo "Error: could not rename $router.new to $router"
+ rm -f $router.new
+ fi
fi
fi
done
diff --git a/bin/cssrancid.in b/bin/cssrancid.in
index e4614b5..898acc3 100644
--- a/bin/cssrancid.in
+++ b/bin/cssrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -231,7 +231,7 @@ sub ShowVersion {
}
if (/(\S+) Silicon\s*Switch Processor/) {
if (!defined($C0)) {
- $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");
+ $C0 = 1; ProcessHistory("COMMENTS","keysort","C0","!\n");
}
ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n");
$ssp = 1;
@@ -260,7 +260,7 @@ sub ShowVersion {
}
if(/^WARNING/) {
if (!defined($I0)) {
- $I0=1;
+ $I0 = 1;
ProcessHistory("COMMENTS","keysort","I0","!\n");
}
ProcessHistory("COMMENTS","keysort","I1","! $_");
@@ -269,7 +269,7 @@ sub ShowVersion {
ProcessHistory("COMMENTS","keysort","I1","! $_");
}
if (/^Configuration register is (.*)$/) {
- $config_register=$1;
+ $config_register = $1;
next;
}
}
@@ -317,7 +317,7 @@ sub ShowBoot {
next if (/\*\* BOOT CONFIG /);
next if /CONFGEN variable/;
if (!defined($H0)) {
- $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n");
+ $H0 = 1; ProcessHistory("COMMENTS","keysort","H0","!\n");
}
if ($type !~ /^(12[04]|7)/) {
if ($type !~ /^(29|35)00/) {
@@ -423,7 +423,7 @@ sub ShowRun {
ProcessHistory("","","","!isis password <removed>$2\n"); next;
}
if (/^\s+(domain-password|area-password) (\S+)( .*)?/
- && $filter_pwds >= 1) {
+ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>$2\n"); next;
}
# this is reversable, despite 'md5' in the cmd
@@ -588,8 +588,8 @@ sub DoNothing {print STDOUT;}
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);
-$cisco_cmds=join(";",@commands);
-$cmds_regexp=join("|",@commands);
+$cisco_cmds = join(";",@commands);
+$cmds_regexp = join("|",@commands);
if (length($host) == 0) {
if ($file) {
@@ -649,13 +649,13 @@ TOP: while(<INPUT>) {
NEXT:
tr/\015//d;
if (/\#\s?exit/) {
- $clean_run=1;
+ $clean_run = 1;
last;
}
if (/^Error:/) {
print STDOUT ("$host clogin error: $_");
print STDERR ("$host clogin error: $_") if ($debug);
- $clean_run=0;
+ $clean_run = 0;
last;
}
if (/#\s*($cmds_regexp)\s*$/) {
diff --git a/bin/elogin.in b/bin/elogin.in
index 0084a1d..e13f206 100644
--- a/bin/elogin.in
+++ b/bin/elogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -377,16 +377,16 @@ proc login { router user userpswd passwd prompt cmethod cyphertype } {
send_user "\nError: Unknown host\n"; wait; return 1
}
-re "$u_prompt" {
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -414,21 +414,10 @@ proc run_commands { prompt command } {
regsub -all "\[)(]" $prompt {\\&} reprompt
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
-
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
- expect {
- -re "^\[^\n\r]*$reprompt." { exp_continue }
- -re "^\[^\n\r *]*$reprompt" {}
- -re "\[\n\r]" { exp_continue }
- }
- }
- } else {
- send "[subst -nocommands $command]\r"
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
expect {
-re "^\[^\n\r]*$reprompt." { exp_continue }
-re "^\[^\n\r *]*$reprompt" {}
diff --git a/bin/erancid.in b/bin/erancid.in
index cfd58b7..c67f796 100644
--- a/bin/erancid.in
+++ b/bin/erancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/f10rancid.in b/bin/f10rancid.in
index d210959..8711133 100644
--- a/bin/f10rancid.in
+++ b/bin/f10rancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -39,7 +39,7 @@
## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
## POSSIBILITY OF SUCH DAMAGE.
-#
+#
# This version of rancid tries to deal with Force10s.
#
# RANCID - Really Awesome New Cisco confIg Differ
@@ -176,34 +176,34 @@ sub ShowVersion {
return(-1) if (/command authorization failed/i);
/ Type: / && chop && chop &&
- ProcessHistory("COMMENTS","keysort","A1","!$_\n");
+ ProcessHistory("COMMENTS","keysort","A1", "!$_\n");
/^.* Version.*$/ &&
- ProcessHistory("COMMENTS","keysort","F1","!Image: $_") && next;
+ ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
/^Build .*$/ &&
- ProcessHistory("COMMENTS","keysort","F1","!Image: $_") && next;
+ ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
/^System image file is "([^\"]*)"$/ &&
- ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") && next;
+ ProcessHistory("COMMENTS","keysort","F5", "!Image: $1\n") && next;
if (/^(.*\s+Processor)( \d)?:(.*) with (\d+[kK]?) bytes/) {
my($cpu) = "$1$2:$3";
my($mem) = int($4 / (1024 * 1024));
my($device) = "Force10";
ProcessHistory("COMMENTS","keysort","B1",
- "!Memory: $1$2: $mem" . "M\n");
+ "!Memory: $1$2: $mem" . "M\n");
ProcessHistory("COMMENTS","keysort","A3","!CPU: $cpu\n");
next;
}
# E-Series and C-Series use NVRAM
/^(\d+[kK]) bytes of non-volatile/ &&
- ProcessHistory("COMMENTS","keysort","B3","!Memory: NVRAM $1\n") &&
+ ProcessHistory("COMMENTS","keysort","B3", "!Memory: NVRAM $1\n") &&
next;
- # S-Series uses boot flash
+ # S-Series uses boot flash
/^(\d+[mM]) bytes of .oot..lash/ &&
- ProcessHistory("COMMENTS","keysort","B3","!Memory: Flash $1\n") &&
+ ProcessHistory("COMMENTS","keysort","B3", "!Memory: Flash $1\n") &&
next;
}
return(0);
@@ -217,7 +217,8 @@ sub ShowBoot {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
- return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /(Invalid input|Type help or )/;
+ return(1) if /( *\^$)/;
return(-1) if (/command authorization failed/i);
ProcessHistory("COMMENTS","keysort","H0","!Boot Variables: $_");
@@ -234,7 +235,8 @@ sub ShowChassis {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
- return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /(Invalid input|Type help or )/;
+ return(1) if /( *\^$)/;
return(-1) if (/command authorization failed/i);
/-----------------------------/ && next;
@@ -257,7 +259,7 @@ sub ShowChassis {
s/ (\d.*)<.*/$1/;
# C300 fan speed
s/FanNumber Speed Status/FanNumber Status/;
- s/(.*\d).*\d\d\d\d(.*)/$1 $2/;
+ s/( \d) *\d\d\d\d(.*)/$1 $2/;
ProcessHistory("COMMENTS","keysort","CHASSIS","!Chassis: $_");
}
ProcessHistory("COMMENTS","keysort","CHASSIS","!\n");
@@ -276,7 +278,7 @@ sub DirSlotN {
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type !~ /^(12[40]|7|36)/);
return(1) if /^\s*\^\s*$/;
- return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /(Invalid input|Type help or )/;
return(1) if /No such device/i;
return(1) if /\% ?Error: No such file or directory/;
@@ -312,7 +314,7 @@ sub ShowInventory {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
- return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /(Invalid input|Type help or )/;
return(-1) if (/command authorization failed/i);
/-----------------------------/ && next;
@@ -330,7 +332,7 @@ sub ShowVLAN {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
- return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /(Invalid input|Type help or )/;
return(-1) if (/command authorization failed/i);
ProcessHistory("COMMENTS","keysort","VLAN","!VLAN: $_");
}
@@ -363,6 +365,10 @@ sub WriteTerm {
ProcessHistory("ENABLE","","","!$1 <removed>\n");
next;
}
+ if (/^(enable restricted) / && $filter_pwds >= 2) {
+ ProcessHistory("ENABLE","","","!$1 <removed>\n");
+ next;
+ }
if (/^username (\S+)(\s.*)? secret /) {
if ($filter_pwds >= 2) {
ProcessHistory("USER","keysort","$1","!username $1$2 secret <removed>\n");
@@ -392,6 +398,9 @@ sub WriteTerm {
if (/^(ip ftp password) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
+ if (/^(ftp-server username.*password) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
if (/^( ip ospf authentication-key) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
@@ -496,7 +505,7 @@ sub WriteTerm {
# catch anything that wasnt matched above.
ProcessHistory("","","","$_");
# end of config. the ": " game is for the PIX
- if (/^end$/) {
+ if (/^end *$/) {
$found_end = 1;
return(0);
}
@@ -514,6 +523,7 @@ sub DoNothing {print STDOUT;}
{'dir flash:' => 'DirSlotN'},
{'dir slot0:' => 'DirSlotN'},
{'show chassis' => 'ShowChassis'},
+ {'show system' => 'ShowChassis'},
{'show inventory' => 'ShowInventory'},
{'show vlan' => 'ShowVLAN'},
{'show running' => 'WriteTerm'}
diff --git a/bin/f5rancid.in b/bin/f5rancid.in
new file mode 100644
index 0000000..ebf66c6
--- /dev/null
+++ b/bin/f5rancid.in
@@ -0,0 +1,645 @@
+#! @PERLV_PATH@
+##
+## $Id$
+##
+## @PACKAGE@ @VERSION@
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
+## All rights reserved.
+##
+## This code is derived from software contributed to and maintained by
+## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
+## Pete Whiting, Austin Schutz, and Andrew Fort.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+## 1. Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## 2. Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in the
+## documentation and/or other materials provided with the distribution.
+## 3. All advertising materials mentioning features or use of this software
+## must display the following acknowledgement:
+## This product includes software developed by Terrapin Communications,
+## Inc. and its contributors for RANCID.
+## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
+## contributors may be used to endorse or promote products derived from
+## this software without specific prior written permission.
+## 5. It is requested that non-binding fixes and modifications be contributed
+## back to Terrapin Communications, Inc.
+##
+## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
+## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
+## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+## POSSIBILITY OF SUCH DAMAGE.
+#
+# This version of rancid tries to deal with F5 BigIPs.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-dV] [-l] [-f filename | hostname]
+#
+use Getopt::Std;
+getopts('dflV');
+if ($opt_V) {
+ print "@PACKAGE@ @VERSION@\n";
+ exit(0);
+}
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # clogin timeout in seconds
+
+# force a terminal type so as not to confuse the POS
+$ENV{'TERM'} = "vt100";
+
+my(@commandtable, %commands, @commands);# command lists
+my($aclsort) = ("ipsort"); # ACL sorting mode
+my($filter_commstr); # SNMP community string filtering
+my($filter_pwds); # password filtering mode
+
+# This routine is used to print out the router configuration
+sub ProcessHistory {
+ my($new_hist_tag,$new_command,$command_string,@string) = (@_);
+ if ((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
+ && defined %history) {
+ print eval "$command \%history";
+ undef %history;
+ }
+ if (($new_hist_tag) && ($new_command) && ($command_string)) {
+ if ($history{$command_string}) {
+ $history{$command_string} = "$history{$command_string}@string";
+ } else {
+ $history{$command_string} = "@string";
+ }
+ } elsif (($new_hist_tag) && ($new_command)) {
+ $history{++$#history} = "@string";
+ } else {
+ print "@string";
+ }
+ $hist_tag = $new_hist_tag;
+ $command = $new_command;
+ 1;
+}
+
+sub numerically { $a <=> $b; }
+
+# This is a sort routine that will sort numerically on the
+# keys of a hash as if it were a normal array.
+sub keynsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort numerically keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# keys of a hash as if it were a normal array.
+sub keysort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# values of a hash as if it were a normal array.
+sub valsort{
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort values %lines) {
+ $sorted_lines[$i] = $key;
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a numerical sort routine (ascending).
+sub numsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $num (sort {$a <=> $b} keys %lines) {
+ $sorted_lines[$i] = $lines{$num};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# ip address when the ip address is anywhere in
+# the strings.
+sub ipsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $addr (sort sortbyipaddr keys %lines) {
+ $sorted_lines[$i] = $lines{$addr};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# These two routines will sort based upon IP addresses
+sub ipaddrval {
+ my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
+ $a[3] + 256 * ($a[2] + 256 * ($a[1] +256 * $a[0]));
+}
+sub sortbyipaddr {
+ &ipaddrval($a) <=> &ipaddrval($b);
+}
+
+# This routine parses "bigpipe base list"
+sub ShowBaseRun {
+ my($line) = (0);
+ print STDERR " In ShowBaseRun: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ if (!$line++) {
+ ProcessHistory("SHOWBASE","","","#\n#base:\n");
+ }
+ ProcessHistory("SHOWBASE","","","# $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "bigpipe db show"
+sub ShowDb {
+ my($line) = (0);
+ print STDERR " In ShowDb: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ if (!$line++) {
+ ProcessHistory("SHOWDB","","","#\n#database:\n");
+ }
+ /UCS.LoadTime/ && next;
+ /Configsync.LocalConfigTime/ && next;
+ /LTM.ConfigTime/ && next;
+
+ if (/^(snmp\..*\.community\..* =) (.+)/i) {
+ if ($filter_commstr) {
+ ProcessHistory("SHOWDB","","","# $1 <removed>\n") && next;
+ } else {
+ ProcessHistory("SHOWDB","","","# $1 $2\n") && next;
+ }
+ }
+
+ ProcessHistory("SHOWDB","","","# $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "cat /config/bigip.license"
+sub ShowLicense {
+ my($line) = (0);
+ print STDERR " In ShowLicense: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ # v9 software license does not have CR at EOF
+ s/^#-+($prompt.*)/$1/;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ if (!$line++) {
+ ProcessHistory("LICENSE","","","#\n#/config/bigip.license:\n");
+ }
+ ProcessHistory("LICENSE","","","# $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "bigpipe monitor list all"
+sub ShowMonitor {
+ my($line) = (0);
+ print STDERR " In ShowMonitor: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ if (!$line++) {
+ ProcessHistory("MONITOR","","","#\n");
+ }
+ if (/^(snmp\.[^ ]+\.community) = (.+)/i) {
+ if ($filter_commstr) {
+ ProcessHistory("SHOWDB","","","# $1 <removed>\n") && next;
+ } else {
+ ProcessHistory("SHOWDB","","","# $1 $2\n") && next;
+ }
+ }
+ if (/^(\s*)password / && $filter_pwds >= 1) {
+ ProcessHistory("LINE-PASS","","","# $1password <removed>\n");
+ next;
+ }
+
+ ProcessHistory("MONITOR","","","# $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "bigpipe platform"
+sub ShowPlatform {
+ print STDERR " In ShowPlatform: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ /fan speed/i && next;
+ /chassis temperature/i && next;
+ /degC/ && next;
+ s/^\|//;
+ /Type: / && ProcessHistory("COMMENTS","keysort","A0",
+ "#Chassis type: $'");
+
+ ProcessHistory("COMMENTS","keysort","B1","#$_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "bigpipe profile list"
+sub ShowProfile {
+ print STDERR " In ShowProfile: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("PROFILE","",""," $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "ls --full-time --color=never /config/ssl/ssl.key"
+sub ShowSslKey {
+ print STDERR " In ShowSslKey: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ # v9 software license does not have CR at EOF
+ s/^#-+($prompt.*)/$1/;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("SSLKEY","","","# $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "ls --full-time --color=never /config/ssl/ssl.crt"
+sub ShowSslCrt {
+ print STDERR " In ShowSslCrt: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ # v9 software license does not have CR at EOF
+ s/^#-+($prompt.*)/$1/;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("SSLCRT","","","# $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "bigpipe route static show"
+sub ShowRouteStatic {
+ print STDERR " In ShowRouteStatic: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("ROUTE","",""," $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "bigpipe version"
+sub ShowVersion {
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(-1) if (/command authorization failed/i);
+
+ /^kernel:/i && ($_ = <INPUT>) &&
+ ProcessHistory("COMMENTS","keysort","A3","#Image: Kernel: $_") &&
+ next;
+ if (/^package:/i) {
+ my($line);
+
+ while ($_ = <INPUT>) {
+ tr/\015//d;
+ last if (/:/);
+ last if (/^$prompt/);
+ chomp;
+ $line .= " $_";
+ }
+ ProcessHistory("COMMENTS","keysort","A2",
+ "#Image: Package:$line\n");
+ }
+
+ if (/:/) {
+ ProcessHistory("COMMENTS","keysort","C1","#$_");
+ } else {
+ ProcessHistory("COMMENTS","keysort","C1","#\t$_");
+ }
+ }
+ return(0);
+}
+
+# This routine processes a "bigpipe list"
+sub WriteTerm {
+ my($lines) = 0;
+ print STDERR " In WriteTerm: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ next if (/^\s*$/);
+ # end of config - hopefully. f5 does not have a reliable end-of-config
+ # tag.
+ if (/^$prompt/) {
+ $found_end++;
+ last;
+ }
+ return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
+ /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ # filter out any RCS/CVS tags to avoid confusing local CVS storage
+ s/\$(Revision|Id):/ $1:/;
+ $lines++;
+
+ if (/^(enable )?(password|passwd) / && $filter_pwds >= 1) {
+ ProcessHistory("ENABLE","","","! $1$2 <removed>\n");
+ next;
+ }
+ if (/^(enable secret) / && $filter_pwds >= 2) {
+ ProcessHistory("ENABLE","","","# $1 <removed>\n");
+ next;
+ }
+ if (/^username (\S+)(\s.*)? secret /) {
+ if ($filter_pwds >= 2) {
+ ProcessHistory("USER","keysort","$1","# username $1$2 secret <removed>\n");
+ } else {
+ ProcessHistory("USER","keysort","$1","$_");
+ }
+ next;
+ }
+ if (/^username (\S+)(\s.*)? password ((\d) \S+|\S+)/) {
+ if ($filter_pwds == 2) {
+ ProcessHistory("USER","keysort","$1","# username $1$2 password <removed>\n");
+ } elsif ($filter_pwds == 1 && $4 ne "5"){
+ ProcessHistory("USER","keysort","$1","# username $1$2 password <removed>\n");
+ } else {
+ ProcessHistory("USER","keysort","$1","$_");
+ }
+ next;
+ }
+ if (/^(\s*)password / && $filter_pwds >= 1) {
+ ProcessHistory("LINE-PASS","","","# $1password <removed>\n");
+ next;
+ }
+ if (/^\s*neighbor (\S*) password / && $filter_pwds >= 1) {
+ ProcessHistory("","","","# neighbor $1 password <removed>\n");
+ next;
+ }
+ # order logging statements
+ /^logging (\d+\.\d+\.\d+\.\d+)/ &&
+ ProcessHistory("LOGGING","ipsort","$1","$_") && next;
+ # order/prune tacacs/radius server statements
+ if (/^(tacacs-server|radius-server) key / && $filter_pwds >= 1) {
+ ProcessHistory("","","","# $1 key <removed>\n"); next;
+ }
+ # order clns host statements
+ /^clns host \S+ (\S+)/ &&
+ ProcessHistory("CLNS","keysort","$1","$_") && next;
+ # order alias statements
+ /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next;
+ # delete ntp auth password - this md5 is a reversable too
+ if (/^(ntp authentication-key \d+ md5) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","# $1 <removed>\n"); next;
+ }
+ # order ntp peers/servers
+ if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) {
+ $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5);
+ ProcessHistory("NTP","keysort",$sortkey,"$_");
+ next;
+ }
+ # order ip host line statements
+ /^ip host line(\d+)/ &&
+ ProcessHistory("IPHOST","numsort","$1","$_") && next;
+ # order ip nat source static statements
+ /^ip nat (\S+) source static (\S+)/ &&
+ ProcessHistory("IP NAT $1","ipsort","$2","$_") && next;
+
+ # catch anything that wasnt matched above.
+ ProcessHistory("","","","$_");
+ }
+
+ if ($lines < 3) {
+ printf(STDERR "ERROR: $host configuration appears truncated.\n");
+ $found_end = 0;
+ return(-1);
+ }
+
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+@commandtable = (
+ {'bigpipe version' => 'ShowVersion'},
+ {'bigpipe platform' => 'ShowPlatform'},
+ {'cat /config/bigip.license' => 'ShowLicense'},
+ {'bigpipe monitor list all' => 'ShowMonitor'},
+ {'bigpipe profile list' => 'ShowProfile'},
+ {'bigpipe base list' => 'ShowBaseRun'},
+ {'bigpipe db show' => 'ShowDb'},
+ {'bigpipe route static show' => 'ShowRouteStatic'},
+ {'ls --full-time --color=never /config/ssl/ssl.crt' => 'ShowSslCrt'},
+ {'ls --full-time --color=never /config/ssl/ssl.key' => 'ShowSslKey'},
+ {'bigpipe list' => 'WriteTerm'}
+);
+# Use an array to preserve the order of the commands and a hash for mapping
+# commands to the subroutine and track commands that have been completed.
+@commands = map(keys(%$_), @commandtable);
+%commands = map(%$_, @commandtable);
+
+$cisco_cmds=join(";",@commands);
+$cmds_regexp=join("|",@commands);
+
+if (length($host) == 0) {
+ if ($file) {
+ print(STDERR "Too few arguments: file name required\n");
+ exit(1);
+ } else {
+ print(STDERR "Too few arguments: host name required\n");
+ exit(1);
+ }
+}
+open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
+select(OUTPUT);
+# make OUTPUT unbuffered if debugging
+if ($debug) { $| = 1; }
+
+if ($file) {
+ print STDERR "opening file $host\n" if ($debug);
+ print STDOUT "opening file $host\n" if ($log);
+ open(INPUT,"<$host") || die "open failed for $host: $!\n";
+} else {
+ print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n";
+ }
+}
+
+# determine ACL sorting mode
+if ($ENV{"ACLSORT"} =~ /no/i) {
+ $aclsort = "";
+}
+# determine community string filtering mode
+if (defined($ENV{"NOCOMMSTR"}) &&
+ ($ENV{"NOCOMMSTR"} =~ /yes/i || $ENV{"NOCOMMSTR"} =~ /^$/)) {
+ $filter_commstr = 1;
+} else {
+ $filter_commstr = 0;
+}
+# determine password filtering mode
+if ($ENV{"FILTER_PWDS"} =~ /no/i) {
+ $filter_pwds = 0;
+} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
+ $filter_pwds = 2;
+} else {
+ $filter_pwds = 1;
+}
+
+ProcessHistory("","","","#RANCID-CONTENT-TYPE: bigip\n#\n");
+ProcessHistory("COMMENTS","keysort","A1","#\n");
+ProcessHistory("COMMENTS","keysort","B0","#\n");
+ProcessHistory("COMMENTS","keysort","C0","#\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/^Error:/) {
+ print STDOUT ("$host clogin error: $_");
+ print STDERR ("$host clogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]+#)/)[0];
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
+ }
+ print STDERR ("HIT COMMAND:$_") if ($debug);
+ if (! defined($commands{$cmd})) {
+ print STDERR "$host: found unexpected command - \"$cmd\"\n";
+ $clean_run = 0;
+ last TOP;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -1) {
+ $clean_run = 0;
+ last TOP;
+ }
+ }
+ if (/\#\s?exit$/) {
+ $clean_run=1;
+ last;
+ }
+}
+print STDOUT "Done $logincmd: $_\n" if ($log);
+# Flush History
+ProcessHistory("","","","");
+# Cleanup
+close(INPUT);
+close(OUTPUT);
+
+if (defined($ENV{NOPIPE})) {
+ unlink("$host.raw") if (! $debug);
+}
+
+# check for completeness
+if (scalar(%commands) || !$clean_run || !$found_end) {
+ if (scalar(%commands)) {
+ printf(STDOUT "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
+ printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
+ }
+ if (!$clean_run || !$found_end) {
+ print STDOUT "$host: End of run not found\n";
+ print STDERR "$host: End of run not found\n" if ($debug);
+ system("/usr/bin/tail -1 $host.new");
+ }
+ unlink "$host.new" if (! $debug);
+}
diff --git a/bin/flogin.in b/bin/flogin.in
index f15b1ec..483a06e 100644
--- a/bin/flogin.in
+++ b/bin/flogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -442,20 +442,20 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
-re "@\[^\r\n]+ $p_prompt" {
# ssh pwd prompt
sleep 1
- send "$userpswd\r"
+ send -- "$userpswd\r"
exp_continue
}
-re "$u_prompt" {
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -480,8 +480,8 @@ proc do_enable { enauser enapasswd } {
sleep 1; # dont go too fast for it now...
send "enable\r"
expect {
- -re "$u_prompt" { send "$enauser\r"; exp_continue}
- -re "$e_prompt" { send "$enapasswd\r"; exp_continue}
+ -re "$u_prompt" { send -- "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send -- "$enapasswd\r"; exp_continue}
"#" { set prompt "#" }
"(enable)" { set prompt "> (enable) " }
denied { send_user "\nError: Check your Enable passwd\n";
@@ -507,27 +507,16 @@ proc run_commands { prompt command } {
set in_proc 1
send "skip-page-display\r"
- expect $prompt {}
-
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
-
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst [lindex $commands $i]]\r"
- expect {
- -re "^\[^\n\r]*$prompt." { exp_continue }
- -re "^\[^\n\r *]*$prompt" {}
- -re "\[\n\r]" { exp_continue }
- }
- }
- } else {
- send "[subst $command]\r"
+ expect -re "$prompt" {}
+
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst [lindex $commands $i]]\r"
expect {
- -re "^\[^\n\r]*$prompt." { exp_continue }
- -re "^\[^\n\r *]*$prompt" {}
- -re "\[\n\r]" { exp_continue }
+ -re "^\[^\n\r]*$prompt." { exp_continue }
+ -re "^\[^\n\r *]*$prompt" {}
+ -re "\[\n\r]" { exp_continue }
}
}
send "exit\r"
@@ -671,6 +660,15 @@ foreach router [lrange $argv $i end] {
}
}
}
+ # we are logged in, now figure out the full prompt
+ send "\r"
+ expect {
+ -re "\[\r\n]+" { exp_continue; }
+ -re "^.+$prompt" { set junk $expect_out(0,string);
+ regsub -all "\[\]\[ ]" $junk {\\&} prompt;
+ }
+ }
+
if { $do_command } {
if {[run_commands $prompt $command]} {
@@ -680,7 +678,7 @@ foreach router [lrange $argv $i end] {
} elseif { $do_script } {
# fucking foundry
send "skip-page-display\r"
- expect $prompt {}
+ expect -re $prompt {}
source $sfile
catch {close};
} else {
diff --git a/bin/fnrancid.in b/bin/fnrancid.in
index 812d796..47f8444 100644
--- a/bin/fnrancid.in
+++ b/bin/fnrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/francid.in b/bin/francid.in
index 66a0e4f..9447a9d 100644
--- a/bin/francid.in
+++ b/bin/francid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -39,7 +39,7 @@
## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
## POSSIBILITY OF SUCH DAMAGE.
-#
+#
# Amazingly hacked version of Hank's rancid - this one tries to
# deal with foundrys and foundrys OEM'd by HP as Procurves.
#
@@ -245,7 +245,7 @@ sub ShowFlash {
print STDERR " In ShowFlash: $_" if ($debug);
while (<INPUT>) {
- tr/\015//d;
+ tr/\015//d;
last if (/^$prompt/);
next if (/^\s*$/);
ProcessHistory("FLASH","","","!Flash: $_");
@@ -264,6 +264,7 @@ sub ShowModule {
return(1) if (/Invalid input ->/);
next if (/^\s*$/);
next if (/:\s*$/);
+
ProcessHistory("MODULE","","","!Module: $_");
}
ProcessHistory("","","","!\n");
@@ -276,9 +277,11 @@ sub WriteTerm {
while (<INPUT>) {
tr/\015//d;
+ return(1) if (/Invalid input ->/);
+ return(0) if ($found_end); # Only do this routine once
last if (/^$prompt/);
- /Current configuration:/i && next;
+ /Current configuration\s*:/i && next;
/^ver \d+\.\d+/ && next;
/^module \d+ / && next;
@@ -363,6 +366,12 @@ sub WriteTerm {
ProcessHistory("","","","!$1 <removed>\n");
next;
}
+ # filter ssl secret
+ if (/^(crypto-ssl certificate generate secret_data)/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n");
+ next;
+ }
# reorder listing of ports in a vlan
if (/^ (?:un)?tagged ethe/) {
@@ -400,7 +409,8 @@ sub DoNothing {print STDOUT;}
{'show chassis' => 'ShowChassis'},
{'show module' => 'ShowModule'},
{'show flash' => 'ShowFlash'},
- {'write term' => 'WriteTerm'}
+ {'write term' => 'WriteTerm'},
+ {'show running-config' => 'WriteTerm'},
);
# Use an array to preserve the order of the commands and a hash for mapping
# commands to the subroutine and track commands that have been completed.
diff --git a/bin/hlogin.in b/bin/hlogin.in
index 1a7722c..e372fe0 100644
--- a/bin/hlogin.in
+++ b/bin/hlogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -79,7 +79,7 @@ set do_enapasswd 1
# attempt at platform switching.
set platform ""
#
-set send_human {.4 .4 .7 .3 5}
+set send_human {.2 .1 .4 .2 1}
# Find the user in the ENV, or use the unix userid.
if {[ info exists env(CISCO_USER) ]} {
@@ -426,13 +426,13 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
catch {close}; catch {wait};
send_user "\nError: Unknown host\n"; wait; return 1
}
- -re "$u_prompt" { send "$user\r"
+ -re "$u_prompt" { send -- "$user\r"
expect {
eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
"Login invalid" { send_user "\nError: Invalid login\n";
catch {close}; catch {wait};
return 1 }
- -re "$p_prompt" { send "$userpswd\r" }
+ -re "$p_prompt" { send -- "$userpswd\r" }
"$prompt" { set in_proc 0; return 0 }
"Press any key to continue" {
send " "
@@ -443,9 +443,9 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
}
-re "$p_prompt" {
if ![string compare $prog "ssh"] {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
expect {
eof { send_user "\nError: Couldn't login\n";
@@ -456,7 +456,7 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
send " ";
exp_continue
}
- -re "$e_prompt" { send "$enapasswd\r" }
+ -re "$e_prompt" { send -- "$enapasswd\r" }
"$prompt" { set in_proc 0;
return 0
}
@@ -483,8 +483,8 @@ proc do_enable { enauser enapasswd } {
send "enable\r"
expect {
- -re "$u_prompt" { send "$enauser\r"; exp_continue}
- -re "$e_prompt" { send "$enapasswd\r"; exp_continue}
+ -re "$u_prompt" { send -- "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send -- "$enapasswd\r"; exp_continue}
"#" { set prompt "#" }
"(enable)" { set prompt "> (enable) " }
denied { send_user "\nError: Check your Enable passwd\n"; return 1}
@@ -513,40 +513,43 @@ proc run_commands { prompt command } {
}
# this is the only way i see to get rid of more prompts in o/p..grrrrr
log_user 0
- # Is this a multi-command?
+
set commands [split $command \;]
set num_commands [llength $commands]
# if the pager can not be turned off, we have to look for the "More"
# prompt.
for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
expect {
- -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)" }
- -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
+ -re "^\[^\n\r *]*$reprompt" { catch {send_user -- "$expect_out(buffer)"} }
+ -re "^\[^\n\r]*$reprompt." { catch {send_user -- "$expect_out(buffer)"}
exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
+ -re "\[\n\r]+" { catch {send_user -- "$expect_out(buffer)"}
exp_continue }
-re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
send " "
expect {
# gag, 2 more prompts
-re "\[\r\n]*\r" {}
- -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" { send " "; exp_continue }
+ -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
+ catch {send " "};
+ exp_continue
+ }
}
exp_continue
}
- -re "^<-+ More -+>\[^\n\r]*" { send " "
+ -re "^<-+ More -+>\[^\n\r]*" { catch {send " "}
exp_continue }
- -re "^-+ MORE -+\[^\n\r]*" { send " "
+ -re "^-+ MORE -+\[^\n\r]*" { catch {send " "}
exp_continue }
# 3 flavours of the more prompt, first -More-, then --More-- (for
# cisco/riverhead AGM), then with more dashes.
- -re "^-More-\[^\n\r-]*" { send " "
+ -re "^-More-\[^\n\r-]*" { catch {send " "}
exp_continue }
- -re "^--More--\[^\n\r-]*" { send " "
+ -re "^--More--\[^\n\r-]*" { catch {send " "}
exp_continue }
-re "^---+More---+\[^\n\r]*" {
- send " "
+ catch {send " "}
exp_continue }
-re "\b+" { exp_continue }
}
@@ -555,20 +558,20 @@ proc run_commands { prompt command } {
send -h "exit\r"
expect {
"Do you want to save current configuration" {
- send "n\r"
+ catch {send "n\r"}
exp_continue
}
"Do you wish to save " {
- send "n\r"
+ catch {send "n\r"}
exp_continue
}
"Do you want to log out" {
- send "y\r"
+ catch {send "y\r"}
exp_continue
}
-re "\[\r\n]+" { exp_continue }
-re "^.+>" {
- send -h "exit\r"
+ catch {send -h "exit\r"}
exp_continue
}
timeout { catch {close}; catch {wait};
diff --git a/bin/hpuifilter.c b/bin/hpuifilter.c
index 38b4223..ab437f7 100644
--- a/bin/hpuifilter.c
+++ b/bin/hpuifilter.c
@@ -1,7 +1,7 @@
/*
* $Id$
*
- * Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+ * Copyright (c) 1997-2008 by Terrapin Communications, Inc.
* All rights reserved.
*
* This code is derived from software contributed to and maintained by
@@ -630,7 +630,7 @@ reapchild(int sig)
fprintf(stderr, "reap child %d\n", (int)pid);
if (pid == child) {
child = 0;
- sigrx = 0;
+ sigrx = 1;
break;
}
}
diff --git a/bin/hrancid.in b/bin/hrancid.in
index 5be2c8d..d1898db 100644
--- a/bin/hrancid.in
+++ b/bin/hrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -66,6 +66,8 @@ my($aclsort) = ("ipsort"); # ACL sorting mode
my($filter_commstr); # SNMP community string filtering
my($filter_pwds); # password filtering mode
+my($systeminfo) = 0; # show system-information
+
# This routine is used to print out the router configuration
sub ProcessHistory {
my($new_hist_tag,$new_command,$command_string,@string) = (@_);
@@ -203,16 +205,21 @@ sub ShowFlash {
return;
}
-# This routine parses "show system-information"
+# This routine parses "show system-information" or "show system information"
sub ShowSystem {
print STDERR " In ShowSystem: $_" if ($debug);
+ if ($systeminfo) {
+ $_ = <INPUT>;
+ return(0);
+ }
+
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(-1) if (/command authorization failed/i);
- return(-1) if /^(Invalid|Ambiguous) input:/i;
+ return(0) if /^(Invalid|Ambiguous) input:/i;
if (/memory\s+-\s+total\s+:\s+(\S+)/i) {
my($mem) = $1;
@@ -229,6 +236,8 @@ sub ShowSystem {
/rom\s+version\s+:\s+(\S+)/i &&
ProcessHistory("COMMENTS","keysort","C1",";Image: ROM $1\n");
}
+ $systeminfo = 1;
+
return(0);
}
@@ -462,6 +471,7 @@ sub DoNothing {print STDOUT;}
{'show version' => 'ShowVersion'},
{'show flash' => 'ShowFlash'},
{'show system-information' => 'ShowSystem'},
+ {'show system information' => 'ShowSystem'},
{'show module' => 'ShowModule'},
{'show stack' => 'ShowStack'},
{'write term' => 'WriteTerm'}
diff --git a/bin/htlogin.in b/bin/htlogin.in
index 2c04e6a..fbe8b1f 100644
--- a/bin/htlogin.in
+++ b/bin/htlogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -379,16 +379,16 @@ proc login { router user userpswd passwd prompt cmethod cyphertype } {
send_user "\nError: Unknown host\n"; wait; return 1
}
-re "$u_prompt" {
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -411,25 +411,14 @@ proc run_commands { prompt command } {
global in_proc
set in_proc 1
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
-
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[lindex $commands $i]\r"
- expect {
- -re "^\[^\n\r]*$prompt" {}
- -re "^\[^\n\r *]*$prompt" {}
- -re "\[\n\r]" { exp_continue }
- }
- }
- } else {
- send "$command\r"
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[lindex $commands $i]\r"
expect {
- -re "^\[^\n\r]*$prompt" {}
- -re "^\[^\n\r *]*$prompt" {}
- -re "\[\n\r]" { exp_continue }
+ -re "^\[^\n\r]*$prompt" {}
+ -re "^\[^\n\r *]*$prompt" {}
+ -re "\[\n\r]" { exp_continue }
}
}
send "exit\r"
diff --git a/bin/htrancid.in b/bin/htrancid.in
index 6819162..b79b5e9 100644
--- a/bin/htrancid.in
+++ b/bin/htrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/jerancid.in b/bin/jerancid.in
index 84d59ec..69d4697 100644
--- a/bin/jerancid.in
+++ b/bin/jerancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -427,6 +427,12 @@ sub WriteTerm {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
}
+ # mpls ldp encrypted password oscillates
+ if (/^(mpls ldp neighbor \S+ password)/) {
+ if ($filter_pwds >= 1 || /^mpls ldp neighbor \S+ password \d /) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+ }
# sort ip explicit-paths.
if (/^ip explicit-path name (\S+)/) {
@@ -470,9 +476,9 @@ sub WriteTerm {
/^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
ProcessHistory("ARP","$aclsort","$1","$_") && next;
- /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
- ProcessHistory("PACL $1 $3","$aclsort","$4","ip prefix-list $1 $3 $4$5\n")
- && next;
+ /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/
+ && ProcessHistory("PACL $1 $3","$aclsort","$4",
+ "ip prefix-list $1 $3 $4$5\n") && next;
# order/prune snmp-server host statements
diff --git a/bin/jlogin.in b/bin/jlogin.in
index e155d10..03c75a7 100644
--- a/bin/jlogin.in
+++ b/bin/jlogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -383,7 +383,7 @@ proc login { router user passwd cmethod cyphertype identfile} {
-re "Enter passphrase.*: " {
# sleep briefly to allow time for stty -echo
sleep 1
- send "$passphrase\r"
+ send -- "$passphrase\r"
exp_continue }
-re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
send "yes\r"
@@ -398,11 +398,11 @@ proc login { router user passwd cmethod cyphertype identfile} {
send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n"
return 1 }
-re "(Username|\[\r\n]login):" {
- send "$user\r"
+ send -- "$user\r"
exp_continue
}
"\[Pp]assword:" {
- sleep 1; send "$passwd\r"
+ sleep 1; send -- "$passwd\r"
exp_continue
}
-re "$prompt" { break; }
@@ -435,25 +435,14 @@ proc run_commands { prompt command } {
send "set cli screen-length 0\r"
expect -re $prompt {}
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
-
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[lindex $commands $i]\r"
- expect {
- -re "^\[^\n\r *]*$prompt $" {}
- -re "^\[^\n\r]*$prompt." { exp_continue }
- -re "(\r\n|\n)" { exp_continue }
- }
- }
- } else {
- send "$command\r"
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send "[lindex $commands $i]\r"
expect {
- -re "^\[^\n\r *]*$prompt $" {}
- -re "^\[^\n\r]*$prompt." { exp_continue }
- -re "(\r\n|\n)" { exp_continue }
+ -re "^\[^\n\r *]*$prompt $" {}
+ -re "^\[^\n\r]*$prompt." { exp_continue }
+ -re "(\r\n|\n)" { exp_continue }
}
}
send "quit\r"
diff --git a/bin/jrancid.in b/bin/jrancid.in
index 309cef9..c34286f 100644
--- a/bin/jrancid.in
+++ b/bin/jrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/lg.cgi.in b/bin/lg.cgi.in
index d1efaea..6e8bfc3 100644
--- a/bin/lg.cgi.in
+++ b/bin/lg.cgi.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/lgform.cgi.in b/bin/lgform.cgi.in
index 18f1c54..052f0cc 100644
--- a/bin/lgform.cgi.in
+++ b/bin/lgform.cgi.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/mrancid.in b/bin/mrancid.in
index 19ffadb..b828e92 100644
--- a/bin/mrancid.in
+++ b/bin/mrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/mrvlogin.in b/bin/mrvlogin.in
new file mode 100644
index 0000000..2de0c28
--- /dev/null
+++ b/bin/mrvlogin.in
@@ -0,0 +1,774 @@
+#! @EXPECT_PATH@ --
+##
+## $Id$
+##
+## @PACKAGE@ @VERSION@
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
+## All rights reserved.
+##
+## This code is derived from software contributed to and maintained by
+## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
+## Pete Whiting, Austin Schutz, and Andrew Fort.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+## 1. Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## 2. Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in the
+## documentation and/or other materials provided with the distribution.
+## 3. All advertising materials mentioning features or use of this software
+## must display the following acknowledgement:
+## This product includes software developed by Terrapin Communications,
+## Inc. and its contributors for RANCID.
+## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
+## contributors may be used to endorse or promote products derived from
+## this software without specific prior written permission.
+## 5. It is requested that non-binding fixes and modifications be contributed
+## back to Terrapin Communications, Inc.
+##
+## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
+## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
+## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+## POSSIBILITY OF SUCH DAMAGE.
+#
+# The expect login scripts were based on Erik Sherk's gwtn, by permission.
+#
+# clogin - Cisco login
+#
+# Most options are intuitive for logging into a Cisco router.
+# The default is to enable (thus -noenable). Some folks have
+# setup tacacs to have a user login at priv-lvl = 15 (enabled)
+# so the -autoenable flag was added for this case (don't go through
+# the process of enabling and the prompt will be the "#" prompt.
+# The default username password is the same as the vty password.
+#
+
+# Usage line
+set usage "Usage: $argv0 \[-dV\] \[-autoenable\] \[-noenable\] \[-c command\] \
+\[-Evar=x\] \[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \
+\[-s script-file\] \[-t timeout\] \[-u username\] \
+\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \
+\[-y ssh_cypher_type\] router \[router...\]\n"
+
+# env(CLOGIN) may contain:
+# x == do not set xterm banner or name
+
+# Password file
+set password_file $env(HOME)/.cloginrc
+# Default is to login to the router
+set do_command 0
+set do_script 0
+# The default is to automatically enable
+set avenable 1
+# The default is that you login non-enabled (tacacs can have you login already
+# enabled)
+set avautoenable 0
+# The default is to look in the password file to find the passwords. This
+# tracks if we receive them on the command line.
+set do_passwd 1
+set do_enapasswd 1
+#
+set send_human {.4 .4 .7 .3 5}
+
+# Find the user in the ENV, or use the unix userid.
+if {[ info exists env(CISCO_USER) ]} {
+ set default_user $env(CISCO_USER)
+} elseif {[ info exists env(USER) ]} {
+ set default_user $env(USER)
+} elseif {[ info exists env(LOGNAME) ]} {
+ set default_user $env(LOGNAME)
+} else {
+ # This uses "id" which I think is portable. At least it has existed
+ # (without options) on all machines/OSes I've been on recently -
+ # unlike whoami or id -nu.
+ if [ catch {exec id} reason ] {
+ send_error "\nError: could not exec id: $reason\n"
+ exit 1
+ }
+ regexp {\(([^)]*)} "$reason" junk default_user
+}
+if {[ info exists env(CLOGINRC) ]} {
+ set password_file $env(CLOGINRC)
+}
+
+# Sometimes routers take awhile to answer (the default is 10 sec)
+set timeout 45
+
+# Process the command line
+for {set i 0} {$i < $argc} {incr i} {
+ set arg [lindex $argv $i]
+
+ switch -glob -- $arg {
+ # Expect debug mode
+ -d* {
+ exp_internal 1
+ # Username
+ } -u* -
+ -U* {
+ if {! [regexp .\[uU\](.+) $arg ignore user]} {
+ incr i
+ set username [ lindex $argv $i ]
+ }
+ # VTY Password
+ } -p* -
+ -P* {
+ if {! [regexp .\[pP\](.+) $arg ignore userpasswd]} {
+ incr i
+ set userpasswd [ lindex $argv $i ]
+ }
+ set do_passwd 0
+ # VTY Password
+ } -v* {
+ if {! [regexp .\[vV\](.+) $arg ignore passwd]} {
+ incr i
+ set passwd [ lindex $argv $i ]
+ }
+ set do_passwd 0
+ # Version string
+ } -V* {
+ send_user "@PACKAGE@ @VERSION@\n"
+ exit 0
+ # Enable Username
+ } -w* -
+ -W* {
+ if {! [regexp .\[wW\](.+) $arg ignore enauser]} {
+ incr i
+ set enausername [ lindex $argv $i ]
+ }
+ # Environment variable to pass to -s scripts
+ } -E*
+ {
+ if {[regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ set E$varname $varvalue
+ } else {
+ send_user "\nError: invalid format for -E in $arg\n"
+ exit 1
+ }
+ # Enable Password
+ } -e*
+ {
+ if {! [regexp .\[e\](.+) $arg ignore enapasswd]} {
+ incr i
+ set enapasswd [ lindex $argv $i ]
+ }
+ set do_enapasswd 0
+ # Command to run.
+ } -c* -
+ -C* {
+ if {! [regexp .\[cC\](.+) $arg ignore command]} {
+ incr i
+ set command [ lindex $argv $i ]
+ }
+ set do_command 1
+ # Expect script to run.
+ } -s* -
+ -S* {
+ if {! [regexp .\[sS\](.+) $arg ignore sfile]} {
+ incr i
+ set sfile [ lindex $argv $i ]
+ }
+ if { ! [ file readable $sfile ] } {
+ send_user "\nError: Can't read $sfile\n"
+ exit 1
+ }
+ set do_script 1
+ # 'ssh -c' cypher type
+ } -y* -
+ -Y* {
+ if {! [regexp .\[eE\](.+) $arg ignore cypher]} {
+ incr i
+ set cypher [ lindex $argv $i ]
+ }
+ # alternate cloginrc file
+ } -f* -
+ -F* {
+ if {! [regexp .\[fF\](.+) $arg ignore password_file]} {
+ incr i
+ set password_file [ lindex $argv $i ]
+ }
+ # Timeout
+ } -t* -
+ -T* {
+ if {! [regexp .\[tT\](.+) $arg ignore timeout]} {
+ incr i
+ set timeout [ lindex $argv $i ]
+ }
+ # Command file
+ } -x* -
+ -X {
+ if {! [regexp .\[xX\](.+) $arg ignore cmd_file]} {
+ incr i
+ set cmd_file [ lindex $argv $i ]
+ }
+ if [ catch {set cmd_fd [open $cmd_file r]} reason ] {
+ send_user "\nError: $reason\n"
+ exit 1
+ }
+ set cmd_text [read $cmd_fd]
+ close $cmd_fd
+ set command [join [split $cmd_text \n] \;]
+ set do_command 1
+ # Do we enable?
+ } -noenable {
+ set avenable 0
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ set avautoenable 1
+ set avenable 0
+ } -* {
+ send_user "\nError: Unknown argument! $arg\n"
+ send_user $usage
+ exit 1
+ } default {
+ break
+ }
+ }
+}
+# Process routers...no routers listed is an error.
+if { $i == $argc } {
+ send_user "\nError: $usage"
+}
+
+# Only be quiet if we are running a script (it can log its output
+# on its own)
+if { $do_script } {
+ log_user 0
+} else {
+ log_user 1
+}
+
+#
+# Done configuration/variable setting. Now run with it...
+#
+
+# Sets Xterm title if interactive...if its an xterm and the user cares
+proc label { host } {
+ global env
+ # if CLOGIN has an 'x' in it, don't set the xterm name/banner
+ if [info exists env(CLOGIN)] {
+ if {[string first "x" $env(CLOGIN)] != -1} { return }
+ }
+ # take host from ENV(TERM)
+ if [info exists env(TERM)] {
+ if [ regexp \^(xterm|vs) $env(TERM) ignore ] {
+ send_user "\033]1;[lindex [split $host "."] 0]\a"
+ send_user "\033]2;$host\a"
+ }
+ }
+}
+
+# This is a helper function to make the password file easier to
+# maintain. Using this the password file has the form:
+# add password sl* pete cow
+# add password at* steve
+# add password * hanky-pie
+proc add {var args} { global int_$var ; lappend int_$var $args}
+proc include {args} {
+ global env
+ regsub -all "(^{|}$)" $args {} args
+ if { [ regexp "^/" $args ignore ] == 0 } {
+ set args $env(HOME)/$args
+ }
+ source_password_file $args
+}
+
+proc find {var router} {
+ upvar int_$var list
+ if { [info exists list] } {
+ foreach line $list {
+ if { [string match [lindex $line 0] $router ] } {
+ return [lrange $line 1 end]
+ }
+ }
+ }
+ return {}
+}
+
+# Loads the password file. Note that as this file is tcl, and that
+# it is sourced, the user better know what to put in there, as it
+# could install more than just password info... I will assume however,
+# that a "bad guy" could just as easy put such code in the clogin
+# script, so I will leave .cloginrc as just an extention of that script
+proc source_password_file { password_file } {
+ global env
+ if { ! [file exists $password_file] } {
+ send_user "\nError: password file ($password_file) does not exist\n"
+ exit 1
+ }
+ file stat $password_file fileinfo
+ if { [expr ($fileinfo(mode) & 007)] != 0000 } {
+ send_user "\nError: $password_file must not be world readable/writable\n"
+ exit 1
+ }
+ if [ catch {source $password_file} reason ] {
+ send_user "\nError: $reason\n"
+ exit 1
+ }
+}
+
+# Log into the router.
+# returns: 0 on success, 1 on failure
+proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
+ global command spawn_id in_proc do_command do_script
+ global prompt u_prompt p_prompt e_prompt sshcmd
+ set in_proc 1
+ set uprompt_seen 0
+
+ # try each of the connection methods in $cmethod until one is successful
+ set progs [llength $cmethod]
+ foreach prog [lrange $cmethod 0 end] {
+ incr progs -1
+ if [string match "telnet*" $prog] {
+ regexp {telnet(:([^[:space:]]+))*} $prog methcmd suffix port
+ if {"$port" == ""} {
+ set retval [ catch {spawn telnet $router} reason ]
+ } else {
+ set retval [ catch {spawn telnet $router $port} reason ]
+ }
+ if { $retval } {
+ send_user "\nError: telnet failed: $reason\n"
+ return 1
+ }
+ } elseif [string match "ssh*" $prog] {
+ regexp {ssh(:([^[:space:]]+))*} $prog methcmd suffix port
+ if {"$port" == ""} {
+ set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ]
+
+ } else {
+ set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user -p $port $router} reason ]
+ }
+ if { $retval } {
+ send_user "\nError: $sshcmd failed: $reason\n"
+ return 1
+ }
+ } else {
+ send_user "\nError: unknown connection method: $prog\n"
+ return 1
+ }
+ sleep 0.3
+
+ # This helps cleanup each expect clause.
+ expect_after {
+ timeout {
+ send_user "\nError: TIMEOUT reached\n"
+ catch {close}; catch {wait};
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ } eof {
+ send_user "\nError: EOF received\n"
+ catch {close}; catch {wait};
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ }
+ }
+
+ # Here we get a little tricky. There are several possibilities:
+ # the router can ask for a username and passwd and then
+ # talk to the TACACS server to authenticate you, or if the
+ # TACACS server is not working, then it will use the enable
+ # passwd. Or, the router might not have TACACS turned on,
+ # then it will just send the passwd.
+ # if telnet fails with connection refused, try ssh
+ expect {
+ -re "(Connection refused|Secure connection \[^\n\r]+ refused)" {
+ catch {close}; catch {wait};
+ if !$progs {
+ send_user "\nError: Connection Refused ($prog): $router\n"
+ return 1
+ }
+ }
+ -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
+ catch {close}; catch {wait};
+ if !$progs {
+ send_user "\nError: Connection closed ($prog): $router\n"
+ return 1
+ }
+ }
+ eof { send_user "\nError: Couldn't login: $router\n"; wait; return 1 }
+ -nocase "unknown host\r" {
+ send_user "\nError: Unknown host $router\n";
+ catch {close}; catch {wait};
+ return 1
+ }
+ "Host is unreachable" {
+ send_user "\nError: Host Unreachable: $router\n";
+ catch {close}; catch {wait};
+ return 1
+ }
+ "No address associated with name" {
+ send_user "\nError: Unknown host $router\n";
+ catch {close}; catch {wait};
+ return 1
+ }
+ -re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
+ send "yes\r"
+ send_user "\nHost $router added to the list of known hosts.\n"
+ exp_continue }
+ -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
+ send "no\r"
+ send_user "\nError: The host key for $router has changed. Update the SSH known_hosts file accordingly.\n"
+ catch {close}; catch {wait};
+ return 1
+ }
+ -re "Offending key for .* \(yes\/no\)\?" {
+ send "no\r"
+ send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n"
+ catch {close}; catch {wait};
+ return 1
+ }
+ -re "(denied|Sorry)" {
+ send_user "\nError: Check your passwd for $router\n"
+ catch {close}; catch {wait}; return 1
+ }
+ "Login failed" {
+ send_user "\nError: Check your passwd for $router\n"
+ catch {close}; catch {wait}; return 1
+ }
+ -re "% (Bad passwords|Authentication failed)" {
+ send_user "\nError: Check your passwd for $router\n"
+ catch {close}; catch {wait}; return 1
+ }
+ "Press any key to continue" {
+ # send_user "Pressing the ANY key\n"
+ send "\r"
+ exp_continue
+ }
+ -re "Enter Selection: " {
+ # Catalyst 1900s have some lame menu. Enter
+ # K to reach a command-line.
+ send "K\r"
+ exp_continue
+ }
+ -re "Last login:" {
+ exp_continue
+ }
+ -re "@\[^\r\n]+ $p_prompt" {
+ # ssh pwd prompt
+ sleep 1
+ send -h -- "$userpswd\r"
+ exp_continue
+ }
+ -re "$u_prompt" {
+ send -h -- "$user\r"
+ set uprompt_seen 1
+ exp_continue
+ }
+ -re "$p_prompt" {
+ sleep 1
+ if {$uprompt_seen == 1} {
+ send -h -- "$userpswd\r"
+ } else {
+ send -h -- "$passwd\r"
+ }
+ exp_continue
+ }
+ -re "$prompt" { break; }
+ "Login invalid" {
+ send_user "\nError: Invalid login: $router\n";
+ catch {close}; catch {wait}; return 1
+ }
+ -re "\[^\r\n]\[\r\n]+" { exp_continue }
+ }
+ }
+
+ set in_proc 0
+ return 0
+}
+
+# Enable
+proc do_enable { enauser enapasswd } {
+ global prompt in_proc
+ global u_prompt e_prompt
+ set in_proc 1
+
+ send -h "enable\r"
+ expect {
+ -re "$u_prompt" { send -h -- "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send -h -- "$enapasswd\r"; exp_continue}
+ "#" { set prompt "#" }
+ -re "(denied|Sorry|Incorrect)" {
+ # % Access denied - from local auth and poss. others
+ send_user "\nError: Check your Enable passwd\n";
+ return 1
+ }
+ "% Error in authentication" {
+ send_user "\nError: Check your Enable passwd\n"
+ return 1
+ }
+ "% Bad passwords" {
+ send_user "\nError: Check your Enable passwd\n"
+ return 1
+ }
+ }
+ # We set the prompt variable (above) so script files don't need
+ # to know what it is.
+ set in_proc 0
+ return 0
+}
+
+# Run commands given on the command line.
+proc run_commands { prompt command } {
+ global in_proc
+ set in_proc 1
+
+ send -h "terminal length 0\r"
+ # escape any parens in the prompt, such as "(enable)"
+ regsub -all {[)(]} $prompt {\\&} reprompt
+ # match cisco config mode prompts too, such as router(config-if)#,
+ # but catalyst does not change in this fashion.
+ regsub -all {^(.{1,11}).*([#>])$} $reprompt {\1([^#>\r\n]+)?\2(\\([^)\\r\\n]+\\))?} reprompt
+ expect {
+ -re $reprompt {}
+ -re "\[\n\r]+" { exp_continue }
+ }
+
+ # this is the only way i see to get rid of more prompts in o/p..grrrrr
+ log_user 0
+
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ # the pager can not be turned off on the PIX, so we have to look
+ # for the "More" prompt. the extreme is equally obnoxious, with a
+ # global switch in the config.
+ # XXX I think the pager can be turned off and this is just an artifact of
+ # clogin
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -h -- "[subst -nocommands [lindex $commands $i]]\r"
+ expect {
+ -re "\b+" { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
+ }
+ -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
+ exp_continue }
+ -re "^--More--\[\r\n]+" { # specific match c1900 pager
+ send " "
+ exp_continue }
+ -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
+ exp_continue }
+ -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
+ send " "
+ # bloody ^[[2K after " "
+ expect {
+ -re "^\[^\r\n]*\r" {}
+ }
+ exp_continue
+ }
+ -re "^ *--More--\[^\n\r]*" {
+ send " "
+ exp_continue }
+ -re "^<-+ More -+>\[^\n\r]*" {
+ send_user -- "$expect_out(buffer)"
+ send " "
+ exp_continue }
+ }
+ }
+ log_user 1
+
+ send -h "exit\r"
+ expect {
+ -re "^\[^\n\r *]*$reprompt" {
+ # the Cisco CE and Jnx ERX
+ # return to non-enabled mode
+ # on exit in enabled mode.
+ send -h "exit\r"
+ exp_continue;
+ }
+ "Would you like to save them now" { # Force10
+ send "n\r"
+ exp_continue
+ }
+ "Configuration changes have occurred.*" { # Cisco CSS
+ send "n\r"
+ exp_continue
+ }
+ "Do you wish to save your configuration changes" {
+ send "n\r"
+ exp_continue
+ }
+ -re "\[\n\r]+" { exp_continue }
+ timeout { catch {close}; catch {wait};
+ return 0
+ }
+ eof { return 0 }
+ }
+ set in_proc 0
+}
+
+#
+# For each router... (this is main loop)
+#
+source_password_file $password_file
+set in_proc 0
+set exitval 0
+foreach router [lrange $argv $i end] {
+ set router [string tolower $router]
+ send_user -- "$router\n"
+
+ # Figure out the prompt.
+ # autoenable is off by default. If we have it defined, it was done
+ # on the command line. If it is not specifically set on the command
+ # line, check the password file.
+ if $avautoenable {
+ set autoenable 1
+ set enable 0
+ set prompt "#\[^\[:digit:]]"
+ } else {
+ set ae [find autoenable $router]
+ if { "$ae" == "1" } {
+ set autoenable 1
+ set enable 0
+ set prompt "#\[^\[:digit:]]"
+ } else {
+ set autoenable 0
+ set enable $avenable
+ set prompt ">"
+ }
+ }
+
+ # look for noenable option in .cloginrc
+ if { [find noenable $router] != "" } {
+ set enable 0
+ }
+
+ # Figure out passwords
+ if { $do_passwd || $do_enapasswd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ send_user -- "\nError: no password for $router in $password_file.\n"
+ continue
+ }
+ if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
+ send_user -- "\nError: no enable password for $router in $password_file.\n"
+ continue
+ }
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
+ } else {
+ set passwd $userpasswd
+ set enapasswd $enapasswd
+ }
+
+ # Figure out username
+ if {[info exists username]} {
+ # command line username
+ set ruser $username
+ } else {
+ set ruser [join [find user $router] ""]
+ if { "$ruser" == "" } { set ruser $default_user }
+ }
+
+ # Figure out username's password (if different from the vty password)
+ if {[info exists userpasswd]} {
+ # command line username
+ set userpswd $userpasswd
+ } else {
+ set userpswd [join [find userpassword $router] ""]
+ if { "$userpswd" == "" } { set userpswd $passwd }
+ }
+
+ # Figure out enable username
+ if {[info exists enausername]} {
+ # command line enausername
+ set enauser $enausername
+ } else {
+ set enauser [join [find enauser $router] ""]
+ if { "$enauser" == "" } { set enauser $ruser }
+ }
+
+ # Figure out prompts
+ set u_prompt [find userprompt $router]
+ if { "$u_prompt" == "" } {
+ set u_prompt "(Username|Login|login|user name):"
+ } else {
+ set u_prompt [join [lindex $u_prompt 0] ""]
+ }
+ set p_prompt [find passprompt $router]
+ if { "$p_prompt" == "" } {
+ set p_prompt "(\[Pp]assword|passwd):"
+ } else {
+ set p_prompt [join [lindex $p_prompt 0] ""]
+ }
+ set e_prompt [find enableprompt $router]
+ if { "$e_prompt" == "" } {
+ set e_prompt "\[Pp]assword:"
+ } else {
+ set e_prompt [join [lindex $e_prompt 0] ""]
+ }
+
+ # Figure out cypher type
+ if {[info exists cypher]} {
+ # command line cypher type
+ set cyphertype $cypher
+ } else {
+ set cyphertype [find cyphertype $router]
+ if { "$cyphertype" == "" } { set cyphertype "3des" }
+ }
+
+ # Figure out connection method
+ set cmethod [find method $router]
+ if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} }
+
+ # Figure out the SSH executable name
+ set sshcmd [find sshcmd $router]
+ if { "$sshcmd" == "" } { set sshcmd {ssh} }
+
+ # Login to the router
+ if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype]} {
+ incr exitval
+ # if login failed, move on to the next device
+ continue
+ }
+ if { $enable } {
+ if {[do_enable $enauser $enapasswd]} {
+ if { $do_command || $do_script } {
+ incr exitval
+ catch {close}; catch {wait};
+ continue
+ }
+ }
+ }
+ # we are logged in, now figure out the full prompt
+ send "\r"
+ expect {
+ -re "\[\r\n]+" { exp_continue; }
+ -re "^.+$prompt" { set junk $expect_out(0,string);
+ regsub -all "\[\]\[]" $junk {\\&} prompt;
+ }
+ }
+
+ if { $do_command } {
+ if {[run_commands $prompt $command]} {
+ incr exitval
+ continue
+ }
+ } elseif { $do_script } {
+ send -h "terminal length 0\r"
+ expect -re $prompt {}
+ source $sfile
+ catch {close};
+ } else {
+ label $router
+ log_user 1
+ interact
+ }
+
+ # End of for each router
+ catch {wait};
+ sleep 0.3
+}
+exit $exitval
diff --git a/bin/mrvrancid.in b/bin/mrvrancid.in
new file mode 100644
index 0000000..3288a31
--- /dev/null
+++ b/bin/mrvrancid.in
@@ -0,0 +1,522 @@
+#! @PERLV_PATH@
+##
+## $Id$
+##
+## @PACKAGE@ @VERSION@
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
+## All rights reserved.
+##
+## This code is derived from software contributed to and maintained by
+## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
+## Pete Whiting, Austin Schutz, and Andrew Fort.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+## 1. Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## 2. Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in the
+## documentation and/or other materials provided with the distribution.
+## 3. All advertising materials mentioning features or use of this software
+## must display the following acknowledgement:
+## This product includes software developed by Terrapin Communications,
+## Inc. and its contributors for RANCID.
+## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
+## contributors may be used to endorse or promote products derived from
+## this software without specific prior written permission.
+## 5. It is requested that non-binding fixes and modifications be contributed
+## back to Terrapin Communications, Inc.
+##
+## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
+## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
+## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+## POSSIBILITY OF SUCH DAMAGE.
+#
+# Amazingly hacked version of Hank's rancid - this one tries to
+# deal with MegaVision MRV.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-dV] [-l] [-f filename | hostname]
+#
+use Getopt::Std;
+getopts('dflV');
+if ($opt_V) {
+ print "@PACKAGE@ @VERSION@\n";
+ exit(0);
+}
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$ios = "IOS";
+$clean_run = 0;
+$found_end = 0;
+$found_version = 0;
+$found_env = 0;
+$found_diag = 0;
+$timeo = 90; # clogin timeout in seconds
+
+# force a terminal type so as not to confuse the POS
+$ENV{'TERM'} = "vt100";
+
+my(@commandtable, %commands, @commands);# command lists
+my($aclsort) = ("ipsort"); # ACL sorting mode
+my($filter_commstr); # SNMP community string filtering
+my($filter_pwds); # password filtering mode
+
+# This routine is used to print out the router configuration
+sub ProcessHistory {
+ my($new_hist_tag,$new_command,$command_string,@string) = (@_);
+ if ((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
+ && defined %history) {
+ print eval "$command \%history";
+ undef %history;
+ }
+ if (($new_hist_tag) && ($new_command) && ($command_string)) {
+ if ($history{$command_string}) {
+ $history{$command_string} = "$history{$command_string}@string";
+ } else {
+ $history{$command_string} = "@string";
+ }
+ } elsif (($new_hist_tag) && ($new_command)) {
+ $history{++$#history} = "@string";
+ } else {
+ print "@string";
+ }
+ $hist_tag = $new_hist_tag;
+ $command = $new_command;
+ 1;
+}
+
+sub numerically { $a <=> $b; }
+
+# This is a sort routine that will sort numerically on the
+# keys of a hash as if it were a normal array.
+sub keynsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort numerically keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# keys of a hash as if it were a normal array.
+sub keysort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# values of a hash as if it were a normal array.
+sub valsort{
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort values %lines) {
+ $sorted_lines[$i] = $key;
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a numerical sort routine (ascending).
+sub numsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $num (sort {$a <=> $b} keys %lines) {
+ $sorted_lines[$i] = $lines{$num};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# ip address when the ip address is anywhere in
+# the strings.
+sub ipsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $addr (sort sortbyipaddr keys %lines) {
+ $sorted_lines[$i] = $lines{$addr};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# These two routines will sort based upon IP addresses
+sub ipaddrval {
+ my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
+ $a[3] + 256 * ($a[2] + 256 * ($a[1] +256 * $a[0]));
+}
+sub sortbyipaddr {
+ &ipaddrval($a) <=> &ipaddrval($b);
+}
+
+# This routine parses "show version"
+sub ShowVersion {
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { $found_version = 1; last};
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(0) if ($found_version); # Only do this routine once
+ return(-1) if (/command authorization failed/i);
+
+ /copyright/i && next;
+ /u-boot/i &&
+ ProcessHistory("COMMENTS","keysort","C1", "!ROM: $_") && next;
+
+ ProcessHistory("COMMENTS","keysort","B1", "!Image: $_") && next;
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
+}
+
+# This routine parses "show chassis" for the gsr
+# This will create arrays for hw info.
+sub ShowChassis {
+ # Skip if this is not a 1200n.
+ print STDERR " In ShowChassis: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ if (/Chassis +Model/ || /=======/) {
+ ProcessHistory("COMMENTS","keysort","C1","!$_");
+ next;
+ }
+ # Trim the temp from the end of the slot line
+ chomp; s/\s+$//;
+ s/\S+$//;
+ ProcessHistory("COMMENTS","keysort","C1","!$_\n");
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
+}
+
+# This routine parses "show slots".
+sub ShowSlots {
+ print STDERR " In ShowSlots: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ return if (/^\s*\^$/);
+ last if (/online diag status/i);
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("SLOTS","","","!$_");
+ next;
+ }
+ ProcessHistory("SLOTS","","","!\n");
+
+ return(0);
+}
+
+# This routine processes a "write term"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+ my($lineauto,$comment,$linecnt) = (0,0,0);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if (/(Invalid input detected|Type help or )/i);
+ return(0) if ($found_end); # Only do this routine once
+ return(-1) if (/command authorization failed/i);
+
+ /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ $linecnt++;
+ $lineauto = 0 if (/^[^ ]/);
+ # skip the crap
+ if (/^(##+$|(Building|Current) configuration)/i) {
+ while (<INPUT>) {
+ next if (/^Current configuration\s*:/i);
+ next if (/^:/);
+ next if (/^([%!].*|\s*)$/);
+ last;
+ }
+ tr/\015//d;
+ }
+
+ # skip consecutive comment lines to avoid oscillating extra comment
+ # line on some access servers. grrr.
+ if (/^!/) {
+ next if ($comment);
+ ProcessHistory("","","",$_);
+ $comment++;
+ next;
+ }
+ $comment = 0;
+
+ # Dog gone Cool matches to process the rest of the config
+ /^tftp-server flash / && next; # kill any tftp remains
+ /^ntp clock-period / && next; # kill ntp clock-period
+ /^ length / && next; # kill length on serial lines
+ /^ width / && next; # kill width on serial lines
+ $lineauto = 1 if /^ modem auto/;
+ /^ speed / && $lineauto && next; # kill speed on serial lines
+ if (/^(enable )?(password|passwd)( level \d+)? / && $filter_pwds >= 1) {
+ ProcessHistory("ENABLE","","","!$1$2$3 <removed>\n");
+ next;
+ }
+ if (/^(enable secret) / && $filter_pwds >= 2) {
+ ProcessHistory("ENABLE","","","!$1 <removed>\n");
+ next;
+ }
+ if (/^username (\S+)(\s.*)? password (encrypted \S+|\S+)(\sclass .*$)/){
+ if ($filter_pwds >= 2) {
+ ProcessHistory("USER","keysort","$1",
+ "!username $1$2 password <removed>$4\n");
+ } else {
+ ProcessHistory("USER","keysort","$1","$_");
+ }
+ next;
+ }
+ if (/^(\s*)password / && $filter_pwds >= 1) {
+ ProcessHistory("LINE-PASS","","","!$1password <removed>\n");
+ next;
+ }
+
+ # filter out any RCS/CVS tags to avoid confusing local CVS storage
+ s/\$(Revision|Id):/ $1:/;
+ # order access-lists
+ /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ &&
+ ProcessHistory("ACL $1 $2","$aclsort","$3","$_") && next;
+ # order extended access-lists
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
+ ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next;
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
+ ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next;
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ &&
+ ProcessHistory("EACL $1 $2","$aclsort","0.0.0.0","$_") && next;
+ # order arp lists
+ /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
+ ProcessHistory("ARP","$aclsort","$1","$_") && next;
+ /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
+ ProcessHistory("PACL $1 $3","$aclsort","$4","ip prefix-list $1 $3 $4$5\n")
+ && next;
+ # order logging statements
+ /^logging (\d+\.\d+\.\d+\.\d+)/ &&
+ ProcessHistory("LOGGING","ipsort","$1","$_") && next;
+ # order/prune snmp-server host statements
+ # we only prune lines of the form
+ # snmp-server host a.b.c.d <community>
+ if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) {
+ if ($filter_commstr) {
+ my($ip) = $1;
+ my($line) = "snmp-server host $ip";
+ my(@tokens) = split(' ', $');
+ my($token);
+ while ($token = shift(@tokens)) {
+ if ($token eq 'version') {
+ $line .= " " . join(' ', ($token, shift(@tokens)));
+ if ($token eq '3') {
+ $line .= " " . join(' ', ($token, shift(@tokens)));
+ }
+ } elsif ($token eq 'vrf') {
+ $line .= " " . join(' ', ($token, shift(@tokens)));
+ } elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) {
+ $line .= " " . $token;
+ } else {
+ $line = "!$line " . join(' ', ("<removed>", join(' ',@tokens)));
+ last;
+ }
+ }
+ ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line\n");
+ } else {
+ ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_");
+ }
+ next;
+ }
+ if (/^(snmp-server community) (\S+)/) {
+ if ($filter_commstr) {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_",
+ "!$1 <removed>$'") && next;
+ } else {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
+ }
+ }
+ # prune tacacs/radius server keys
+ # radius-server host <1-5> IP SECRET [<ip port> [TIMEOUT [RETRY]]]
+ if (/^((tacacs|radius)-server)\s(\d+\.\d+\.\d+\.\d+)\s(\w*)/
+ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 $2 <removed>$'"); next;
+ }
+ # order ntp peers/servers
+ if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) {
+ $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5);
+ ProcessHistory("NTP","keysort",$sortkey,"$_");
+ next;
+ }
+
+ # catch anything that wasnt matched above.
+ ProcessHistory("","","","$_");
+ }
+ # The MRV MCC lacks a definitive "end of config" marker. If we have seen
+ # at least 5 lines of show config output, we can be reasonably sure that
+ # we got the config.
+ if ($linecnt > 5) {
+ $found_end = 1;
+ return(0);
+ }
+
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+@commandtable = (
+ {'show version' => 'ShowVersion'},
+ {'show chassis' => 'ShowChassis'},
+ {'show slots' => 'ShowSlots'},
+ {'show running-config' => 'WriteTerm'}
+);
+# Use an array to preserve the order of the commands and a hash for mapping
+# commands to the subroutine and track commands that have been completed.
+@commands = map(keys(%$_), @commandtable);
+%commands = map(%$_, @commandtable);
+
+$cisco_cmds = join(";",@commands);
+$cmds_regexp = join("|",@commands);
+
+if (length($host) == 0) {
+ if ($file) {
+ print(STDERR "Too few arguments: file name required\n");
+ exit(1);
+ } else {
+ print(STDERR "Too few arguments: host name required\n");
+ exit(1);
+ }
+}
+open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
+select(OUTPUT);
+# make OUTPUT unbuffered if debugging
+if ($debug) { $| = 1; }
+
+if ($file) {
+ print STDERR "opening file $host\n" if ($debug);
+ print STDOUT "opening file $host\n" if ($log);
+ open(INPUT,"<$host") || die "open failed for $host: $!\n";
+} else {
+ print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "mrvlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"mrvlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "mrvlogin failed for $host: $!\n";
+ }
+}
+
+# determine ACL sorting mode
+if ($ENV{"ACLSORT"} =~ /no/i) {
+ $aclsort = "";
+}
+# determine community string filtering mode
+if (defined($ENV{"NOCOMMSTR"}) &&
+ ($ENV{"NOCOMMSTR"} =~ /yes/i || $ENV{"NOCOMMSTR"} =~ /^$/)) {
+ $filter_commstr = 1;
+} else {
+ $filter_commstr = 0;
+}
+# determine password filtering mode
+if ($ENV{"FILTER_PWDS"} =~ /no/i) {
+ $filter_pwds = 0;
+} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
+ $filter_pwds = 2;
+} else {
+ $filter_pwds = 1;
+}
+
+ProcessHistory("","","","!RANCID-CONTENT-TYPE: mrv\n!\n");
+ProcessHistory("COMMENTS","keysort","B0","!\n");
+ProcessHistory("COMMENTS","keysort","C0","!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/^Error:/) {
+ print STDOUT ("$host clogin error: $_");
+ print STDERR ("$host clogin error: $_") if ($debug);
+ $clean_run = 0;
+ last;
+ }
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]+#)/)[0];
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
+ }
+ print STDERR ("HIT COMMAND:$_") if ($debug);
+ if (! defined($commands{$cmd})) {
+ print STDERR "$host: found unexpected command - \"$cmd\"\n";
+ $clean_run = 0;
+ last TOP;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -1) {
+ $clean_run = 0;
+ last TOP;
+ }
+ }
+ if (/[>#]\s?exit$/) {
+ $clean_run = 1;
+ last;
+ }
+}
+print STDOUT "Done $logincmd: $_\n" if ($log);
+# Flush History
+ProcessHistory("","","","");
+# Cleanup
+close(INPUT);
+close(OUTPUT);
+
+if (defined($ENV{NOPIPE})) {
+ unlink("$host.raw") if (! $debug);
+}
+
+# check for completeness
+if (scalar(%commands) || !$clean_run || !$found_end) {
+ if (scalar(%commands)) {
+ printf(STDOUT "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
+ printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
+ }
+ if (!$clean_run || !$found_end) {
+ print STDOUT "$host: End of run not found\n";
+ print STDERR "$host: End of run not found\n" if ($debug);
+ system("/usr/bin/tail -1 $host.new");
+ }
+ unlink "$host.new" if (! $debug);
+}
diff --git a/bin/nlogin.in b/bin/nlogin.in
index 73b0e5a..d2e211d 100644
--- a/bin/nlogin.in
+++ b/bin/nlogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -379,22 +379,22 @@ cyphertype } {
" ### Login failed" {send_user "\nError: Check your passwd for $firewall\n"; return 1 }
-re "(login:)" {
sleep 1;
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "@\[^\r\n]+\[Pp]assword:" {
# ssh pwd prompt
sleep 1
- send "$userpswd\r"
+ send -- "$userpswd\r"
exp_continue
}
"\[Pp]assword:" {
sleep 1;
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -413,27 +413,14 @@ proc run_commands { prompt command } {
send "set console page 0\r"
expect -re $prompt {}
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
-
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst [lindex $commands $i]]\r"
- expect {
- -re "\[\n\r]+" { exp_continue }
- -re "$prompt" {}
- -gl "--- more ---" { send " "
- exp_continue
- }
- }
- }
- } else {
- send "[subst $command]\r"
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst [lindex $commands $i]]\r"
expect {
- -re "\[\n\r]+" { exp_continue }
- -re "$prompt" {}
- -gl "--- more ---" { send " "
+ -re "\[\n\r]+" { exp_continue }
+ -re "$prompt" {}
+ -gl "--- more ---" { send " "
exp_continue
}
}
diff --git a/bin/nrancid.in b/bin/nrancid.in
index c4fe9f1..6d6fbd4 100644
--- a/bin/nrancid.in
+++ b/bin/nrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/nslogin.in b/bin/nslogin.in
index 9e9e354..0dae833 100644
--- a/bin/nslogin.in
+++ b/bin/nslogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -78,8 +78,6 @@ set avautoenable 0
# tracks if we receive them on the command line.
set do_passwd 1
set do_enapasswd 1
-# attempt at platform switching.
-set platform ""
# Find the user in the ENV, or use the unix userid.
if {[ info exists env(CISCO_USER) ]} {
@@ -317,7 +315,7 @@ proc source_password_file { password_file } {
# Log into the router.
# returns: 0 on success, 1 on failure
proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
- global spawn_id in_proc do_command do_script platform
+ global spawn_id in_proc do_command do_script
global prompt u_prompt p_prompt e_prompt sshcmd
set in_proc 1
set uprompt_seen 0
@@ -426,7 +424,7 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
-re "(@\[^\r\n]+ )?$p_prompt" {
# ssh pwd prompt
sleep 1
- send "$userpswd\r"
+ send -- "$userpswd\r"
exp_continue
}
@@ -446,83 +444,52 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
# Run commands given on the command line.
proc run_commands { prompt command } {
- global in_proc platform
+ global in_proc
set in_proc 1
regsub -all "\[)(]" $prompt {\\&} reprompt
# this is the only way i see to get rid of more prompts in o/p..grrrrr
log_user 0
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
- # the pager can not be turned off on the PIX, so we have to look
- # for the "More" prompt. the extreme is equally obnoxious, with a
- # global switch in the config.
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
- expect {
- -re "\b+" { exp_continue }
- -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
- }
- -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
- send " "
- # bloody ^[[2K after " "
- expect {
- -re "^\[^\r\n]*\r" {}
- }
- exp_continue
- }
- -re "^ --More--\[^\n\r]*" {
- send " "
- exp_continue }
- -re "^<-+ More -+>\[^\n\r]*" {
- send_user -- "$expect_out(buffer)"
- send " "
- exp_continue }
- }
- }
- } else {
- # the pager can not be turned off on the PIX, so we have to look
- # for the "More" prompt. the extreme is equally obnoxious, with a
- # global switch in the config.
- send "[subst -nocommands $command]\r"
- expect {
- -re "\b+" { exp_continue }
- -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
- }
- -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
- exp_continue }
- -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
- send " "
- # bloody ^[[2K after " "
- expect {
- -re "^\[^\r\n]*\r" {}
- }
- exp_continue
- }
- -re "^ --More--\[^\n\r]*" {
- send " "
- exp_continue }
- -re "^<-+ More -+>\[^\n\r]*" {
- send_user -- "$expect_out(buffer)"
- send " "
- exp_continue }
- }
+
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ # the pager can not be turned off on the PIX, so we have to look
+ # for the "More" prompt. the extreme is equally obnoxious, with a
+ # global switch in the config.
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
+ expect {
+ -re "\b+" { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
+ }
+ -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
+ exp_continue
+ }
+ -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
+ exp_continue
+ }
+ -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
+ send " "
+ # bloody ^[[2K after " "
+ expect {
+ -re "^\[^\r\n]*\r" {}
+ }
+ exp_continue
+ }
+ -re "^ --More--\[^\n\r]*" {
+ send " "
+ exp_continue
+ }
+ -re "^<-+ More -+>\[^\n\r]*" {
+ send_user -- "$expect_out(buffer)"
+ send " "
+ exp_continue
+ }
+ }
}
log_user 1
- if { [ string compare "extreme" "$platform" ] } {
- send "exit\r"
- } else {
- send "quit\r"
- }
+ send "quit\r"
expect {
"Do you wish to save your configuration changes" {
send "n\r"
@@ -651,17 +618,8 @@ foreach router [lrange $argv $i end] {
send "\r"
expect {
-re "\[\r\n]+" { exp_continue; }
- -re "^(.+:)1 $prompt" { # stoopid extreme cmd-line numbers and
- # prompt based on state of config changes
- set junk $expect_out(1,string)
- regsub -all "^\\\* " $expect_out(1,string) {} junk
- set prompt ".? ?$junk\[0-9]+ $prompt";
- set platform "extreme"
- }
-re "^.+$prompt" { set junk $expect_out(0,string);
regsub -all "\[\]\[]" $junk {\\&} prompt; }
- -re "^.+> \\\(enable\\\)" { set junk $expect_out(0,string);
- regsub -all "\[\]\[]" $junk {\\&} prompt; }
}
if { $do_command } {
diff --git a/bin/nsrancid.in b/bin/nsrancid.in
index bd159b7..e7f3d96 100644
--- a/bin/nsrancid.in
+++ b/bin/nsrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -66,8 +66,6 @@ my($aclsort) = ("ipsort"); # ACL sorting mode
my($filter_commstr); # SNMP community string filtering
my($filter_pwds); # password filtering mode
-@temp1 = split (/\./,$host);
-$prompt = "$temp1[0]#";
$prompt = "netscaler#";
# This routine is used to print out the router configuration
@@ -170,7 +168,7 @@ sub sortbyipaddr {
&ipaddrval($a) <=> &ipaddrval($b);
}
-# This routine parses "show config"
+# This routine parses "show ns ns.conf"
sub ShowConfig {
print STDERR " In ShowConfig: $_" if ($debug);
@@ -199,23 +197,6 @@ sub ShowConfig {
return(0);
}
-# This routine parses "get log setting"
-sub GetLogSet {
- print STDERR " In GetLogSet: $_" if ($debug);
-
- while (<INPUT>) {
- tr/\015//d;
- last if (/^$prompt/);
- next if (/^(\s*|\s*$cmd\s*)$/);
- next if (/^Reading configuration information/);
- next if (/^Can\'t find object or class named \"\-all\"\s*$/);
- return(1) if /(invalid command name)/;
-
- ProcessHistory("","","","$_");
- }
- return(0);
-}
-
# This routine parses single command's that return no required info
sub RunCommand {
print STDERR " In RunCommand: $_" if ($debug);
@@ -233,8 +214,7 @@ sub DoNothing {print STDOUT;}
# Main
@commandtable = (
- {'cat /etc/ns.conf' => 'ShowConfig'},
- {'get log setting' => 'GetLogSet'}
+ {'show ns ns.conf' => 'ShowConfig'},
);
# Use an array to preserve the order of the commands and a hash for mapping
# commands to the subroutine and track commands that have been completed.
@@ -297,26 +277,14 @@ if ($ENV{"FILTER_PWDS"} =~ /no/i) {
ProcessHistory("","","","!RANCID-CONTENT-TYPE: netscaler\n!\n");
TOP: while(<INPUT>) {
tr/\015//d;
-#print STDOUT " --IN--$_";
- # if ( (/exit/) || $found_end ) {
-# $clean_run=1;
-#print STDOUT "\n\nhere11\n";
-#last;
-# }
-
- # if ( (/netscaler#/) || $found_end ) {
-#print STDOUT "\n\nhere1\n";
-# $clean_run=1;
-# last;
-# }
if (/^Error:/) {
print STDOUT ("$host nslogin error: $_");
print STDERR ("$host nslogin error: $_") if ($debug);
- $clean_run=0;
+ $clean_run = 0;
last;
}
- while (/#\s*($cmds_regexp)\s*$/) {
+ while (/$prompt\s*($cmds_regexp)\s*$/) {
$cmd = $1;
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
diff --git a/bin/nxrancid.in b/bin/nxrancid.in
new file mode 100644
index 0000000..699479f
--- /dev/null
+++ b/bin/nxrancid.in
@@ -0,0 +1,1835 @@
+#! @PERLV_PATH@
+##
+## $Id$
+##
+## @PACKAGE@ @VERSION@
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
+## All rights reserved.
+##
+## This code is derived from software contributed to and maintained by
+## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
+## Pete Whiting, Austin Schutz, and Andrew Fort.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+## 1. Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## 2. Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in the
+## documentation and/or other materials provided with the distribution.
+## 3. All advertising materials mentioning features or use of this software
+## must display the following acknowledgement:
+## This product includes software developed by Terrapin Communications,
+## Inc. and its contributors for RANCID.
+## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
+## contributors may be used to endorse or promote products derived from
+## this software without specific prior written permission.
+## 5. It is requested that non-binding fixes and modifications be contributed
+## back to Terrapin Communications, Inc.
+##
+## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
+## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
+## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+## POSSIBILITY OF SUCH DAMAGE.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-dV] [-l] [-f filename | hostname]
+#
+use Getopt::Std;
+getopts('dflV');
+if ($opt_V) {
+ print "@PACKAGE@ @VERSION@\n";
+ exit(0);
+}
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$ios = "IOS";
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # clogin timeout in seconds
+
+my(@commandtable, %commands, @commands);# command lists
+my($aclsort) = ("ipsort"); # ACL sorting mode
+my($filter_commstr); # SNMP community string filtering
+my($filter_pwds); # password filtering mode
+
+# This routine is used to print out the router configuration
+sub ProcessHistory {
+ my($new_hist_tag,$new_command,$command_string,@string) = (@_);
+ if ((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
+ && defined %history) {
+ print eval "$command \%history";
+ undef %history;
+ }
+ if (($new_hist_tag) && ($new_command) && ($command_string)) {
+ if ($history{$command_string}) {
+ $history{$command_string} = "$history{$command_string}@string";
+ } else {
+ $history{$command_string} = "@string";
+ }
+ } elsif (($new_hist_tag) && ($new_command)) {
+ $history{++$#history} = "@string";
+ } else {
+ print "@string";
+ }
+ $hist_tag = $new_hist_tag;
+ $command = $new_command;
+ 1;
+}
+
+sub numerically { $a <=> $b; }
+
+# This is a sort routine that will sort numerically on the
+# keys of a hash as if it were a normal array.
+sub keynsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort numerically keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# keys of a hash as if it were a normal array.
+sub keysort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# values of a hash as if it were a normal array.
+sub valsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort values %lines) {
+ $sorted_lines[$i] = $key;
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a numerical sort routine (ascending).
+sub numsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $num (sort {$a <=> $b} keys %lines) {
+ $sorted_lines[$i] = $lines{$num};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# ip address when the ip address is anywhere in
+# the strings.
+sub ipsort {
+ local(%lines) = @_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $addr (sort sortbyipaddr keys %lines) {
+ $sorted_lines[$i] = $lines{$addr};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# These two routines will sort based upon IP addresses
+sub ipaddrval {
+ my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
+ $a[3] + 256 * ($a[2] + 256 * ($a[1] +256 * $a[0]));
+}
+sub sortbyipaddr {
+ &ipaddrval($a) <=> &ipaddrval($b);
+}
+
+# This routine parses "show version"
+sub ShowVersion {
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { last};
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ if (/^Cisco Nexus Operating System/) { $type = "NXOS";}
+ if (/^Software$/) {
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { last};
+ next if (/^\s*$cmd\s*$/);
+
+ if (/^$/) {
+ goto EndSoftware;
+ }
+ /\s*([^:]*:)\s*(.*)$/ && ProcessHistory("COMMENTS","keysort","F1", "!Software: $1 $2\n") && next;
+ }
+ }
+EndSoftware:
+ if (/^Hardware$/) {
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { last};
+ next if (/^\s*$cmd\s*$/);
+
+ if (/^$/) {
+ goto EndHardware;
+ }
+ if (/^\s*(.*) CPU\s*with (\d*) kB(.*)$/) {
+ my($tmp) = int($2 / 1024);
+ ProcessHistory("COMMENTS","keysort","A2", "!Hardware: $1 CPU with $tmp MB$3\n");
+ next;
+ }
+ if (/^\s*(.*)\s*with (\d*) kB(.*)$/) {
+ my($tmp) = int($2 / 1024);
+ ProcessHistory("COMMENTS","keysort","A2", "!Hardware: $1with $tmp MB$3\n");
+ next;
+ }
+ /^\s*(.*)$/ && ProcessHistory("COMMENTS","keysort","A2", "!Hardware: $1\n") && next;
+ }
+ }
+EndHardware:
+ if (/^\s+(bootflash|slot0):\s+(\d+) kB(.*)$/) {
+ my($tmp) = int($2 / 1024);
+ ProcessHistory("COMMENTS","keysort","B2", "!Memory: $1: $tmp MB$3\n");
+ next;
+ }
+
+ }
+
+ print STDERR "TYPE = $type\n" if ($debug);
+ ProcessHistory("COMMENTS","keysort","A1", "!Chassis type: $proc - a $type router\n");
+
+ return(0);
+}
+
+# This routine parses "show version build-info"
+sub ShowVersionBuild {
+ print STDERR " In ShowVersionBuild: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { last};
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ /^Built By / && ProcessHistory("Build","","", "!Build: $_");
+ /^On Date / && ProcessHistory("Build","","", "!Build: $_");
+ /^From Tree / && ProcessHistory("Build","","", "!Build: $_");
+ /^Base Tag / && ProcessHistory("Build","","", "!Build: $_");
+ /^Release for / && ProcessHistory("Build","","", "!Build: $_");
+ }
+ ProcessHistory("Build","","","!\n");
+ return(0);
+}
+
+# This routine parses "show system redundancy status"
+sub ShowRedundancy {
+ print STDERR " In ShowRedundancy: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+
+ s/ +$//; # Drop trailing ' '
+ ProcessHistory("Redundancy","","","!Red: $_");
+ }
+ ProcessHistory("Redundancy","","","!\n");
+ return(0);
+}
+
+# This routine parses "show IDprom"
+sub ShowIDprom {
+ my($tmp);
+
+ print STDERR " In ShowIDprom: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ /FRU is .(.*)\'/ && ($tmp = $1);
+ /Product Number = .(.*)\'/ &&
+ ProcessHistory("COMMENTS","keysort","D0",
+ "!Catalyst Chassis type: $1, $tmp\n");
+ /Serial Number = .([0-9A-Za-z]+)/ &&
+ ProcessHistory("COMMENTS","keysort","D1",
+ "!Catalyst Chassis S/N: $1\n");
+ /Manufacturing Assembly Number = .([-0-9]+)/ && ($tmp = $1);
+ /Manufacturing Assembly Revision = .(.*)\'/ && ($tmp .= ", rev " . $1);
+ /Hardware Revision = ([0-9.]+)/ &&
+ ProcessHistory("COMMENTS","keysort","D2",
+ "!Catalyst Chassis assembly: $tmp, ver $1\n");
+ }
+ return(0);
+}
+
+# This routine parses "show install active"
+sub ShowInstallActive {
+ print STDERR " In ShowInstallActive: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "show environment"
+sub ShowEnv {
+ print STDERR " In ShowEnv: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { last};
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ s/ +$//; # Drop trailing ' '
+ ProcessHistory("COMMENTS","","","!Env: $_");
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
+}
+
+# This routine parses "show environment temperature"
+sub ShowEnvTemp {
+ print STDERR " In ShowEnvTemp: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { last};
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+# Cut out CurTemp
+#--------------------------------------------------------------------
+#Module Sensor MajorThresh MinorThres CurTemp Status
+# 1 2 3 4 5 6 7
+#1234567890123456789012345678901234567890123456789012345678901234567890
+
+ s/^(.{50})(.{12})(.*)$/$1$3/;
+
+ s/ +$//; # Drop trailing ' '
+ ProcessHistory("COMMENTS","","","!Env: $_");
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
+}
+
+# This routine parses "show rsp chassis-info" for the rsp
+# This will create arrays for hw info.
+sub ShowRSP {
+ print STDERR " In ShowRSP: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+ # return(1) if ($type !~ /^12[40]/);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+ /^$/ && next;
+
+ /^\s+Chassis model: (\S+)/ &&
+ ProcessHistory("COMMENTS","keysort","D1",
+ "!RSP Chassis model: $1\n") &&
+ next;
+ /^\s+Chassis S\/N: (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","D2",
+ "!RSP Chassis S/N: $1\n") &&
+ next;
+ }
+
+ return(0);
+}
+
+# This routine parses "show gsr chassis-info" for the gsr
+# This will create arrays for hw info.
+sub ShowGSR {
+ # Skip if this is not a 1200n.
+ print STDERR " In ShowGSR: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+ # return(1) if ($type !~ /^12[40]/);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+ /^$/ && next;
+
+ /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ &&
+ ProcessHistory("COMMENTS","keysort","D1",
+ "!GSR Chassis type: $1 Fab Ver: $2\n") &&
+ next;
+ /^\s+Chassis S\/N: (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","D2",
+ "!GSR Chassis S/N: $1\n") &&
+ next;
+ /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ &&
+ ProcessHistory("COMMENTS","keysort","D3",
+ "!GSR Backplane PCA: $1, rev $2, ver $3\n") &&
+ next;
+ /^\s+Backplane S\/N: (\S+)$/ &&
+ ProcessHistory("COMMENTS","keysort","D4",
+ "!GSR Backplane S/N: $1\n") &&
+ next;
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
+}
+
+# This routine parses "show boot"
+sub ShowBoot {
+ print STDERR " In ShowBoot: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /Ambiguous command/i;
+ return(-1) if (/command authorization failed/i);
+
+ s/ variable = / = /;
+ ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
+}
+
+# This routine parses "show flash"
+sub ShowFlash {
+ # skip if this is 7000, 7200, 7500, or 12000; else we end up with
+ # redundant data from dir /all slot0:
+ print STDERR " In ShowFlash: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type =~ /^(12[40]|7)/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ /\s+(multiple-fs|nv_hdr|vlan\.dat)$/ && next;
+ ProcessHistory("FLASH","","","!Flash: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return;
+}
+
+# This routine parses "dir /all ((disk|slot)N|bootflash|nvram):"
+sub DirSlotN {
+ print STDERR " In DirSlotN: $_" if ($debug);
+
+ my($dev) = (/\s([^\s]+):/);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /(No such device|Error Sending Request)/i;
+ return(1) if /\%Error: No such file or directory/;
+ return(1) if /No space information available/;
+ return(1) if / is either not present or not formatted/;
+ return(-1) if /\%Error calling/;
+ return(-1) if /(: device being squeezed|ATA_Status time out)/i; # busy
+ return(-1) if (/command authorization failed/i);
+ return(1) if /(Open device \S+ failed|Error opening \S+:)/;
+
+ if (/^\s*(\d+) bytes /) {
+ my($tmp) = int($1 / (1024 * 1024));
+ s/$1 bytes /$tmp MB /;
+ }
+
+ ProcessHistory("FLASH","","","!Flash: $dev: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return(0);
+}
+
+# This routine parses "show controllers"
+sub ShowContAll {
+ # Skip if this is a 70[01]0, 7500, or 12000.
+ print STDERR " In ShowContAll: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ # return(1) if ($type =~ /^(12[40]|7[05])/);
+ return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; }
+ /^(BRI unit \d)/ &&
+ ProcessHistory("INT","","","!Interface: $1\n") && next;
+ /^LANCE unit \d, NIM/ &&
+ ProcessHistory("INT","","","!Interface: $_") && next;
+ /^(LANCE unit \d)/ &&
+ ProcessHistory("INT","","","!Interface: $1\n") && next;
+ /(Media Type is \S+),/ &&
+ ProcessHistory("INT","","","!\t$1\n");
+ if (/(M\dT[^ :]*:) show controller:$/) {
+ my($ctlr) = $1;
+ $_ = <INPUT>; tr/\015//d; s/ subunit \d,//;
+ ProcessHistory("INT","","","!Interface: $ctlr $_");
+ }
+ if (/^(\S+) : show controller:$/) {
+ my($ctlr) = $1;
+ $_ = <INPUT>; tr/\015//d; s/ subunit \d,//;
+ ProcessHistory("INT","","","!Interface: $ctlr: $_");
+ }
+ /^(HD unit \d), idb/ &&
+ ProcessHistory("INT","","","!Interface: $1\n") && next;
+ /^HD unit \d, NIM/ &&
+ ProcessHistory("INT","","","!Interface: $_") && next;
+ /^buffer size \d+ HD unit \d, (.*)/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^AM79970 / && ProcessHistory("INT","","","!Interface: $_") && next;
+ /^buffer size \d+ (Universal Serial: .*)/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^Hardware is (.*)/ &&
+ ProcessHistory("INT","","","!Interface: $INT$1\n") && next;
+ /^(QUICC Serial unit \d),/ &&
+ ProcessHistory("INT","","","!$1\n") && next;
+ /^QUICC Ethernet .*/ &&
+ ProcessHistory("INT","","","!$_") && next;
+ /^DTE .*\.$/ &&
+ ProcessHistory("INT","","","!\t$_") && next;
+ /^(cable type :.*),/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^(.* cable.*), received clockrate \d+$/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^.* cable.*$/ &&
+ ProcessHistory("INT","","","!\t$_") && next;
+ }
+ return(0);
+}
+
+# This routine parses "show controllers cbus"
+# Some of this is printed out in ShowDiagbus.
+sub ShowContCbus {
+ # Skip if this is not a 7000 or 7500.
+ print STDERR " In ShowContCbus: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ #return(1) if ($type !~ /^7[05]0/);
+ return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) {
+ $slot = $1;
+ $board{$slot} = $2;
+ $hwver{$slot} = $3;
+ $hwucode{$slot} = $4;
+ } elsif (/^\s*(\S+) (\d+), hardware version (\S+), microcode version (\S+)/) {
+ $slot = $2;
+ $board{$slot} = $1;
+ $hwver{$slot} = $3;
+ $hwucode{$slot} = $4;
+ } elsif (/(Microcode .*)/) {
+ $ucode{$slot} = $1;
+ } elsif (/(software loaded .*)/) {
+ $ucode{$slot} = $1;
+ } elsif (/(\d+) Kbytes of main memory, (\d+) Kbytes cache memory/) {
+ $hwmemd{$slot} = $1;
+ $hwmemc{$slot} = $2;
+ } elsif (/byte buffers/) {
+ chop;
+ s/^\s*//;
+ $hwbuf{$slot} = $_;
+ } elsif (/Interface (\d+) - (\S+ \S+),/) {
+ $interface = $1;
+ ProcessHistory("HW","","",
+ "!\n!Int $interface: in slot $slot, named $2\n"); next;
+ } elsif (/(\d+) buffer RX queue threshold, (\d+) buffer TX queue limit, buffer size (\d+)/) {
+ ProcessHistory("HW","","","!Int $interface: rxq $1, txq $2, bufsize $3\n");
+ next;
+ }
+ }
+ return(0);
+}
+
+# This routine parses "show debug"
+sub ShowDebug {
+ print STDERR " In ShowDebug: $_" if ($debug);
+ my($lines) = 0;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ /^No matching debug flags set$/ && next;
+ /^No debug flags set$/ && next;
+ ProcessHistory("COMMENTS","keysort","J1","!DEBUG: $_");
+ $lines++;
+ }
+ if ($lines) {
+ ProcessHistory("COMMENTS","keysort","J0","!\n");
+ }
+ return(0);
+}
+
+# This routine parses "show cores"
+sub ShowCores {
+ print STDERR " In ShowCores: $_" if ($debug);
+ my($lines) = 0;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("COMMENTS","keysort","K1","!CORES: $_");
+ $lines++;
+ }
+ if ($lines) {
+ ProcessHistory("COMMENTS","keysort","K0","!\n");
+ }
+ return(0);
+}
+
+# This routine parses "show processes log"
+sub ShowProcLog {
+ print STDERR " In ShowProcLog: $_" if ($debug);
+ my($lines) = 0;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("COMMENTS","keysort","L1","!PROC_LOGS: $_");
+ $lines++;
+ }
+ if ($lines) {
+ ProcessHistory("COMMENTS","keysort","L0","!\n");
+ }
+ return(0);
+}
+
+# This routine parses "show diagbus"
+# This will create arrarys for hw info.
+sub ShowDiagbus {
+ # Skip if this is not a 7000, 70[01]0, or 7500.
+ print STDERR " In ShowDiagbus: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ #return(1) if ($type !~ /^7[05]/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ if (/^\s*Slot (\d+):/i) {
+ $slot = $1;
+ next;
+ } elsif (/^\s*Slot (\d+) \(virtual\):/i) {
+ $slot = $1;
+ next;
+ } elsif (/^\s*(.*Processor.*|.*controller|.*controler|.*Chassis Interface)(, FRU\s?:.*)?, HW rev (\S+), board revision (\S+)/i) {
+ $board = $1;
+ $hwver = $3;
+ $boardrev = $4;
+ if ($board =~ /Processor/) {
+ if ($board =~ /7000 Route\/Switch/) {
+ $board = "RSP7000";
+ } elsif ($board =~ /Route\/Switch Processor (\d)/) {
+ $board = "RSP$1";
+ } elsif ($board =~ /Route/) {
+ $board = "RP";
+ } elsif ($board =~ /Silicon Switch/) {
+ $board = "SSP";
+ } elsif ($board =~ /Switch/) {
+ $board = "SP";
+ $board = "SSP $sspmem" if $ssp;
+ } elsif ($board =~ /ATM/) {
+ $board = "AIP";
+ }
+ } elsif ($board =~ /(.*) controller/i) {
+ $board = $1;
+ }
+ # hwucode{$slot} defined in ShowContCbus
+ if (defined $hwucode{$slot}) {
+ ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n");
+ } else {
+ ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n");
+ }
+ # These are also from the ShowContCbus
+ ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot});
+ ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n")
+ if ((defined $hwmemd{$slot}) && (defined $hwmemc{$slot}));
+ ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot});
+ next;
+ }
+ /Serial number: (\S+)\s*Part number: (\S+)/ &&
+ ProcessHistory("SLOT","","",
+ "!Slot $slot/$board: part $2, serial $1\n") &&
+ next;
+ /^\s*Controller Memory Size: (.*)$/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: $1\n") &&
+ next;
+ if (/PA Bay (\d) Information/) {
+ $pano = $1;
+ if ("PA" =~ /$board/) {
+ ($s,$c) = split(/\//,$board);
+ $board = "$s/$c/PA $pano";
+ } else {
+ $board =~ s/\/PA \d//;
+ $board = "$board/PA $pano";
+ }
+ next;
+ }
+ /\s+(.*) (IP|PA), (\d) ports?,( \S+,)? (FRU\s?: )?(\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: type $6, $3 ports\n") &&
+ next;
+ /\s+(.*) (IP|PA)( \(\S+\))?, (\d) ports?/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$3, $4 ports\n") &&
+ next;
+ /^\s*HW rev (\S+), Board revision (\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") &&
+ next;
+ /Serial number: (\S+)\s*Part number: (\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && next;
+ }
+ return(0);
+}
+
+# This routine parses "show diag" for the gsr, 7200, 3700, 3600, 2600.
+# This will create arrarys for hw info.
+sub ShowDiag {
+ # Skip if this is not a 12000.
+ print STDERR " In ShowDiag: $_" if ($debug);
+
+ while (<INPUT>) {
+REDUX: tr/\015//d;
+ if (/^$prompt/) { $found_diag = 1; last};
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ # return(1) if ($type !~ /^(12[40]|720|36|26)/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(0) if ($found_diag); # Only do this routine once
+ return(-1) if (/command authorization failed/i);
+ /^$/ && next;
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ s/Port Packet Over SONET/POS/;
+ if (/^\s*SLOT\s+(\d+)\s+\((.*)\): (.*)/) {
+ $slot = $1;
+ ProcessHistory("SLOT","","","!\n");
+ ProcessHistory("SLOT","keysort","A","!Slot $slot: $3\n");
+ next;
+ }
+ if (/^\s*NODE\s+(\S+) : (.*)/) {
+ $slot = $1;
+ ProcessHistory("SLOT","","","!\n");
+ ProcessHistory("SLOT","keysort","A","!Slot $slot: $2\n");
+ next;
+ }
+ if (/^\s*PLIM\s+(\S+) : (.*)/) {
+ $slot = $1 . " PLIM";
+ ProcessHistory("SLOT","","","!\n");
+ ProcessHistory("SLOT","keysort","A","!Slot $slot: $2\n");
+ next;
+ }
+ if (/^\s*RACK\s+(\S+) : (.*)/) {
+ $slot = "Rack/" . $1;
+ ProcessHistory("SLOT","","","!\n");
+ ProcessHistory("SLOT","keysort","A","!Slot $slot: $2\n");
+ next;
+ }
+ if (/^\s+MAIN:\s* type \S+,\s+(.*)/) {
+ local($part) = $1;
+ $_ = <INPUT>;
+ if (/^\s+(HW version|Design Release) (\S+)\s+S\/N (\S+)/i) {
+ ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part, serial $3\n");
+ ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: hvers $2\n");
+ } else {
+ ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part\n");
+ goto REDUX;
+ }
+ next;
+ }
+ if (/^\s+MAIN:\s* board type \S+$/) {
+ $_ = <INPUT>;
+ tr/\015//d;
+ if (/^\s+(.+)$/) {
+ local($part) = $1;
+ $_ = <INPUT>;
+ tr/\015//d;
+ if (/^\s+dev (.*)$/) {
+ local($dev) = $1;
+ $_ = <INPUT>;
+ if (/^\s+S\/N (\S+)/) {
+ ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part, dev $dev, serial $1\n");
+ } else {
+ ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part, dev $dev\n");
+ goto REDUX;
+ }
+ } else {
+ ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part\n");
+ goto REDUX;
+ }
+ } else {
+ goto REDUX;
+ }
+ next;
+ }
+ if (/^c3700\s+(io-board|mid-plane)/i) {
+ $slot = $1;
+ ProcessHistory("SLOT","","","!\n");
+ ProcessHistory("SLOT","keysort","A","!Slot $slot: part $1\n");
+ next;
+ }
+ if (/ Engine:\s+(.*)/) {
+ ProcessHistory("SLOT","keysort","AE","!Slot $slot/Engine: $1\n");
+ }
+ if (/FRU:\s+Linecard\/Module:\s+(\S+)/) {
+ ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Linecard/Module: $1\n");
+ next;
+ }
+ if (/\s+Processor Memory:\s+(\S+)/) {
+ ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Processor Memory: $1\n");
+ next;
+ }
+ if (/\s+Packet Memory:\s+(\S+)/) {
+ ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Packet Memory: $1\n");
+ next;
+ }
+ if (/^\s+PCA:\s+(.*)/) {
+ local($part) = $1;
+ $_ = <INPUT>;
+ if (/^\s+(HW version|design release) (\S+)\s+S\/N (\S+)/i) {
+ ProcessHistory("SLOT","keysort","C1","!Slot $slot/PCA: part $part, serial $3\n");
+ ProcessHistory("SLOT","keysort","C2","!Slot $slot/PCA: hvers $2\n");
+ } else {
+ ProcessHistory("SLOT","keysort","C1","!Slot $slot/PCA: part $part\n");
+ goto REDUX;
+ }
+ next;
+ }
+ if (/^\s+MBUS: .*\)\s+(.*)/) {
+ local($tmp) = "!Slot $slot/MBUS: part $1";
+ $_ = <INPUT>;
+ /^\s+HW version (\S+)\s+S\/N (\S+)/ &&
+ ProcessHistory("SLOT","keysort","MB1","$tmp, serial $2\n") &&
+ ProcessHistory("SLOT","keysort","MB2","!Slot $slot/MBUS: hvers $1\n");
+ next;
+ }
+ if (/^\s+MBUS Agent Software version (.*)/) {
+ ProcessHistory("SLOT","keysort","MB3","!Slot $slot/MBUS: software $1\n");
+ next;
+ }
+ if (/^\s+PLD: (.*)/) {
+ ProcessHistory("SLOT","keysort","P","!Slot $slot/PLD: $1\n");
+ next;
+ }
+ if (/^\s+MONLIB: (.*)/) {
+ ProcessHistory("SLOT","keysort","Q","!Slot $slot/MONLIB: $1\n");
+ next;
+ }
+ if (/^\s+ROM Monitor version (.*)/) {
+ ProcessHistory("SLOT","keysort","R","!Slot $slot/ROM Monitor: version $1\n");
+ next;
+ }
+ if (/^\s+ROMMON: Version (.*)/) {
+ ProcessHistory("SLOT","keysort","R","!Slot $slot/ROMMON: version $1\n");
+ next;
+ }
+ if (/^\s+Fabric Downloader version used (.*)/) {
+ ProcessHistory("SLOT","keysort","Z","!Slot $slot/Fabric Downloader: version $1\n");
+ next;
+ }
+ if (/^\s+DRAM size: (\d+)/) {
+ local($dram) = $1 / 1048576;
+ $_ = <INPUT>;
+ if (/^\s+FrFab SDRAM size: (\d+)/) {
+ ProcessHistory("SLOT","keysort","MB4","!Slot $slot/MBUS: $dram Mbytes DRAM, "
+ . $1 / 1024 . " Kbytes SDRAM\n");
+ } else {
+ ProcessHistory("SLOT","keysort","MB4","!Slot $slot/MBUS: $dram Mbytes DRAM\n");
+ goto REDUX;
+ }
+ next;
+ }
+ # 7200, 3600, 2600, and 1700 stuff
+ if (/^(Slot)\s+(\d+(\/\d+)?):/
+ || /^\s+(WIC|VIC|WIC\/VIC) Slot (\d):/
+ || /^(Encryption AIM) (\d):/) {
+ if ($1 eq "WIC") {
+ $WIC = "/$2";
+ } elsif ($1 eq "VIC") {
+ $WIC = "/$2";
+ } elsif ($1 eq "WIC/VIC") {
+ $WIC = "/$2";
+ } elsif ($1 eq "DSP") {
+ $WIC = "/$2";
+ } elsif ($1 eq "Encryption AIM") {
+ $slot = "$2";
+ undef($WIC);
+ ProcessHistory("SLOT","","","!\n");
+ ProcessHistory("SLOT","keysort","B","!Slot $slot: type $1\n");
+ next;
+ } else {
+ $slot = $2;
+ undef($WIC);
+ }
+ $_ = <INPUT>; tr/\015//d;
+
+ # clean up hideous 7200/etc formats to look more like 7500 output
+ s/Fast-ethernet on C7200 I\/O card/FE-IO/;
+ s/ with MII or RJ45/-TX/;
+ s/Fast-ethernet /100Base/; s/[)(]//g;
+ s/intermediate reach/IR/i;
+
+ ProcessHistory("SLOT","","","!\n");
+ /\s+(.*) port adapter,?\s+(\d+)\s+/i &&
+ ProcessHistory("SLOT","keysort","B",
+ "!Slot $slot: type $1, $2 ports\n") && next;
+ # I/O controller with no interfaces
+ /\s+(.*)\s+port adapter\s*$/i &&
+ ProcessHistory("SLOT","keysort","B",
+ "!Slot $slot: type $1, 0 ports\n") && next;
+ /\s+(.*)\s+daughter card(.*)$/ &&
+ ProcessHistory("SLOT","keysort","B",
+ "!Slot $slot$WIC: type $1$2\n") && next;
+ /\s+(FT1)$/ &&
+ ProcessHistory("SLOT","keysort","B",
+ "!Slot $slot$WIC: type $1\n") && next;
+ # AS5300/5400 handling
+ /^Hardware is\s+(.*)$/i &&
+ ProcessHistory("SLOT","keysort","B","!Slot $slot: type $1\n")
+ && next;
+ /^DFC type is\s+(.*)$/i &&
+ ProcessHistory("SLOT","keysort","B","!Slot $slot: type $1\n")
+ && next;
+ #
+ # handle WICs lacking "daughter card" in the 2nd line of their
+ # show diag o/p
+ if (defined($WIC)) {
+ s/^\s+//;
+ ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: type $_");
+ }
+ next;
+ } elsif (/^\s+(.* (DSP) Module) Slot (\d):/) {
+ # The 1760 (at least) has yet another format...where it has two
+ # dedicated DSP slots, and thus two slot 0s.
+ my($TYPE) = $1;
+ $WIC = "/$3";
+ ProcessHistory("SLOT","","","!\n");
+ ProcessHistory("SLOT","keysort","B",
+ "!Slot $slot$WIC: type $TYPE\n");
+ next;
+ }
+ # yet another format. seen on 2600s w/ 12.1, but appears to be all
+ # 12.1, including 7200s & 3700s. Sometimes the PCB serial appears
+ # before the hardware revision.
+ if (/(pcb serial number|hardware revision)\s+:\s+(\S+)$/i) {
+ my($hw, $pn, $rev, $sn);
+ if ($1 =~ /^pcb/i) {
+ $sn = $2;
+ } else {
+ $hw = $2;
+ }
+ while (<INPUT>) {
+ tr/\015//d;
+
+ if (/0x..: / || /^$/) {
+ # no effing idea why break does not work there
+ goto PerlSucks;
+ }
+ if (/hardware revision\s+:\s+(\S+)/i) { $hw = $1; }
+ if (/part number\s+:\s+(\S+)/i) { $pn = $1; }
+ if (/board revision\s+:\s+(\S+)/i) { $rev = $1; }
+ if (/pcb serial number\s+:\s+(\S+)/i) { $sn = $1; }
+ # fru/pid bits, true Cisco evolving "standard", hopefully
+ # "show inventory" will be "the way" soon.
+ #
+ if (/product \(fru\) number\s+:\s+(\S+)/i) { $fn = $1; }
+ if (/product number\s+:\s+(\S+)/i) { $fn = $1; }
+ if (/product\s+identifier\s+\(PID\)\s+:\s+(\S+)/i) { $fn = $1; }
+ if (/fru\s+part\s+number\s+(\S+)/i) { $fn = $1; }
+ }
+PerlSucks:
+ # fru/pid bits
+ ProcessHistory("SLOT","keysort","AG","!Slot $slot$WIC: fru $fn\n");
+ #
+ ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: hvers $hw rev $rev\n");
+ ProcessHistory("SLOT","keysort","C","!Slot $slot$WIC: part $pn, serial $sn\n");
+ }
+ /revision\s+(\S+).*revision\s+(\S+)/ &&
+ ProcessHistory("SLOT","keysort","C","!Slot $slot$WIC: hvers $1 rev $2\n") &&
+ next;
+ /number\s+(\S+)\s+Part number\s+(\S+)/ &&
+ ProcessHistory("SLOT","keysort","D","!Slot $slot$WIC: part $2, serial $1\n") &&
+ next;
+ # AS5x00 bits
+ /^\ Board Revision\s+(\S+),\s+Serial Number\s+(\S+),/ &&
+ ProcessHistory("SLOT","keysort","D",
+ "!Slot $slot$WIC: rev $1, serial $2\n") && next;
+ /^\ Board Hardware Version\s+(\S+),\s+Item Number\s+(\S+),/ &&
+ ProcessHistory("SLOT","keysort","D",
+ "!Slot $slot$WIC: hvers $1, part $2\n") && next;
+ /^Motherboard Info:/ &&
+ ProcessHistory("SLOT","keysort","D",
+ "!Slot $slot$WIC: Motherboard\n") && next;
+ #
+ }
+ ProcessHistory("SLOT","","","!\n");
+ return(0);
+}
+
+# This routine parses "show inventory".
+sub ShowInventory {
+ print STDERR " In ShowInventory: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ return if (/^\s*\^$/);
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ if (/^(NAME: "[^"]*",)\s+(DESCR: "[^"]+")/) {
+ ProcessHistory("INVENTORY","","", sprintf("!%-30s %s\n", $1, $2));
+ next;
+ }
+ # split PID/VID/SN line
+ if (/^PID: (\S*)\s*,\s+VID: (\S*)\s*,\s+SN: (\S*)\s*$/) {
+ my($entries) = "";
+ $entries .= "!PID: $1\n" if ($1);
+ $entries .= "!VID: $2\n" if ($2);
+ $entries .= "!SN: $3\n" if ($3);
+ ProcessHistory("INVENTORY","","", "$entries");
+ next;
+ }
+ # split broken PID/VID/SN lines.
+ if (/^PID: (\S*)\s*,\s+VID: (\S*)\s*$/) {
+ my($entries) = "";
+ $entries .= "!PID: $1\n" if ($1);
+ $entries .= "!VID: $2\n" if ($2);
+ <INPUT>;
+ tr/\015//d;
+ /^\s*,\s+SN: (\S*)\s*$/;
+ $entries .= "!SN: $1\n" if ($1);
+ ProcessHistory("INVENTORY","","", "$entries");
+ next;
+ }
+ ProcessHistory("INVENTORY","","","!$_");
+ }
+ ProcessHistory("INVENTORY","","","!\n");
+
+ return(0);
+}
+
+# This routine parses "show module".
+sub ShowModule {
+ print STDERR " In ShowModule: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ return if (/^\s*\^$/);
+ last if (/online diag status/i);
+ last if (/^$prompt/);
+ next if (/^\s*$cmd\s*$/);
+ return(-1) if (/command authorization failed/i);
+
+ s/(.*) \*$/$1/; # Drop a trailing '*'
+ /^\* this terminal session/ && next;
+ s/ +$//; # Drop trailing ' '
+ ProcessHistory("Module","","","!Mod: $_");
+ }
+ ProcessHistory("Module","","","!\n");
+
+ return(0);
+}
+
+# This routine parses "show spe version".
+sub ShowSpeVersion {
+ print STDERR " In ShowSpeVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("MODEM","","","!Modem: $_") && next;
+ }
+ ProcessHistory("MODEM","","","!\n");
+ return(0);
+}
+
+# This routine parses "show c7200" for the 7200
+# This will create arrays for hw info.
+sub ShowC7200 {
+ # Skip if this is not a 7200.
+ print STDERR " In ShowC7200: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ #return(1) if ($type !~ /^72/);
+ return(-1) if (/command authorization failed/i);
+ /^$/ && next;
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ if (/^(C7200 )?Midplane EEPROM:/) {
+ $_ = <INPUT>;
+ /revision\s+(\S+).*revision\s+(\S+)/;
+ ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n");
+ $_ = <INPUT>;
+ /number\s+(\S+)\s+Part number\s+(\S+)/;
+ ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n");
+ next;
+ }
+ if (/C720\d(VXR)? CPU EEPROM:/) {
+ my ($hvers,$rev,$part,$serial);
+ # npe400s report their cpu eeprom info differently w/ 12.0.21S
+ while (<INPUT>) {
+ /Hardware Revision\s+: (\S+)/ && ($hvers = $1) && next;
+ /Board Revision\s+: (\S+)/ && ($rev = $1) && next;
+ /Part Number\s+: (\S+)/ && ($part = $1) && next;
+ /Serial Number\s+: (\S+)/ && ($serial = $1) && next;
+ /revision\s+(\S+).*revision\s+(\S+)/ &&
+ ($hvers = $1, $rev = $2) && next;
+ /number\s+(\S+)\s+Part number\s+(\S+)/ &&
+ ($serial = $1, $part = $2) && next;
+ /^\s*$/ && last;
+ }
+ ProcessHistory("SLOT","","","!Slot CPU: hvers $hvers rev $rev\n");
+ ProcessHistory("SLOT","","","!Slot CPU: part $part, serial $serial\n!\n");
+ next;
+ }
+ }
+ return(0);
+}
+
+# This routine parses "show vtp status"
+sub ShowVTP {
+ print STDERR " In ShowVTP: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ #return(1) if ($type !~ /^(2900XL|3500XL|6000)$/);
+ return(-1) if (/command authorization failed/i);
+ next if (/^Configuration last modified by/);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ if (/^VTP Operating Mode\s+:\s+(Transparent|Server)/) {
+ $DO_SHOW_VLAN = 1;
+ }
+ ProcessHistory("COMMENTS","keysort","I0","!VTP: $_");
+ }
+ ProcessHistory("COMMENTS","keysort","I0","!\n");
+ return(0);
+}
+
+# This routine parses "show vlan"
+sub ShowVLAN {
+ print STDERR " In ShowVLAN: $_" if ($debug);
+
+ ($_ = <INPUT>, return(1)) if (!$DO_SHOW_VLAN);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Line has invalid autocommand /;
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /Ambiguous command/i;
+ # newer releases (~12.1(9)) place the vlan config in the normal
+ # configuration (write term).
+ return(1) if ($type =~ /^(3550|4500)$/);
+ #return(1) if ($type !~ /^(2900XL|3500XL|6000)$/);
+ return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ if (/^(<-+ More -+>)/) {
+ my($len) = length($1);
+ s/^$1\s{$len}//;
+ }
+
+ ProcessHistory("COMMENTS","keysort","IO","!VLAN: $_");
+ }
+ ProcessHistory("COMMENTS","keysort","IO","!\n");
+ return(0);
+}
+
+# This routine processes a "write term"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+ my($lineauto,$comment,$linecnt) = (0,0,0);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if (/(Invalid input detected|Type help or )/i);
+ return(0) if ($found_end); # Only do this routine once
+ return(-1) if (/command authorization failed/i);
+# # the pager can not be disabled per-session on the PIX
+# if (/^(<-+ More -+>)/) {
+# my($len) = length($1);
+# s/^$1\s{$len}//;
+# }
+
+# /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ $linecnt++;
+ $lineauto = 0 if (/^[^ ]/);
+# # skip the crap
+# if (/^(##+$|(Building|Current) configuration)/i) {
+# while (<INPUT>) {
+# next if (/^Current configuration\s*:/i);
+# next if (/^:/);
+# next if (/^([%!].*|\s*)$/);
+# next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S
+# last;
+# }
+# if (defined($config_register)) {
+# ProcessHistory("","","","!\nconfig-register $config_register\n");
+# }
+# tr/\015//d;
+# }
+# # some versions have other crap mixed in with the bits in the
+# # block above
+# /^! (Last configuration|NVRAM config last)/ && next;
+
+# # skip consecutive comment lines to avoid oscillating extra comment
+# # line on some access servers. grrr.
+# if (/^!/) {
+# next if ($comment);
+# ProcessHistory("","","",$_);
+# $comment++;
+# next;
+# }
+# $comment = 0;
+
+ # Dog gone Cool matches to process the rest of the config
+# /^tftp-server flash / && next; # kill any tftp remains
+# /^ntp clock-period / && next; # kill ntp clock-period
+# /^ length / && next; # kill length on serial lines
+# /^ width / && next; # kill width on serial lines
+# $lineauto = 1 if /^ modem auto/;
+# /^ speed / && $lineauto && next; # kill speed on serial lines
+# /^ clockrate / && next; # kill clockrate on serial interfaces
+# if (/^(enable )?(password|passwd)( level \d+)? / && $filter_pwds >= 1) {
+# ProcessHistory("ENABLE","","","!$1$2$3 <removed>\n");
+# next;
+# }
+# if (/^(enable secret) / && $filter_pwds >= 2) {
+# ProcessHistory("ENABLE","","","!$1 <removed>\n");
+# next;
+# }
+# if (/^username (\S+)(\s.*)? secret /) {
+# if ($filter_pwds >= 2) {
+# ProcessHistory("USER","keysort","$1","!username $1$2 secret <removed>\n");
+# } else {
+# ProcessHistory("USER","keysort","$1","$_");
+# }
+# next;
+# }
+ # Sort username and delete passwords.
+ if (/^username (\S+) password (\d) (\S+)(\s.*)$/) {
+ if ($filter_pwds >= 2) {
+ ProcessHistory("USER","keysort","$1","!username $1 password <removed>$4\n");
+ } elsif ($filter_pwds >= 1 && $2 ne "5") {
+ ProcessHistory("USER","keysort","$1","!username $1 password <removed>$4\n");
+ } else {
+ ProcessHistory("USER","keysort","$1","$_");
+ }
+ next;
+ }
+ # Sort any other username info.
+ /^username (\S+) .*$/ && ProcessHistory("USER","keysort","$1","$_") && next;
+ # Sort snmp user and delete passwords.
+ if (/^snmp-server user (\S+) (\S+) auth md5 (\S+) priv (\S+) localizedkey$/) {
+ if ($filter_pwds >= 2) {
+ ProcessHistory("SNMP-USER","keysort","$1","!snmp-server user $1 $2 auth md5 <removed> priv <removed> localizedkey\n");
+ } else {
+ ProcessHistory("SNMP-USER","keysort","$1","$_");
+ }
+ next;
+ }
+ # Sort any other snmp user info.
+ /^snmp-server user (\S+) .*$/ && ProcessHistory("SNMP-USER","keysort","$1","$_") && next;
+ # Delete bgp passwords.
+ if (/^(\s*)password (\d) (\S+)(\s.*)?$/) {
+ if ($filter_pwds >= 2) {
+ ProcessHistory("","","","!$1password <removed>$4");
+ } elsif ($filter_pwds >= 1 && $2 ne "5") {
+ ProcessHistory("","","","!$1password <removed>$4");
+ } else {
+ ProcessHistory("","","","$_");
+ }
+ next;
+ }
+# # cisco AP w/ IOS
+# if (/^(wlccp \S+ username (\S+)(\s.*)? password) (\d \S+|\S+)/) {
+# if ($filter_pwds >= 1) {
+# ProcessHistory("USER","keysort","$2","!$1 <removed>\n");
+# } else {
+# ProcessHistory("USER","keysort","$2","$_");
+# }
+# next;
+# }
+# if (/^( set session-key (in|out)bound ah \d+ )/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1<removed>\n");
+# next;
+# }
+# if (/^( set session-key (in|out)bound esp \d+ (authenticator|cypher) )/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1<removed>\n");
+# next;
+# }
+# if (/^(\s*)password / && $filter_pwds >= 1) {
+# ProcessHistory("LINE-PASS","","","!$1password <removed>\n");
+# next;
+# }
+# if (/^(\s*)secret / && $filter_pwds >= 2) {
+# ProcessHistory("LINE-PASS","","","!$1secret <removed>\n");
+# next;
+# }
+# if (/^\s*neighbor (\S*) password / && $filter_pwds >= 1) {
+# ProcessHistory("","","","! neighbor $1 password <removed>\n");
+# next;
+# }
+# if (/^(ppp .* password) 7 .*/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# if (/^(ip ftp password) / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# if (/^( ip ospf authentication-key) / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# # isis passwords appear to be completely plain-text
+# if (/^\s+isis password (\S+)( .*)?/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!isis password <removed>$2\n"); next;
+# }
+# if (/^\s+(domain-password|area-password) (\S+)( .*)?/
+# && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>$3\n"); next;
+# }
+# # this is reversable, despite 'md5' in the cmd
+# if (/^( ip ospf message-digest-key \d+ md5) / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# # this is also reversable, despite 'md5 encrypted' in the cmd
+# if (/^( message-digest-key \d+ md5 (7|encrypted)) / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# if (/^((crypto )?isakmp key) \S+ / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed> $'"); next;
+# }
+# # filter HSRP passwords
+# if (/^(\s+standby \d+ authentication) / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# # this appears in "measurement/sla" images
+# if (/^(\s+key-string \d?)/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# if (/^( l2tp tunnel \S+ password)/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# # i am told these are plain-text on the PIX
+# if (/^(vpdn username (\S+) password)/) {
+# if ($filter_pwds >= 1) {
+# ProcessHistory("USER","keysort","$2","!$1 <removed>\n");
+# } else {
+# ProcessHistory("USER","keysort","$2","$_");
+# }
+# next;
+# }
+# if (/^( cable shared-secret )/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n");
+# next;
+# }
+# /fair-queue individual-limit/ && next;
+# # sort ip explicit-paths.
+# if (/^ip explicit-path name (\S+)/) {
+# my($key) = $1;
+# my($expath) = $_;
+# while (<INPUT>) {
+# tr/\015//d;
+# last if (/^$prompt/);
+# last if (/^$prompt/ || ! /^(ip explicit-path name |[ !])/);
+# if (/^ip explicit-path name (\S+)/) {
+# ProcessHistory("EXPATH","keysort","$key","$expath");
+# $key = $1;
+# $expath = $_;
+# } else {
+# $expath .= $_;
+# }
+# }
+# ProcessHistory("EXPATH","keysort","$key","$expath");
+# }
+# # sort route-maps
+# if (/^route-map (\S+)/) {
+# my($key) = $1;
+# my($routemap) = $_;
+# while (<INPUT>) {
+# tr/\015//d;
+# last if (/^$prompt/ || ! /^(route-map |[ !])/);
+# if (/^route-map (\S+)/) {
+# ProcessHistory("ROUTEMAP","keysort","$key","$routemap");
+# $key = $1;
+# $routemap = $_;
+# } else {
+# $routemap .= $_;
+# }
+# }
+# ProcessHistory("ROUTEMAP","keysort","$key","$routemap");
+# }
+# # filter out any RCS/CVS tags to avoid confusing local CVS storage
+# s/\$(Revision|Id):/ $1:/;
+# # order access-lists
+# /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ &&
+# ProcessHistory("ACL $1 $2","$aclsort","$3","$_") && next;
+# # order extended access-lists
+# /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
+# ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next;
+# /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
+# ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next;
+# /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ &&
+# ProcessHistory("EACL $1 $2","$aclsort","0.0.0.0","$_") && next;
+# # order arp lists
+# /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
+# ProcessHistory("ARP","$aclsort","$1","$_") && next;
+# /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
+# ProcessHistory("PACL $1 $3","$aclsort","$4","ip prefix-list $1 $3 $4$5\n")
+# && next;
+# # order logging statements
+# /^logging (\d+\.\d+\.\d+\.\d+)/ &&
+# ProcessHistory("LOGGING","ipsort","$1","$_") && next;
+ # order cli alias names
+ /^cli alias name (\S+) .*$/ &&
+ ProcessHistory("CLI-ALIAS","keysort","$1","$_") && next;
+ # order snmp-server enable trap statements
+ /^snmp-server enable traps (.*)$/ &&
+ ProcessHistory("SNMP-TRAPS","keysort","$1","$_") && next;
+# # order/prune snmp-server host statements
+# # we only prune lines of the form
+# # snmp-server host a.b.c.d <community>
+# if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) {
+# if ($filter_commstr) {
+# my($ip) = $1;
+# my($line) = "snmp-server host $ip";
+# my(@tokens) = split(' ', $');
+# my($token);
+# while ($token = shift(@tokens)) {
+# if ($token eq 'version') {
+# $line .= " " . join(' ', ($token, shift(@tokens)));
+# if ($token eq '3') {
+# $line .= " " . join(' ', ($token, shift(@tokens)));
+# }
+# } elsif ($token eq 'vrf') {
+# $line .= " " . join(' ', ($token, shift(@tokens)));
+# } elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) {
+# $line .= " " . $token;
+# } else {
+# $line = "!$line " . join(' ', ("<removed>", join(' ',@tokens)));
+# last;
+# }
+# }
+# ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line\n");
+# } else {
+# ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_");
+# }
+# next;
+# }
+# if (/^(snmp-server community) (\S+)/) {
+# if ($filter_commstr) {
+# ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 <removed>$'") && next;
+# } else {
+# ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
+# }
+# }
+# # prune tacacs/radius server keys
+# if (/^((tacacs|radius)-server\s(\w*[-\s(\s\S+])*\s?key) (\d )?\w+/
+# && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>$'"); next;
+# }
+# # order clns host statements
+# /^clns host \S+ (\S+)/ &&
+# ProcessHistory("CLNS","keysort","$1","$_") && next;
+# # order alias statements
+# /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next;
+# # delete ntp auth password - this md5 is a reversable too
+# if (/^(ntp authentication-key \d+ md5) / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed>\n"); next;
+# }
+# # order ntp peers/servers
+# if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) {
+# $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5);
+# ProcessHistory("NTP","keysort",$sortkey,"$_");
+# next;
+# }
+# # order ip host statements
+# /^ip host (\S+) / &&
+# ProcessHistory("IPHOST","keysort","$1","$_") && next;
+# # order ip nat source static statements
+# /^ip nat (\S+) source static (\S+)/ &&
+# ProcessHistory("IP NAT $1","ipsort","$2","$_") && next;
+# # order atm map-list statements
+# /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ &&
+# ProcessHistory("ATM map-list","ipsort","$1","$_") && next;
+# # order ip rcmd lines
+# /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next;
+#
+# # system controller
+# /^syscon address (\S*) (\S*)/ &&
+# ProcessHistory("","","","!syscon address $1 <removed>\n") &&
+# next;
+# if (/^syscon password (\S*)/ && $filter_pwds >= 1) {
+# ProcessHistory("","","","!syscon password <removed>\n");
+# next;
+# }
+
+ # catch anything that wasnt matched above.
+ ProcessHistory("","","","$_");
+ # end of config. the ": " game is for the PIX
+ if (/^(: +)?end$/) {
+ $found_end = 1;
+ return(0);
+ }
+ }
+ # The ContentEngine lacks a definitive "end of config" marker. If we
+ # know that it is a CE, SAN, or NXOS and we have seen at least 5 lines
+ # of write term output, we can be reasonably sure that we got the config.
+ if (($type == "CE" || $type == "SAN" || $type == "NXOS" ) && $linecnt > 5) {
+ $found_end = 1;
+ return(0);
+ }
+
+ return(0);
+}
+
+# This routine parses a single command that returns no required info.
+sub RunCommand {
+ print STDERR " In RunCommand: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ return(1) if /Line has invalid autocommand /;
+ return(1) if (/(Invalid input detected|Type help or )/i);
+ }
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+##############################
+# add these:
+# show version module X - wait until can show all
+# show version module X epld - wait until can show all
+# show version fan X epld - wait until can show all
+# show version xbar X epld - wait until can show all
+# show license - get sample output
+# show license usage - chop grace
+# show license host-id
+##############################
+
+# Main
+@commandtable = (
+ {'term no monitor-force' => 'RunCommand'},
+ {'show version' => 'ShowVersion'},
+ {'show version build-info all' => 'ShowVersionBuild'},
+ {'show system redundancy status' => 'ShowRedundancy'},
+# {'show idprom backplane', => 'ShowIDprom'},
+ {'show environment clock' => 'ShowEnv'},
+ {'show environment fan' => 'ShowEnv'},
+ {'show environment temperature' => 'ShowEnvTemp'},
+ {'show environment power' => 'ShowEnv'},
+# {'show rsp chassis-info', => 'ShowRSP'},
+# {'show gsr chassis' => 'ShowGSR'},
+ {'show diag chassis-info' => 'ShowGSR'},
+ {'show boot' => 'ShowBoot'},
+ {'dir bootflash:' => 'DirSlotN'},
+ {'dir core:' => 'DirSlotN'},
+ {'dir debug:' => 'DirSlotN'},
+## {'dir log:' => 'DirSlotN'}, # not useful
+ {'dir logflash:' => 'DirSlotN'},
+ {'dir slot0:' => 'DirSlotN'},
+ {'dir usb1:' => 'DirSlotN'},
+ {'dir usb2:' => 'DirSlotN'},
+ {'dir volatile:' => 'DirSlotN'},
+# {'show controllers' => 'ShowContAll'},
+# {'show controllers cbus' => 'ShowContCbus'},
+ {'show diagbus' => 'ShowDiagbus'},
+ {'show diag' => 'ShowDiag'},
+ {'show module' => 'ShowModule'},
+ {'show module xbar' => 'ShowModule'},
+ {'show spe version' => 'ShowSpeVersion'},
+ {'show inventory' => 'ShowInventory'},
+ {'show vtp status' => 'ShowVTP'},
+ {'show vlan' => 'ShowVLAN'},
+ {'show vlan-switch' => 'ShowVLAN'},
+ {'show debug' => 'ShowDebug'},
+ {'show cores vdc-all' => 'ShowCores'},
+ {'show processes log vdc-all' => 'ShowProcLog'},
+ {'show running-config' => 'WriteTerm'},
+# {'write term' => 'WriteTerm'},
+);
+# Use an array to preserve the order of the commands and a hash for mapping
+# commands to the subroutine and track commands that have been completed.
+@commands = map(keys(%$_), @commandtable);
+%commands = map(%$_, @commandtable);
+
+$cisco_cmds = join(";",@commands);
+$cmds_regexp = join("|",@commands);
+
+if (length($host) == 0) {
+ if ($file) {
+ print(STDERR "Too few arguments: file name required\n");
+ exit(1);
+ } else {
+ print(STDERR "Too few arguments: host name required\n");
+ exit(1);
+ }
+}
+open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
+select(OUTPUT);
+# make OUTPUT unbuffered if debugging
+if ($debug) { $| = 1; }
+
+if ($file) {
+ print STDERR "opening file $host\n" if ($debug);
+ print STDOUT "opening file $host\n" if ($log);
+ open(INPUT,"<$host") || die "open failed for $host: $!\n";
+} else {
+ print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n";
+ }
+}
+
+# determine ACL sorting mode
+if ($ENV{"ACLSORT"} =~ /no/i) {
+ $aclsort = "";
+}
+# determine community string filtering mode
+if (defined($ENV{"NOCOMMSTR"}) &&
+ ($ENV{"NOCOMMSTR"} =~ /yes/i || $ENV{"NOCOMMSTR"} =~ /^$/)) {
+ $filter_commstr = 1;
+} else {
+ $filter_commstr = 0;
+}
+# determine password filtering mode
+if ($ENV{"FILTER_PWDS"} =~ /no/i) {
+ $filter_pwds = 0;
+} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
+ $filter_pwds = 2;
+} else {
+ $filter_pwds = 1;
+}
+
+ProcessHistory("","","","!RANCID-CONTENT-TYPE: cisco\n!\n");
+ProcessHistory("COMMENTS","keysort","B0","!\n");
+ProcessHistory("COMMENTS","keysort","D0","!\n");
+ProcessHistory("COMMENTS","keysort","F0","!\n");
+ProcessHistory("COMMENTS","keysort","G0","!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+
+ if (/[>#]\s?exit$/) {
+ print STDERR ("$host: found exit\n") if ($debug);
+ $clean_run = 1;
+ last;
+ }
+ if (/^Error:/) {
+ print STDOUT ("$host clogin error: $_");
+ print STDERR ("$host clogin error: $_") if ($debug);
+ $clean_run = 0;
+ last;
+ }
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]+#)/)[0];
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
+ }
+ print STDERR ("HIT COMMAND:$_") if ($debug);
+ if (! defined($commands{$cmd})) {
+ print STDERR "$host: found unexpected command - \"$cmd\"\n";
+ $clean_run = 0;
+ last TOP;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -1) {
+ $clean_run = 0;
+ print STDERR ("$host: $cmd failed: $rval\n") if ($debug);
+ last TOP;
+ }
+ if (/[>#]\s?exit$/) {
+ print STDERR ("$host: found exit\n") if ($debug);
+ $clean_run = 1;
+ last TOP;
+ }
+ }
+}
+print STDOUT "Done $logincmd: $_\n" if ($log);
+# Flush History
+ProcessHistory("","","","");
+# Cleanup
+close(INPUT);
+close(OUTPUT);
+
+if (defined($ENV{NOPIPE})) {
+ unlink("$host.raw") if (! $debug);
+}
+
+# check for completeness
+if (scalar(%commands) || !$clean_run || !$found_end) {
+ if (scalar(%commands)) {
+ printf(STDOUT "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
+ printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
+ }
+ if (!$clean_run || !$found_end) {
+ print STDOUT "$host: End of run not found\n";
+ print STDERR "$host: End of run not found\n" if ($debug);
+ print STDERR "$host: clean: $clean_run, end: $found_end\n" if ($debug);
+ system("/usr/bin/tail -1 $host.new");
+ }
+ unlink "$host.new" if (! $debug);
+}
diff --git a/bin/par.in b/bin/par.in
index e7559f0..e37c4a4 100644
--- a/bin/par.in
+++ b/bin/par.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/prancid.in b/bin/prancid.in
index 5228da7..c431b93 100755
--- a/bin/prancid.in
+++ b/bin/prancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/rancid-cvs.in b/bin/rancid-cvs.in
index 86ca065..17960e0 100644
--- a/bin/rancid-cvs.in
+++ b/bin/rancid-cvs.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -128,9 +128,9 @@ do
cd $BASEDIR
cvs checkout $GROUP
else
- svn import -m "$GROUP" . file://$CVSROOT/$GROUP
+ svn import -m "$GROUP" . file:///$CVSROOT/$GROUP
cd $BASEDIR
- svn checkout file://$CVSROOT/$GROUP $GROUP
+ svn checkout file:///$CVSROOT/$GROUP $GROUP
fi
fi
cd $DIR
diff --git a/bin/rancid-fe.in b/bin/rancid-fe.in
index d5c68c2..a76bc4d 100644
--- a/bin/rancid-fe.in
+++ b/bin/rancid-fe.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -51,17 +51,20 @@ require 5;
$vendor =~ tr/[A-Z]/[a-z]/;
%vendortable = (
+ 'agm' => 'agmrancid',
'alteon' => 'arancid',
'avocent' => 'avorancid',
'baynet' => 'brancid',
'bigip' => 'f5rancid',
'cat5' => 'cat5rancid',
'cisco' => 'rancid',
+ 'cisco-nx' => 'nxrancid',
'css' => 'cssrancid',
'enterasys' => 'rivrancid',
'erx' => 'jerancid',
'extreme' => 'xrancid',
'ezt3' => 'erancid',
+ 'f5' => 'f5rancid',
'force10' => 'f10rancid',
'fortigate' => 'fnrancid',
'foundry' => 'francid',
@@ -69,11 +72,12 @@ $vendor =~ tr/[A-Z]/[a-z]/;
'hp' => 'hrancid',
'juniper' => 'jrancid',
'mrtd' => 'mrancid',
+ 'mrv' => 'mrvrancid',
+ 'netopia' => 'trancid',
'netscaler' => 'nsrancid',
'netscreen' => 'nrancid',
'procket' => 'prancid',
'redback' => 'rrancid',
- 'riverhead' => 'agmrancid',
'riverstone' => 'rivrancid',
'smc' => 'srancid',
'tnt' => 'tntrancid',
diff --git a/bin/rancid-run.in b/bin/rancid-run.in
index ae24912..40ca26d 100644
--- a/bin/rancid-run.in
+++ b/bin/rancid-run.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/rancid.in b/bin/rancid.in
index 45baa5c..6926691 100644
--- a/bin/rancid.in
+++ b/bin/rancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -39,7 +39,7 @@
## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
## POSSIBILITY OF SUCH DAMAGE.
-#
+#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-dV] [-l] [-f filename | hostname]
@@ -64,6 +64,7 @@ $timeo = 90; # clogin timeout in seconds
my(@commandtable, %commands, @commands);# command lists
my($aclsort) = ("ipsort"); # ACL sorting mode
+my($config_register); # configuration register value
my($filter_commstr); # SNMP community string filtering
my($filter_pwds); # password filtering mode
@@ -174,7 +175,7 @@ sub ShowVersion {
while (<INPUT>) {
tr/\015//d;
- if (/^$prompt/) { $found_version=1; last};
+ if (/^$prompt/) { $found_version = 1; last};
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
@@ -192,7 +193,12 @@ sub ShowVersion {
next;
}
if (/cisco ios xr /i) { $ios = "XR"; }
- if (/^Application and Content Networking Software/) { $type="CE"; }
+ if (/cisco ios .* IOS-XE/i) { $ios = "XE"; }
+ if (/^Application and Content Networking Software/) { $type = "CE"; }
+ # treat the ACE like the Content Engines for matching endofconfig
+ if (/^Cisco Application Control Software/) { $type = "CE"; }
+ if (/^Cisco Storage Area Networking Operating System/) { $type = "SAN";}
+ if (/^Cisco Nexus Operating System/) { $type = "NXOS";}
/^Application and Content Networking Software Release /i &&
ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
/^Cisco Secure PIX /i &&
@@ -375,7 +381,7 @@ sub ShowVersion {
}
if (/(\S+) Silicon\s*Switch Processor/) {
if (!defined($C0)) {
- $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");
+ $C0 = 1; ProcessHistory("COMMENTS","keysort","C0","!\n");
}
ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n");
$ssp = 1;
@@ -402,19 +408,24 @@ sub ShowVersion {
"!Memory: pcmcia $2 $3$4 $1\n");
next;
}
+ if (/^(\d+[kK]) bytes of (slot|disk)(\d)/i) {
+ ProcessHistory("COMMENTS","keysort","B7",
+ "!Memory: pcmcia $2$3 $1\n");
+ next;
+ }
if (/^WARNING/) {
if (!defined($I0)) {
- $I0=1;
+ $I0 = 1;
ProcessHistory("COMMENTS","keysort","I0","!\n");
}
ProcessHistory("COMMENTS","keysort","I1","! $_");
}
if (/^Configuration register is (.*)$/) {
- $config_register=$1;
+ $config_register = $1;
next;
}
if (/^Configuration register on node \S+ is (.*)$/) {
- $config_register=$1 if $config_register eq "";
+ $config_register = $1 if (length($config_register) < 1);
next;
}
}
@@ -517,7 +528,7 @@ sub ShowEnv {
while (<INPUT>) {
tr/\015//d;
- if (/^$prompt/) { $found_env=1; last};
+ if (/^$prompt/) { $found_env = 1; last};
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^7/);
return(1) if /Line has invalid autocommand /;
@@ -531,12 +542,12 @@ sub ShowEnv {
}
if (!defined($E0)) {
- $E0=1;
+ $E0 = 1;
ProcessHistory("COMMENTS","keysort","E0","!\n");
}
if (/^Arbiter type (\d), backplane type (\S+)/) {
if (!defined($C0)) {
- $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");
+ $C0 = 1; ProcessHistory("COMMENTS","keysort","C0","!\n");
}
ProcessHistory("COMMENTS","keysort","C1",
"!Enviromental Arbiter Type: $1\n");
@@ -656,7 +667,7 @@ sub ShowBoot {
next if /CONFGEN variable/;
if (!defined($H0)) {
- $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n");
+ $H0 = 1; ProcessHistory("COMMENTS","keysort","H0","!\n");
}
if ($type !~ /^(12[04]|7)/) {
if ($type !~ /^(29|35)00/) {
@@ -718,14 +729,25 @@ sub DirSlotN {
return(1) if /(No such device|Error Sending Request)/i;
return(1) if /\%Error: No such file or directory/;
return(1) if /No space information available/;
+ # Corrupt flash
+ /\%Error calling getdents / &&
+ ProcessHistory("FLASH","","","!Flash: $dev: $_") && next;
return(-1) if /\%Error calling/;
return(-1) if /(: device being squeezed|ATA_Status time out)/i; # busy
return(-1) if (/command authorization failed/i);
return(1) if /(Open device \S+ failed|Error opening \S+:)/;
- if (/.*\((\d+) bytes free\)/ && $ios eq "XR") {
+ # filter frequently changing files from IOX bootflash
+ if ($dev =~ /bootflash/) {
+ next if (/temp_cont\s*$/);
+ next if (/uptime_cont\s*$/);
+ }
+ if (($ios eq "XR" || $ios eq "XE") && /.*\((\d+) bytes free\)/) {
my($tmp) = int($1 / (1024 * 1024));
s/$1 bytes free/$tmp MB free/;
}
+ if ($ios eq "XE" && /^((\s+)?\d+\s+\S+)\s+\d+.*(tracelogs$)/) {
+ $_ = "$1" . sprintf("%43s", "") . "$3\n";
+ }
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
@@ -873,6 +895,7 @@ sub ShowDebug {
}
/^No matching debug flags set$/ && next;
+ /^No debug flags set$/ && next;
ProcessHistory("COMMENTS","keysort","J1","!DEBUG: $_");
$lines++;
}
@@ -984,7 +1007,7 @@ sub ShowDiag {
while (<INPUT>) {
REDUX: tr/\015//d;
- if (/^$prompt/) { $found_diag=1; last};
+ if (/^$prompt/) { $found_diag = 1; last};
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type !~ /^(12[40]|720|36|26)/);
return(1) if /Line has invalid autocommand /;
@@ -1061,7 +1084,7 @@ REDUX: tr/\015//d;
next;
}
if (/^c3700\s+(io-board|mid-plane)/i) {
- $slot=$1;
+ $slot = $1;
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","A","!Slot $slot: part $1\n");
next;
@@ -1081,6 +1104,10 @@ REDUX: tr/\015//d;
ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Packet Memory: $1\n");
next;
}
+ if (/\s+Route Memory:\s+(\S+)/) {
+ ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Route Memory: $1\n");
+ next;
+ }
if (/^\s+PCA:\s+(.*)/) {
local($part) = $1;
$_ = <INPUT>;
@@ -1495,6 +1522,7 @@ sub WriteTerm {
last if (/^$prompt/);
return(1) if /Line has invalid autocommand /;
return(1) if (/(Invalid input detected|Type help or )/i);
+ return(1) if /\%Error: No such file or directory/;
return(0) if ($found_end); # Only do this routine once
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
@@ -1502,12 +1530,15 @@ sub WriteTerm {
my($len) = length($1);
s/^$1\s{$len}//;
}
+ if (!$linecnt && defined($config_register)) {
+ ProcessHistory("","","", "!\nconfig-register $config_register\n");
+ }
/Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
$linecnt++;
$lineauto = 0 if (/^[^ ]/);
# skip the crap
- if (/^(##+$|(Building|Current) configuration)/i) {
+ if (/^(##+|(building|current) configuration)/i) {
while (<INPUT>) {
next if (/^Current configuration\s*:/i);
next if (/^:/);
@@ -1515,9 +1546,6 @@ sub WriteTerm {
next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S
last;
}
- if (defined($config_register)) {
- ProcessHistory("","","","!\nconfig-register $config_register\n");
- }
tr/\015//d;
}
# some versions have other crap mixed in with the bits in the
@@ -1552,7 +1580,8 @@ sub WriteTerm {
}
if (/^username (\S+)(\s.*)? secret /) {
if ($filter_pwds >= 2) {
- ProcessHistory("USER","keysort","$1","!username $1$2 secret <removed>\n");
+ ProcessHistory("USER","keysort","$1",
+ "!username $1$2 secret <removed>\n");
} else {
ProcessHistory("USER","keysort","$1","$_");
}
@@ -1560,9 +1589,11 @@ sub WriteTerm {
}
if (/^username (\S+)(\s.*)? password ((\d) \S+|\S+)/) {
if ($filter_pwds >= 2) {
- ProcessHistory("USER","keysort","$1","!username $1$2 password <removed>\n");
+ ProcessHistory("USER","keysort","$1",
+ "!username $1$2 password <removed>\n");
} elsif ($filter_pwds >= 1 && $4 ne "5"){
- ProcessHistory("USER","keysort","$1","!username $1$2 password <removed>\n");
+ ProcessHistory("USER","keysort","$1",
+ "!username $1$2 password <removed>\n");
} else {
ProcessHistory("USER","keysort","$1","$_");
}
@@ -1581,7 +1612,8 @@ sub WriteTerm {
ProcessHistory("","","","!$1<removed>\n");
next;
}
- if (/^( set session-key (in|out)bound esp \d+ (authenticator|cypher) )/ && $filter_pwds >= 1) {
+ if (/^( set session-key (in|out)bound esp \d+ (authenticator|cypher) )/
+ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1<removed>\n");
next;
}
@@ -1619,7 +1651,8 @@ sub WriteTerm {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
# this is also reversable, despite 'md5 encrypted' in the cmd
- if (/^( message-digest-key \d+ md5 (7|encrypted)) / && $filter_pwds >= 1) {
+ if (/^( message-digest-key \d+ md5 (7|encrypted)) /
+ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
if (/^((crypto )?isakmp key) \S+ / && $filter_pwds >= 1) {
@@ -1645,6 +1678,11 @@ sub WriteTerm {
}
next;
}
+ # ASA/PIX keys in more system:running-config
+ if (/^( pre-shared-key |failover key ).*/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed> $'"); next;
+ }
+ #
if (/^( cable shared-secret )/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n");
next;
@@ -1726,7 +1764,8 @@ sub WriteTerm {
} elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) {
$line .= " " . $token;
} else {
- $line = "!$line " . join(' ', ("<removed>", join(' ',@tokens)));
+ $line = "!$line " . join(' ', ("<removed>",
+ join(' ',@tokens)));
last;
}
}
@@ -1738,7 +1777,8 @@ sub WriteTerm {
}
if (/^(snmp-server community) (\S+)/) {
if ($filter_commstr) {
- ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 <removed>$'") && next;
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_",
+ "!$1 <removed>$'") && next;
} else {
ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
}
@@ -1784,6 +1824,8 @@ sub WriteTerm {
next;
}
+ /^Cryptochecksum:/ && next;
+
# catch anything that wasnt matched above.
ProcessHistory("","","","$_");
# end of config. the ": " game is for the PIX
@@ -1793,9 +1835,9 @@ sub WriteTerm {
}
}
# The ContentEngine lacks a definitive "end of config" marker. If we
- # know that it is a CE and we have seen at least 5 lines of write term
- # o/p, we can be reasonably sure that we got the config.
- if ($type =~ /^CE$/ && $linecnt > 5) {
+ # know that it is a CE, SAN, or NXOS and we have seen at least 5 lines
+ # of write term output, we can be reasonably sure that we got the config.
+ if (($type == "CE" || $type == "SAN" || $type == "NXOS" ) && $linecnt > 5) {
$found_end = 1;
return(0);
}
@@ -1866,6 +1908,7 @@ sub DoNothing {print STDOUT;}
{'show vlan' => 'ShowVLAN'},
{'show vlan-switch' => 'ShowVLAN'},
{'show debug' => 'ShowDebug'},
+ {'more system:running-config' => 'WriteTerm'}, # ASA/PIX
{'show running-config' => 'WriteTerm'},
{'write term' => 'WriteTerm'},
);
@@ -1874,8 +1917,8 @@ sub DoNothing {print STDOUT;}
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);
-$cisco_cmds=join(";",@commands);
-$cmds_regexp=join("|",@commands);
+$cisco_cmds = join(";",@commands);
+$cmds_regexp = join("|",@commands);
if (length($host) == 0) {
if ($file) {
@@ -1934,13 +1977,13 @@ ProcessHistory("COMMENTS","keysort","G0","!\n");
TOP: while(<INPUT>) {
tr/\015//d;
if (/[>#]\s?exit$/) {
- $clean_run=1;
+ $clean_run = 1;
last;
}
if (/^Error:/) {
print STDOUT ("$host clogin error: $_");
print STDERR ("$host clogin error: $_") if ($debug);
- $clean_run=0;
+ $clean_run = 0;
last;
}
while (/#\s*($cmds_regexp)\s*$/) {
diff --git a/bin/rivlogin.in b/bin/rivlogin.in
index 7a65986..b9ca2bc 100644
--- a/bin/rivlogin.in
+++ b/bin/rivlogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -255,7 +255,7 @@ proc login { router user userpswd passwd enapasswd } {
"Password:" {
incr pass_attempt
- send "$passwd\r"
+ send -- "$passwd\r"
exp_continue
}
@@ -263,16 +263,16 @@ proc login { router user userpswd passwd enapasswd } {
set pattempt 0
- send "$user\r"
+ send -- "$user\r"
expect {
"Password: " {
incr pattempt
if {$pattempt == 1} {
- send "$userpswd\r";
+ send -- "$userpswd\r";
} else {
- send "$enapasswd\r";
+ send -- "$enapasswd\r";
}
exp_continue
}
@@ -418,14 +418,14 @@ proc do_enable { enauser enapasswd userpswd } {
expect {
Username: {
set uses_username 1;
- send "$enauser\r";
+ send -- "$enauser\r";
exp_continue
}
Password: {
if {$uses_username == 1} {
- send "$userpswd\r";
+ send -- "$userpswd\r";
} else {
- send "$enapasswd\r";
+ send -- "$enapasswd\r";
}
exp_continue
}
@@ -435,7 +435,7 @@ proc do_enable { enauser enapasswd userpswd } {
return 1
}
- "CONS-W-AUTH_PASSWD" { send "$enapasswd\r"; }
+ "CONS-W-AUTH_PASSWD" { send -- "$enapasswd\r"; }
"$enable_prompt " { }
"%SYS-W-NOPASSWD*" { }
diff --git a/bin/rivrancid.in b/bin/rivrancid.in
index 0e86994..b647264 100644
--- a/bin/rivrancid.in
+++ b/bin/rivrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/rrancid.in b/bin/rrancid.in
index 78eb000..d55afc7 100644
--- a/bin/rrancid.in
+++ b/bin/rrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/srancid.in b/bin/srancid.in
index b59917c..f8549c5 100755
--- a/bin/srancid.in
+++ b/bin/srancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/tlogin.in b/bin/tlogin.in
new file mode 100644
index 0000000..e097da1
--- /dev/null
+++ b/bin/tlogin.in
@@ -0,0 +1,815 @@
+#! @EXPECT_PATH@ --
+##
+## $Id$
+##
+## Copyright (C) 1997-2008 by Terrapin Communications, Inc.
+## All rights reserved.
+##
+## This software may be freely copied, modified and redistributed
+## without fee for non-commerical purposes provided that this license
+## remains intact and unmodified with any RANCID distribution.
+##
+## There is no warranty or other guarantee of fitness of this software.
+## It is provided solely "as is". The author(s) disclaim(s) all
+## responsibility and liability with respect to this software's usage
+## or its effect upon hardware, computer systems, other software, or
+## anything else.
+##
+## Except where noted otherwise, rancid was written by and is maintained by
+## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
+##
+#
+# The login expect scripts were based on Erik Sherk's gwtn, by permission.
+#
+# tlogin - Netopis login
+#
+# Modified by Ed Ravin for Netopia.
+
+# Usage line
+set usage "Usage: $argv0 \[-autoenable\] \[-noenable\] \[-c command\] \
+\[-debug] \
+\[-Evar=x\] \[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \
+\[-s script-file\] \[-t timeout\] \[-u username\] \
+\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \
+\[-y ssh_cypher_type\] router \[router...\]\n"
+
+# env(CLOGIN) may contain:
+# x == do not set xterm banner or name
+
+# Password file
+set password_file $env(HOME)/.cloginrc
+# Default is to login to the router
+set do_command 0
+set do_script 0
+# The default is to automatically enable
+set avenable 1
+# The default is that you login non-enabled (tacacs can have you login already
+# enabled)
+set avautoenable 0
+# The default is to look in the password file to find the passwords. This
+# tracks if we receive them on the command line.
+set do_passwd 1
+set do_enapasswd 1
+# attempt at platform switching.
+set platform ""
+
+# Find the user in the ENV, or use the unix userid.
+if {[ info exists env(CISCO_USER) ] } {
+ set default_user $env(CISCO_USER)
+} elseif {[ info exists env(USER) ]} {
+ set default_user $env(USER)
+} elseif {[ info exists env(LOGNAME) ]} {
+ set default_user $env(LOGNAME)
+} else {
+ # This uses "id" which I think is portable. At least it has existed
+ # (without options) on all machines/OSes I've been on recently -
+ # unlike whoami or id -nu.
+ if [ catch {exec id} reason ] {
+ send_error "\nError: could not exec id: $reason\n"
+ exit 1
+ }
+ regexp {\(([^)]*)} "$reason" junk default_user
+}
+
+# Sometimes routers take awhile to answer (the default is 10 sec)
+set timeout 45
+
+# Process the command line
+for {set i 0} {$i < $argc} {incr i} {
+ set arg [lindex $argv $i]
+
+ switch -glob -- $arg {
+ # Username
+ -u* -
+ -U* {
+ if {! [ regexp .\[uU\](.+) $arg ignore user]} {
+ incr i
+ set username [ lindex $argv $i ]
+ }
+ # VTY Password
+ } -p* -
+ -P* {
+ if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} {
+ incr i
+ set userpasswd [ lindex $argv $i ]
+ }
+ set do_passwd 0
+ # VTY Password
+ } -v* -
+ -v* {
+ if {! [ regexp .\[vV\](.+) $arg ignore passwd]} {
+ incr i
+ set passwd [ lindex $argv $i ]
+ }
+ set do_passwd 0
+ # Enable Username
+ } -w* -
+ -W* {
+ if {! [ regexp .\[wW\](.+) $arg ignore enauser]} {
+ incr i
+ set enausername [ lindex $argv $i ]
+ }
+ # Environment variable to pass to -s scripts
+ } -E*
+ {
+ if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ set E$varname $varvalue
+ } else {
+ send_user "\nError: invalid format for -E in $arg\n"
+ exit 1
+ }
+ # Enable Password
+ } -e*
+ {
+ if {! [ regexp .\[e\](.+) $arg ignore enapasswd]} {
+ incr i
+ set enapasswd [ lindex $argv $i ]
+ }
+ set do_enapasswd 0
+ # Command to run.
+ } -c* -
+ -C* {
+ if {! [ regexp .\[cC\](.+) $arg ignore command]} {
+ incr i
+ set command [ lindex $argv $i ]
+ }
+ set do_command 1
+ # Expect script to run.
+ } -s* -
+ -S* {
+ if {! [ regexp .\[sS\](.+) $arg ignore sfile]} {
+ incr i
+ set sfile [ lindex $argv $i ]
+ }
+ if { ! [ file readable $sfile ] } {
+ send_user "\nError: Can't read $sfile\n"
+ exit 1
+ }
+ set do_script 1
+ # 'ssh -c' cypher type
+ } -y* -
+ -Y* {
+ if {! [ regexp .\[eE\](.+) $arg ignore cypher]} {
+ incr i
+ set cypher [ lindex $argv $i ]
+ }
+ # alternate cloginrc file
+ } -f* -
+ -F* {
+ if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
+ incr i
+ set password_file [ lindex $argv $i ]
+ }
+ # Timeout
+ } -t* -
+ -T* {
+ if {! [ regexp .\[tT\](.+) $arg ignore timeout]} {
+ incr i
+ set timeout [ lindex $argv $i ]
+ }
+ # Command file
+ } -x* -
+ -X {
+ if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} {
+ incr i
+ set cmd_file [ lindex $argv $i ]
+ }
+ if [ catch {set cmd_fd [open $cmd_file r]} reason ] {
+ send_user "\nError: $reason\n"
+ exit 1
+ }
+ set cmd_text [read $cmd_fd]
+ close $cmd_fd
+ set command [join [split $cmd_text \n] \;]
+ set do_command 1
+ # Do we enable?
+ } -noenable {
+ set avenable 0
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ set avautoenable 1
+ set avenable 0
+ } -debug {
+ exp_internal 1
+ } -* {
+ send_user "\nError: Unknown argument! $arg\n"
+ send_user $usage
+ exit 1
+ } default {
+ break
+ }
+ }
+}
+# Process routers...no routers listed is an error.
+if { $i == $argc } {
+ send_user "\nError: $usage"
+}
+
+# Only be quiet if we are running a script (it can log its output
+# on its own)
+if { $do_script } {
+ log_user 0
+} else {
+ log_user 1
+}
+
+#
+# Done configuration/variable setting. Now run with it...
+#
+
+# Sets Xterm title if interactive...if its an xterm and the user cares
+proc label { host } {
+ global env
+ # if CLOGIN has an 'x' in it, don't set the xterm name/banner
+ if [info exists env(CLOGIN)] {
+ if {[string first "x" $env(CLOGIN)] != -1} { return }
+ }
+ # take host from ENV(TERM)
+ if [info exists env(TERM)] {
+ if [regexp \^(xterm|vs) $env(TERM) ignore ] {
+ send_user "\033]1;[lindex [split $host "."] 0]\a"
+ send_user "\033]2;$host\a"
+ }
+ }
+}
+
+# This is a helper function to make the password file easier to
+# maintain. Using this the password file has the form:
+# add password sl* pete cow
+# add password at* steve
+# add password * hanky-pie
+proc add {var args} { global int_$var ; lappend int_$var $args}
+proc include {args} {
+ global env
+ regsub -all "(^{|}$)" $args {} args
+ if { [ regexp "^/" $args ignore ] == 0 } {
+ set args $env(HOME)/$args
+ }
+ source_password_file $args
+}
+
+proc find {var router} {
+ upvar int_$var list
+ if { [info exists list] } {
+ foreach line $list {
+ if { [string match [lindex $line 0] $router ] } {
+ return [lrange $line 1 end]
+ }
+ }
+ }
+ return {}
+}
+
+# Loads the password file. Note that as this file is tcl, and that
+# it is sourced, the user better know what to put in there, as it
+# could install more than just password info... I will assume however,
+# that a "bad guy" could just as easy put such code in the clogin
+# script, so I will leave .cloginrc as just an extention of that script
+proc source_password_file { password_file } {
+ global env
+ if { ! [file exists $password_file] } {
+ send_user "\nError: password file ($password_file) does not exist\n"
+ exit 1
+ }
+ file stat $password_file fileinfo
+ if { [expr ($fileinfo(mode) & 007)] != 0000 } {
+ send_user "\nError: $password_file must not be world readable/writable\n"
+ exit 1
+ }
+ if [ catch {source $password_file} reason ] {
+ send_user "\nError: $reason\n"
+ exit 1
+ }
+}
+
+# Log into the router.
+proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
+ global spawn_id in_proc do_command do_script platform
+ global prompt u_prompt p_prompt e_prompt sshcmd usercmd usercmd_chat
+ global otpinuse
+ set in_proc 1
+ set uprompt_seen 0
+
+ # try each of the connection methods in $cmethod until one is successful
+ set progs [llength $cmethod]
+ foreach prog [lrange $cmethod 0 end] {
+ if [string match "telnet*" $prog] {
+ regexp {telnet(:([^[:space:]]+))*} $prog command suffix port
+ if {"$port" == ""} {
+ set retval [ catch {spawn telnet $router} reason ]
+ } else {
+ set retval [ catch {spawn telnet $router $port} reason ]
+ }
+ if { $retval } {
+ send_user "\nError: telnet failed: $reason\n"
+ exit 1
+ }
+ } elseif [string match "ssh*" $prog] {
+ regexp {ssh(:([^[:space:]]+))*} $prog command suffix port
+ if {"$port" == ""} {
+ set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ]
+
+ } else {
+ set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user -p $port $router} reason ]
+ }
+ if { $retval } {
+ send_user "\nError: $sshcmd failed: $reason\n"
+ exit 1
+ }
+ } elseif [string match "usercmd" $prog] { # user supplies connect cmd
+ set retval [ catch {eval spawn $usercmd} reason ]
+ if { $retval } {
+ send_user "\nError: '$usercmd' failed: $reason\n"
+ exit 1
+ }
+ if { [llength $usercmd_chat] > 0 } {
+ #send_user "\nExecuting usercmd_chat: $usercmd_chat\n"
+ sleep 0.3
+ foreach {i j} $usercmd_chat {
+ expect {
+ -re $i { eval send -- "\"$j\""}
+ timeout { send "\r"; send_user "\nTimeout in usercmd_chat waiting for -re $i: punting with CR\n"; break }
+ }
+ }
+ }
+ } elseif ![string compare $prog "rsh"] {
+ if [ catch {spawn rsh -l $user $router} reason ] {
+ send_user "\nError: rsh failed: $reason\n"
+ exit 1
+ }
+ } else {
+ puts "\nError: unknown connection method: $prog"
+ return 1
+ }
+ incr progs -1
+ sleep 0.3
+
+ # This helps cleanup each expect clause.
+ expect_after {
+ timeout {
+ send_user "\nError: TIMEOUT reached\n"
+ catch {close}; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ } eof {
+ send_user "\nError: EOF received\n"
+ catch {close}; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ }
+ }
+
+ # Here we get a little tricky. There are several possibilities:
+ # the router can ask for a username and passwd and then
+ # talk to the TACACS server to authenticate you, or if the
+ # TACACS server is not working, then it will use the enable
+ # passwd. Or, the router might not have TACACS turned on,
+ # then it will just send the passwd.
+ # if telnet fails with connection refused, try ssh
+ expect {
+ -re "(Connection refused|Secure connection \[^\n\r]+ refused)" {
+ catch {close}; wait
+ if !$progs {
+ send_user "\nError: Connection Refused ($prog): $router\n"
+ return 1
+ }
+ }
+ -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
+ catch {close}; wait
+ if !$progs {
+ send_user "\nError: Connection closed ($prog): $router\n"
+ return 1
+ }
+ }
+ eof { send_user "\nError: Couldn't login: $router\n"; wait; return 1 }
+ -nocase "unknown host\r" {
+ catch {close};
+ send_user "\nError: Unknown host $router\n"; wait; return 1
+ }
+ "Host is unreachable" {
+ catch {close};
+ send_user "\nError: Host Unreachable: $router\n"; wait; return 1
+ }
+ "No address associated with name" {
+ catch {close};
+ send_user "\nError: Unknown host $router\n"; wait; return 1
+ }
+ -re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
+ send "yes\r"
+ send_user "\nHost $router added to the list of known hosts.\n"
+ exp_continue }
+ -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
+ send "no\r"
+ send_user "\nError: The host key for $router has changed. Update the SSH known_hosts file accordingly.\n"
+ return 1 }
+ -re "Offending key for .* \(yes\/no\)\?" {
+ send "no\r"
+ send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n"
+ return 1 }
+ -re "(denied|Sorry)" {
+ send_user "\nError: Check your passwd for $router\n"
+ catch {close}; wait; return 1
+ }
+ "Login failed" {
+ send_user "\nError: Check your passwd for $router\n"
+ return 1
+ }
+ -re "% (Bad passwords|Authentication failed)" {
+ send_user "\nError: Check your passwd for $router\n"
+ return 1
+ }
+ "Press any key to continue." {
+ # send_user "Pressing the ANY key\n"
+ send "\r"
+ exp_continue
+ }
+ -re "Enter Selection: " {
+ # Catalyst 1900s have some lame menu. Enter
+ # K to reach a command-line.
+ send "K\r"
+ exp_continue;
+ }
+ -re "Netopia.*always start from this main screen" {
+ # send control-N to escape from the Playskool menu
+ send -- "\x0e"
+ set platform "netopia"
+ set prompt "#"
+ set autoenable 1
+ return 0
+ }
+ -re "@\[^\r\n]+ $p_prompt" {
+ # ssh pwd prompt
+ sleep 1
+ send -- "$userpswd\r"
+ exp_continue
+ }
+ -re "$u_prompt" {
+ send -- "$user\r"
+ set uprompt_seen 1
+ exp_continue
+ }
+ -re "(s/key|otp-\[0-9a-zA-Z]+) +\[0-9]+ +\[-0-9a-zA-Z]+\[ \r\n]" {
+ if { !$otpinuse} {
+ exp_continue
+ }
+ set challenge $expect_out(0,string)
+ regsub {[ \r\n]$} $challenge {} challenge
+ if [ catch {exec otphelper $router "$challenge"} userpswd ] {
+ send_error "\nError: login: 'otphelper $router $challenge' failed.\nRun otphelper standalone to diagnose further.\n"
+ exit 1
+ }
+ exp_continue
+ }
+ -re "$p_prompt" {
+ sleep 1
+ if {$uprompt_seen == 1} {
+ send -- "$userpswd\r"
+ } else {
+ send -- "$passwd\r"
+ }
+ exp_continue
+ }
+ -re "$prompt" { break; }
+ "Login invalid" {
+ send_user "\nError: Invalid login: $router\n";
+ catch {close}; wait; return 1
+ }
+ }
+ }
+
+ set in_proc 0
+ return 0
+}
+
+# Enable
+proc do_enable { enauser enapasswd } {
+ global prompt in_proc
+ global u_prompt e_prompt
+ global router otpinuse
+ set in_proc 1
+
+ send "enable\r"
+ expect {
+ -re "(s/key|otp-\[0-9a-zA-Z]+) +\[0-9]+ +\[-0-9a-zA-Z]+\[ \r\n]" {
+ if { !$otpinuse} {
+ exp_continue
+ }
+ set challenge $expect_out(0,string)
+ regsub {[ \r\n]$} $challenge {} challenge
+ if [ catch {exec otphelper $router "$challenge"} enapasswd ] {
+ send_error "\nError: enable: 'otphelper $router $challenge' failed.\nRun otphelper standalone to diagnose further.\n"
+ exit 1
+ }
+ exp_continue
+ }
+ -re "$u_prompt" { send -- "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send -- "$enapasswd\r"; exp_continue}
+ "#" { set prompt "#" }
+ "(enable)" { set prompt "> (enable) " }
+ -re "(denied|Sorry|Incorrect)" {
+ # % Access denied - from local auth and poss. others
+ send_user "\nError: Check your Enable passwd\n";
+ return 1
+ }
+ "% Error in authentication" {
+ send_user "\nError: Check your Enable passwd\n"
+ return 1
+ }
+ "% Bad passwords" {
+ send_user "\nError: Check your Enable passwd\n"
+ return 1
+ }
+ }
+ # We set the prompt variable (above) so script files don't need
+ # to know what it is.
+ set in_proc 0
+ return 0
+}
+
+# Run commands given on the command line.
+proc run_commands { prompt command } {
+ global in_proc platform
+ set in_proc 1
+
+ # If the prompt is (enable), then we are on a switch and the
+ # command is "set length 0"; otherwise its "term length 0".
+ # skip if its an extreme (since the pager can not be disabled on a
+ # per-vty basis).
+ if { [ string compare "extreme" "$platform" ] } {
+ if [ regexp -- ".*> .*enable" "$prompt" ] {
+ send "set length 0\r"
+ # This is ugly, but reduces code duplication, allowing the
+ # subsequent expects to handle everything as normal.
+ set command "set logging session disable;$command"
+ } elseif { ![ string compare "netopia" "$platform" ] } {
+ # kludge - should instead skip re-sensing prompt if platform netopia
+ set prompt "#"
+ } else {
+ send "term length 0\r"
+ }
+ # escape any parens in the prompt, such as "(enable)"
+ regsub -all {[)(]} $prompt {\\&} reprompt
+ # match cisco config mode prompts too, such as router(config-if)#,
+ # but catalyst does not change in this fashion.
+ regsub -all {^(.{1,14}).*([#>])$} $reprompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt
+ expect {
+ -re $reprompt {}
+ -re "\[\n\r]+" { exp_continue }
+ }
+ } else {
+ regsub -all "\[)(]" $prompt {\\&} reprompt
+ }
+
+ # this is the only way i see to get rid of more prompts in o/p..grrrrr
+ log_user 0
+
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ # the pager can not be turned off on the PIX, so we have to look
+ # for the "More" prompt. the extreme is equally obnoxious, with a
+ # global switch in the config.
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
+ expect {
+ -re "\b+" { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
+ }
+ -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
+ exp_continue }
+ -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
+ exp_continue }
+ -re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
+ send " "
+ # bloody ^[[2K after " "
+ expect {
+ -re "^\[^\r\n]*\r" {}
+ }
+ exp_continue
+ }
+ -re "^ *--More--\[^\n\r]*" {
+ send " "
+ exp_continue }
+ -re "^<-+ More -+>\[^\n\r]*" {
+ send_user -- "$expect_out(buffer)"
+ send " "
+ exp_continue }
+ }
+ }
+ log_user 1
+
+ if { [ string compare "extreme" "$platform" ] } {
+ send "exit\r"
+ } else {
+ send "quit\r"
+ }
+ expect {
+ -re "^\[^\n\r *]*$reprompt" {
+ # the Cisco CE and Jnx ERX
+ # return to non-enabled mode
+ # on exit in enabled mode.
+ send "exit\r"
+ exp_continue;
+ }
+ "Do you wish to save your configuration changes" {
+ send "n\r"
+ exp_continue
+ }
+ -re "\[\n\r]+" { exp_continue }
+ timeout { close; return 0 }
+ eof { return 0 }
+ }
+ set in_proc 0
+}
+
+#
+# For each router... (this is main loop)
+#
+source_password_file $password_file
+set in_proc 0
+foreach router [lrange $argv $i end] {
+ set router [string tolower $router]
+ send_user "$router\n"
+
+ # Figure out prompt.
+ # Since autoenable is off by default, if we have it defined, it
+ # was done on the command line. If it is not specifically set on the
+ # command line, check the password file.
+ if $avautoenable {
+ set autoenable 1
+ set enable 0
+ set prompt "(#| \\(enable\\))"
+ } else {
+ set ae [find autoenable $router]
+ if { "$ae" == "1" } {
+ set autoenable 1
+ set enable 0
+ set prompt "(#| \\(enable\\))"
+ } else {
+ set autoenable 0
+ set enable $avenable
+ set prompt ">"
+ }
+ }
+
+ # look for noenable option in .cloginrc
+ if { [find noenable $router] != "" } {
+ set enable 0
+ }
+
+ # is OTP in use? If so, bypass password checks
+ set otpinuse 0
+ if { [find otp_secret $router] != "" } {
+ set otpinuse 1
+ }
+
+ # Figure out passwords
+ if { $do_passwd || $do_enapasswd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 && !$otpinuse} {
+ send_user "\nError: no password for $router in $password_file.\n"
+ continue
+ }
+ if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 && !$otpinuse } {
+ send_user "\nError: no enable password for $router in $password_file.\n"
+ continue
+ }
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
+ }
+
+ # Figure out username
+ if {[info exists username]} {
+ # command line username
+ set ruser $username
+ } else {
+ set ruser [join [find user $router] ""]
+ if { "$ruser" == "" } { set ruser $default_user }
+ }
+
+ # Figure out username's password (if different from the vty password)
+ if {[info exists userpasswd]} {
+ # command line username
+ set userpswd $userpasswd
+ } else {
+ set userpswd [join [find userpassword $router] ""]
+ if { "$userpswd" == "" } { set userpswd $passwd }
+ }
+
+ # Figure out enable username
+ if {[info exists enausername]} {
+ # command line enausername
+ set enauser $enausername
+ } else {
+ set enauser [join [find enauser $router] ""]
+ if { "$enauser" == "" } { set enauser $ruser }
+ }
+
+ # Figure out prompts
+ set u_prompt [find userprompt $router]
+ if { "$u_prompt" == "" } {
+ set u_prompt "(Username|Login|login|user name|name):"
+ } else {
+ set u_prompt [join [lindex $u_prompt 0] ""]
+ }
+ set p_prompt [find passprompt $router]
+ if { "$p_prompt" == "" } {
+ set p_prompt "(\[Pp]assword|passwd):"
+ } else {
+ set p_prompt [join [lindex $p_prompt 0] ""]
+ }
+ set e_prompt [find enableprompt $router]
+ if { "$e_prompt" == "" } {
+ set e_prompt "\[Pp]assword:"
+ } else {
+ set e_prompt [join [lindex $e_prompt 0] ""]
+ }
+
+ # Figure out cypher type
+ if {[info exists cypher]} {
+ # command line cypher type
+ set cyphertype $cypher
+ } else {
+ set cyphertype [find cyphertype $router]
+ if { "$cyphertype" == "" } { set cyphertype "3des" }
+ }
+
+ # Figure out connection method
+ set cmethod [find method $router]
+ if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} }
+
+ # Figure out the SSH executable name
+ set sshcmd [find sshcmd $router]
+ if { "$sshcmd" == "" } { set sshcmd {ssh} }
+
+ # If user provides a router-specific connection method, use it
+ set usercmd [find usercmd $router]
+ set usercmd_chat [find usercmd_chat $router]
+
+ # Login to the router
+ if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype]} {
+ continue
+ }
+ if { $enable } {
+ if {[do_enable $enauser $enapasswd]} {
+ if { $do_command || $do_script } {
+ close; wait
+ continue
+ }
+ }
+ }
+ # we are logged in, now figure out the full prompt
+ send "\r"
+ expect {
+ -re "\[\r\n]+" { exp_continue; }
+ -re "^(.+:)1 $prompt" { # stoopid extreme cmd-line numbers and
+ # prompt based on state of config changes,
+ # which may have an * at the beginning.
+ set junk $expect_out(1,string)
+ regsub -all "^\\\* " $expect_out(1,string) {} junk
+ set prompt ".? ?$junk\[0-9]+ $expect_out(2,string)";
+ set platform "extreme"
+ }
+ -re "^.+$prompt" { set junk $expect_out(0,string);
+ regsub -all "\[\]\[]" $junk {\\&} prompt;
+ }
+ -re "^.+> \\\(enable\\\)" {
+ set junk $expect_out(0,string);
+ regsub -all "\[\]\[]" $junk {\\&} prompt;
+ }
+ }
+
+ if { $do_command } {
+ if {[run_commands $prompt $command]} {
+ continue
+ }
+ } elseif { $do_script } {
+ # If the prompt is (enable), then we are on a switch and the
+ # command is "set length 0"; otherwise its "term length 0".
+ if [ regexp -- ".*> .*enable" "$prompt" ] {
+ send "set length 0\r"
+ send "set logging session disable\r"
+ } elseif { ![ string compare "netopia" "$platform" ] } {
+ # do nothing
+ } else {
+ send "term length 0\r"
+ }
+ expect -re $prompt {}
+ source $sfile
+ close
+ } else {
+ label $router
+ log_user 1
+ interact
+ }
+
+ # End of for each router
+ wait
+ sleep 0.3
+}
+exit 0
diff --git a/bin/tntlogin.in b/bin/tntlogin.in
index 16a742e..8a265b3 100644
--- a/bin/tntlogin.in
+++ b/bin/tntlogin.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -381,16 +381,16 @@ proc login { router user userpswd passwd prompt cmethod cyphertype } {
return 1 }
-re "$u_prompt" {
- send "$user\r"
+ send -- "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
- send "$userpswd\r"
+ send -- "$userpswd\r"
} else {
- send "$passwd\r"
+ send -- "$passwd\r"
}
exp_continue
}
@@ -420,25 +420,14 @@ proc run_commands { prompt command } {
expect -re $prompt {}
regsub -all "\[)(]" $prompt {\\&} reprompt
- # Is this a multi-command?
- if [ string match "*\;*" "$command" ] {
- set commands [split $command \;]
- set num_commands [llength $commands]
- for {set i 0} {$i < $num_commands} { incr i} {
- send "[subst -nocommands [lindex $commands $i]]\r"
- expect {
- -re "^\[^\n\r]*$reprompt" {}
- -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue }
- -re "\[\n\r]+" { exp_continue }
- }
- }
- } else {
- send "[subst -nocommands $command]\r"
- send "y\r"
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send -- "[subst -nocommands [lindex $commands $i]]\r"
expect {
- -re "^\[^\n\r]*$reprompt" {}
- -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue }
- -re "\[\n\r]+" { exp_continue }
+ -re "^\[^\n\r]*$reprompt" {}
+ -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue }
+ -re "\[\n\r]+" { exp_continue }
}
}
diff --git a/bin/tntrancid.in b/bin/tntrancid.in
index 748f532..19cba57 100644
--- a/bin/tntrancid.in
+++ b/bin/tntrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
diff --git a/bin/trancid.in b/bin/trancid.in
new file mode 100644
index 0000000..0e4f7fd
--- /dev/null
+++ b/bin/trancid.in
@@ -0,0 +1,300 @@
+#! @PERLV_PATH@
+##
+## $Id$
+##
+## Copyright (C) 1997-2004 by Terrapin Communications, Inc.
+## All rights reserved.
+##
+## This software may be freely copied, modified and redistributed
+## without fee for non-commerical purposes provided that this license
+## remains intact and unmodified with any RANCID distribution.
+##
+## There is no warranty or other guarantee of fitness of this software.
+## It is provided solely "as is". The author(s) disclaim(s) all
+## responsibility and liability with respect to this software's usage
+## or its effect upon hardware, computer systems, other software, or
+## anything else.
+##
+## Except where noted otherwise, rancid was written by and is maintained by
+## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
+##
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+# Modified by Ed Ravin for Netopia.
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$found_version = 0;
+$found_env = 0;
+$found_diag = 0;
+$timeo = 90; # clogin timeout in seconds
+$clogin_pgm= $ENV{'RANCID_CLOGIN'} || "tlogin";
+
+my(%filter_pwds); # password filtering mode
+
+# This routine is used to print out the router configuration
+sub ProcessHistory {
+ my($new_hist_tag,$new_command,$command_string,@string)=(@_);
+ if((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
+ && defined %history) {
+ print eval "$command \%history";
+ undef %history;
+ }
+ if (($new_hist_tag) && ($new_command) && ($command_string)) {
+ if ($history{$command_string}) {
+ $history{$command_string} = "$history{$command_string}@string";
+ } else {
+ $history{$command_string} = "@string";
+ }
+ } elsif (($new_hist_tag) && ($new_command)) {
+ $history{++$#history} = "@string";
+ } else {
+ print "@string";
+ }
+ $hist_tag = $new_hist_tag;
+ $command = $new_command;
+ 1;
+}
+
+sub numerically { $a <=> $b; }
+
+# This is a sort routing that will sort numerically on the
+# keys of a hash as if it were a normal array.
+sub keynsort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort numerically keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routing that will sort on the
+# keys of a hash as if it were a normal array.
+sub keysort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routing that will sort on the
+# values of a hash as if it were a normal array.
+sub valsort{
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort values %lines) {
+ $sorted_lines[$i] = $key;
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a numerical sort routing (ascending).
+sub numsort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $num (sort {$a <=> $b} keys %lines) {
+ $sorted_lines[$i] = $lines{$num};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# ip address when the ip address is anywhere in
+# the strings.
+sub ipsort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $addr (sort sortbyipaddr keys %lines) {
+ $sorted_lines[$i] = $lines{$addr};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# These two routines will sort based upon IP addresses
+sub ipaddrval {
+ my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
+ $a[3]+256*($a[2]+256*($a[1]+256*$a[0]));
+}
+sub sortbyipaddr {
+ &ipaddrval($a) <=> &ipaddrval($b);
+}
+
+# This routine parses "show version"
+sub ShowVersion {
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { $found_version=1; last};
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+ return(0) if ($found_version); # Only do this routine once
+
+ # no pagers in Netopia-land, but shouldn't hurt
+ s/^<-+ More -+>\s*//;
+
+### sample output:
+### #show version
+### cli version: 01.00d00
+### firmware version: 05.03.09f06
+### hardware version: 01.00f00
+### mib version: 01.00f00
+### html version: 01.01d07
+
+ ProcessHistory("COMMENTS","keysort","A1","# $_");
+ }
+
+ return(0);
+}
+
+sub ShowConfig {
+ print STDERR " In ShowConfig: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ if (/^$prompt/) { $found_end=1; $clean_run=1; return 0};
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+
+ # no pagers in Netopia-land, but shouldn't hurt
+ s/^<-+ More -+>\s*//;
+
+ # no post-processing needed - just file it
+ ProcessHistory("","","","$_");
+ }
+}
+
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+@commandtable=(
+ {'show version' => "ShowVersion"},
+ {'show config' => "ShowConfig"},
+);
+
+# Use array to preserve order of commands, and hash for mapping to subroutine
+my (%commands, @commands);
+foreach (@commandtable) {
+ push @commands, (keys(%{$_}))[0];
+ $commands{$commands[$#commands]}= (values(%{$_}))[0];
+};
+
+$cisco_cmds=join(";",@commands);
+$cmds_regexp=join("|",@commands);
+
+open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
+select(OUTPUT);
+# make OUTPUT unbuffered if debugging
+if ($debug) { $| = 1; }
+
+if ($file) {
+ print STDERR "opening file $host\n" if ($debug);
+ print STDOUT "opening file $host\n" if ($log);
+ open(INPUT,"<$host") || die "open failed for $host: $!\n";
+} else {
+ print STDERR "executing $clogin_pgm -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing $clogin_pgm -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "$clogin_pgm -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "$clogin_pgm failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "$clogin_pgm failed for $host: $!\n";
+ } else {
+ open(INPUT,"$clogin_pgm -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "$clogin_pgm failed for $host: $!\n";
+ }
+}
+
+# determine password filtering mode
+if ($ENV{"FILTER_PWDS"} =~ /no/i) {
+ $filter_pwds = 0;
+} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
+ $filter_pwds = 2;
+} else {
+ $filter_pwds = 1;
+}
+
+ProcessHistory("","","","#RANCID-CONTENT-TYPE: netopia\n#\n");
+ProcessHistory("COMMENTS","keysort","B0","#\n");
+ProcessHistory("COMMENTS","keysort","D0","#\n");
+ProcessHistory("COMMENTS","keysort","F0","#\n");
+ProcessHistory("COMMENTS","keysort","G0","#\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/[>#]\s?exit$/) {
+ $clean_run=1;
+ last;
+ }
+ if (/^Error:/) {
+ print STDOUT ("$host $clogin_pgm error: $_");
+ print STDERR ("$host $clogin_pgm error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = "#"; # crude but effective
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
+ }
+ print STDERR ("HIT COMMAND:$_") if ($debug);
+ if (! defined($commands{$cmd})) {
+ print STDERR "$host: found unexpected command - \"$cmd\"\n";
+ $clean_run = 0;
+ last TOP;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -1) {
+ $clean_run = 0;
+ last TOP;
+ }
+ }
+}
+print STDOUT "Done $logincmd: $_\n" if ($log);
+# Flush History
+ProcessHistory("","","","");
+# Cleanup
+close(INPUT);
+close(OUTPUT);
+
+if (defined($ENV{NOPIPE})) {
+ unlink("$host.raw") if (! $debug);
+}
+
+# check for completeness
+if (scalar(%commands) || !$clean_run || !$found_end) {
+ if (scalar(%commands)) {
+ printf(STDOUT "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
+ printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
+ }
+ if (!$clean_run || !$found_end) {
+ print STDOUT "$host: End of run not found\n";
+ print STDERR "$host: End of run not found\n" if ($debug);
+ system("/usr/bin/tail -1 $host.new");
+ }
+ unlink "$host.new" if (! $debug);
+}
diff --git a/bin/xrancid.in b/bin/xrancid.in
index 130bf06..fdda169 100644
--- a/bin/xrancid.in
+++ b/bin/xrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by
@@ -402,6 +402,7 @@ sub WriteTerm {
$found_end = 0;
return(-1);
}
+ $found_end = 1;
return(0);
}
@@ -424,8 +425,8 @@ sub DoNothing {print STDOUT;}
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);
-$cisco_cmds=join(";",@commands);
-$cmds_regexp=join("|",@commands);
+$cisco_cmds = join(";",@commands);
+$cmds_regexp = join("|",@commands);
if (length($host) == 0) {
if ($file) {
@@ -490,13 +491,13 @@ TOP: while(<INPUT>) {
# unreliable about echoing the 'exit\n' command. this match might really
# be a bad idea, but instead rely upon WriteTerm's found_end?
if (/$prompt\s?(quit|exit|Connection( to \S+)? closed)/ && $found_end) {
- $clean_run=1;
+ $clean_run = 1;
last;
}
if (/^Error:/) {
print STDOUT ("$host clogin error: $_");
print STDERR ("$host clogin error: $_") if ($debug);
- $clean_run=0;
+ $clean_run = 0;
last;
}
while (/$prompt\s*($cmds_regexp)\s*$/) {
diff --git a/bin/zrancid.in b/bin/zrancid.in
index 197c323..e26dda0 100755
--- a/bin/zrancid.in
+++ b/bin/zrancid.in
@@ -3,7 +3,7 @@
## $Id$
##
## @PACKAGE@ @VERSION@
-## Copyright (c) 1997-2007 by Terrapin Communications, Inc.
+## Copyright (c) 1997-2008 by Terrapin Communications, Inc.
## All rights reserved.
##
## This code is derived from software contributed to and maintained by