summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorTar Committer <tar@ocjtech.us>2004-01-12 03:17:26 +0000
committerTar Committer <tar@ocjtech.us>2004-01-12 03:17:26 +0000
commit989312339ea2e16579803a48700628c5469e327a (patch)
tree967ee77195819d70f2dc675444e92340bb98e0d6 /bin
parentff168ecfe045c690c24d5bbc5a3062bf9d64120c (diff)
downloadrancid-989312339ea2e16579803a48700628c5469e327a.tar.gz
rancid-989312339ea2e16579803a48700628c5469e327a.tar.xz
rancid-989312339ea2e16579803a48700628c5469e327a.zip
Imported from rancid-2.3.rc1.tar.gz.rancid-2.3.rc1
Diffstat (limited to 'bin')
-rw-r--r--bin/Makefile.am103
-rw-r--r--bin/Makefile.in746
-rw-r--r--bin/alogin.in84
-rw-r--r--bin/arancid.in25
-rw-r--r--bin/blogin.in85
-rw-r--r--bin/brancid.in20
-rw-r--r--[-rwxr-xr-x]bin/cat5rancid.in31
-rw-r--r--[-rwxr-xr-x]bin/clogin.in156
-rw-r--r--[-rwxr-xr-x]bin/control_rancid.in79
-rw-r--r--bin/cssrancid.in660
-rw-r--r--[-rwxr-xr-x]bin/elogin.in44
-rw-r--r--bin/env.in48
-rw-r--r--[-rwxr-xr-x]bin/erancid.in23
-rw-r--r--[-rwxr-xr-x]bin/f10rancid.in31
-rw-r--r--[-rwxr-xr-x]bin/flogin.in95
-rw-r--r--bin/fnrancid.in275
-rw-r--r--[-rwxr-xr-x]bin/francid.in25
-rw-r--r--[-rwxr-xr-x]bin/hlogin.in92
-rw-r--r--bin/hpuifilter.c (renamed from bin/hpfilter.c)29
-rw-r--r--[-rwxr-xr-x]bin/hrancid.in32
-rw-r--r--bin/htlogin.in492
-rw-r--r--bin/htrancid.in266
-rw-r--r--bin/jerancid.in645
-rw-r--r--[-rwxr-xr-x]bin/jlogin.in50
-rw-r--r--[-rwxr-xr-x]bin/jrancid.in102
-rw-r--r--bin/lg.cgi.in867
-rw-r--r--bin/lgform.cgi.in259
-rw-r--r--[-rwxr-xr-x]bin/mrancid.in30
-rw-r--r--bin/nlogin.in524
-rw-r--r--bin/nrancid.in302
-rw-r--r--bin/nslogin.in642
-rw-r--r--bin/nsrancid.in313
-rw-r--r--[-rwxr-xr-x]bin/par.in17
-rwxr-xr-xbin/prancid.in569
-rw-r--r--[-rwxr-xr-x]bin/rancid-cvs.in (renamed from bin/create_cvs.in)27
-rw-r--r--[-rwxr-xr-x]bin/rancid-fe.in51
-rw-r--r--[-rwxr-xr-x]bin/rancid-run.in (renamed from bin/do-diffs.in)36
-rw-r--r--[-rwxr-xr-x]bin/rancid.in445
-rwxr-xr-xbin/rename.in113
-rw-r--r--bin/rivlogin.in1005
-rw-r--r--bin/rivrancid.in344
-rw-r--r--[-rwxr-xr-x]bin/rrancid.in23
-rw-r--r--bin/tntlogin.in528
-rw-r--r--bin/tntrancid.in292
-rw-r--r--[-rwxr-xr-x]bin/xrancid.in64
-rwxr-xr-xbin/zrancid.in411
46 files changed, 10117 insertions, 983 deletions
diff --git a/bin/Makefile.am b/bin/Makefile.am
index 67c8966..21fac52 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -1,26 +1,46 @@
## Process this file with automake to produce Makefile.in
## A Makefile.in is supplied, in case you do not have automake.
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## $Id: Makefile.am,v 1.28 2004/01/11 07:15:23 hank Exp $
+##
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
+##
#AUTOMAKE_OPTIONS=foreign no-dependencies
AUTOMAKE_OPTIONS=foreign
-PREFIX = @prefix@
+bin_PROGRAMS = hpuifilter
+bin_SCRIPTS = cat5rancid control_rancid \
+ alogin arancid clogin blogin brancid cssrancid \
+ elogin erancid f10rancid flogin francid fnrancid \
+ jlogin jrancid jerancid \
+ hlogin hrancid htlogin htrancid \
+ mrancid nlogin nrancid nslogin nsrancid par prancid \
+ rancid rancid-fe rivlogin rivrancid rrancid \
+ tntlogin tntrancid 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
+#dist_bin_SCRIPTS= $(bin_SCRIPTS:%=%.in)
+
+CLEANFILES= lg.cgi lgform.cgi rancid-cvs rancid-run
+#CLEANFILES= $(bin_SCRIPTS)
-bin_PROGRAMS = hpfilter
-hpfilter_SOURCES = hpfilter.c
+hpuifilter_SOURCES = hpuifilter.c
#CPPFLAGS += @PG_CPPFLAGS@
#INCLUDES += -I$(top_srcdir)/include @PG_CPPFLAGS@
@@ -35,35 +55,46 @@ YFLAGS = -d
# no idea why automake doesnt clean these targets
#CLEANFILES= y.tab.c y.tab.h lex.yy.c conf.h conf.c conflex.c
-BIN_PROGS=@RD_BIN_PROGS@
-BIN_DATAS=@RD_BIN_DATAS@
-
-install: all
- for prog in $(BIN_PROGS) ; do \
- $(INSTALL) $$prog $(bindir); \
- done; \
- if test -f $(bindir)/env ; then \
- echo "WARNING: *** $(bindir)/env exists: installing as env.new."; \
- echo " *** review env.new for new/deprecated switches"; \
- $(INSTALL_DATA) env $(bindir)/env.new; \
- else \
- $(INSTALL_DATA) env $(bindir); \
- fi
-# BIN_DATAS are empty at the moment.
-# for prog in $(BIN_DATAS) ; do \
-# $(INSTALL_DATA) $$prog $(PREFIX)/bin; \
-# done; \
-
#clean:
# rm -f Makefile env $(BIN_DATAS) $(BIN_PROGS)
-#distclean: clean
-# rm -f config.log config.status
+# auto_edit does the autoconf variable substitution. This allows the
+# substitution to have the full expansion of the variables, e.g.: $sysconfdir
+# will be /prefix/etc instead of ${prefix}/etc.
+#
+# This is a bit of a PITA, but is the method recommended by the autoconf
+# documentation.
+auto_edit = sed \
+ -e 's,@prefix\@,$(prefix),g' \
+ -e 's,@localstatedir\@,$(localstatedir),g' \
+ -e 's,@sysconfdir\@,$(sysconfdir),g' \
+ -e 's,@EXPECT_PATH\@,$(EXPECT_PATH),g' \
+ -e 's,@PERLV\@,$(PERLV),g' \
+ -e 's,@PERLV_PATH\@,$(PERLV_PATH),g' \
+ -e 's,@LG_PING_CMD\@,$(LG_PING_CMD),g' \
+ -e 's,@ADMINMAILPLUS\@,$(ADMINMAILPLUS),g' \
+ -e 's,@MAILPLUS\@,$(MAILPLUS),g'
+
+lg.cgi: Makefile $(srcdir)/lg.cgi.in
+ rm -f lg.cgi lg.cgi.tmp; \
+ $(auto_edit) $(srcdir)/lg.cgi.in >lg.cgi.tmp; \
+ chmod +x lg.cgi.tmp; \
+ mv lg.cgi.tmp lg.cgi
+
+lgform.cgi: Makefile $(srcdir)/lgform.cgi.in
+ rm -f lgform.cgi lgform.cgi.tmp; \
+ $(auto_edit) $(srcdir)/lgform.cgi.in >lgform.cgi.tmp; \
+ chmod +x lgform.cgi.tmp; \
+ mv lgform.cgi.tmp lgform.cgi
+
+rancid-cvs: Makefile $(srcdir)/rancid-cvs.in
+ rm -f rancid-cvs rancid-cvs.tmp; \
+ $(auto_edit) $(srcdir)/rancid-cvs.in >rancid-cvs.tmp; \
+ chmod +x rancid-cvs.tmp; \
+ mv rancid-cvs.tmp rancid-cvs
-#distdir:
-# for file in Makefile.in configure.in env.in $(BIN_DATAS:=.in) ; do \
-# $(INSTALL_DATA) $$file $(distdir); \
-# done
-# for file in configure $(BIN_PROGS:=.in) ; do \
-# $(INSTALL) $$file $(distdir); \
-# done
+rancid-run: Makefile $(srcdir)/rancid-run.in
+ rm -f rancid-run rancid-run.tmp; \
+ $(auto_edit) $(srcdir)/rancid-run.in >rancid-run.tmp; \
+ chmod +x rancid-run.tmp; \
+ mv rancid-run.tmp rancid-run
diff --git a/bin/Makefile.in b/bin/Makefile.in
index ad98aa8..eedc795 100644
--- a/bin/Makefile.in
+++ b/bin/Makefile.in
@@ -1,6 +1,8 @@
-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
+# Makefile.in generated by automake 1.8 from Makefile.am.
+# @configure_input@
-# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# 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.
@@ -10,397 +12,595 @@
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
-#AUTOMAKE_OPTIONS=foreign no-dependencies
+@SET_MAKE@
-SHELL = @SHELL@
+SOURCES = $(hpuifilter_SOURCES)
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DESTDIR =
-
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
-
top_builddir = ..
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
+bin_PROGRAMS = hpuifilter$(EXEEXT)
+subdir = bin
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/alogin.in $(srcdir)/arancid.in $(srcdir)/blogin.in \
+ $(srcdir)/brancid.in $(srcdir)/cat5rancid.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)/htrancid.in $(srcdir)/jerancid.in \
+ $(srcdir)/jlogin.in $(srcdir)/jrancid.in $(srcdir)/mrancid.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)/tntlogin.in \
+ $(srcdir)/tntrancid.in $(srcdir)/xrancid.in \
+ $(srcdir)/zrancid.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/config.h
+CONFIG_CLEAN_FILES = control_rancid par rancid-fe alogin arancid \
+ blogin brancid cat5rancid clogin rancid cssrancid elogin \
+ erancid f10rancid flogin francid fnrancid jlogin jrancid \
+ jerancid hlogin hrancid htlogin htrancid mrancid nlogin \
+ nrancid nslogin nsrancid prancid rivlogin rivrancid rrancid \
+ tntlogin tntrancid xrancid zrancid
+am__installdirs = $(DESTDIR)$(bindir) $(DESTDIR)$(bindir)
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_hpuifilter_OBJECTS = hpuifilter.$(OBJEXT)
+hpuifilter_OBJECTS = $(am_hpuifilter_OBJECTS)
+hpuifilter_LDADD = $(LDADD)
+binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
+SCRIPTS = $(bin_SCRIPTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/hpuifilter.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(hpuifilter_SOURCES)
+DIST_SOURCES = $(hpuifilter_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMINMAILPLUS = @ADMINMAILPLUS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+
+#CPPFLAGS += @PG_CPPFLAGS@
+#INCLUDES += -I$(top_srcdir)/include @PG_CPPFLAGS@
+#INCLUDES += -I$(top_srcdir)/include
+
+#CFLAGS += -g
+CFLAGS = -g -O0
COMM = @COMM@
CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
CVS = @CVS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
DIFF = @DIFF@
DIFF_CMD = @DIFF_CMD@
DIRNAME = @DIRNAME@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
ENV_PATH = @ENV_PATH@
+EXEEXT = @EXEEXT@
EXPECT_PATH = @EXPECT_PATH@
FIND = @FIND@
GREP = @GREP@
ID = @ID@
-INST_PROGS = @INST_PROGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
LG_PING_CMD = @LG_PING_CMD@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
MAILPLUS = @MAILPLUS@
-MAINT = @MAINT@
MAKE = @MAKE@
MAKEINFO = @MAKEINFO@
MKDIR = @MKDIR@
+OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
PERLV = @PERLV@
PERLV_PATH = @PERLV_PATH@
PING_PATH = @PING_PATH@
-RD_BIN_DATAS = @RD_BIN_DATAS@
-RD_BIN_PROGS = @RD_BIN_PROGS@
-RD_UTIL_LG_PROGS = @RD_UTIL_LG_PROGS@
-RD_UTIL_PROGS = @RD_UTIL_PROGS@
RSH = @RSH@
SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
SORT = @SORT@
SSH = @SSH@
+STRIP = @STRIP@
TAR = @TAR@
TELNET = @TELNET@
TOUCH = @TOUCH@
U = @U@
VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build_alias = @build_alias@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+#AUTOMAKE_OPTIONS=foreign no-dependencies
AUTOMAKE_OPTIONS = foreign
-
-PREFIX = @prefix@
-
-bin_PROGRAMS = hpfilter
-hpfilter_SOURCES = hpfilter.c
-
-#CPPFLAGS += @PG_CPPFLAGS@
-#INCLUDES += -I$(top_srcdir)/include @PG_CPPFLAGS@
-#INCLUDES += -I$(top_srcdir)/include
-
-#CFLAGS += -g
-CFLAGS = -g -O0
-
+bin_SCRIPTS = cat5rancid control_rancid \
+ alogin arancid clogin blogin brancid cssrancid \
+ elogin erancid f10rancid flogin francid fnrancid \
+ jlogin jrancid jerancid \
+ hlogin hrancid htlogin htrancid \
+ mrancid nlogin nrancid nslogin nsrancid par prancid \
+ rancid rancid-fe rivlogin rivrancid rrancid \
+ tntlogin tntrancid 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
+#CLEANFILES= $(bin_SCRIPTS)
+hpuifilter_SOURCES = hpuifilter.c
YFLAGS = -d
#LFLAGS = -i
# no idea why automake doesnt clean these targets
#CLEANFILES= y.tab.c y.tab.h lex.yy.c conf.h conf.c conflex.c
-BIN_PROGS = @RD_BIN_PROGS@
-BIN_DATAS = @RD_BIN_DATAS@
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../include/config.h
-CONFIG_CLEAN_FILES = alogin arancid blogin brancid cat5rancid clogin \
-control_rancid create_cvs do-diffs elogin env erancid f10rancid flogin \
-francid jlogin jrancid hlogin hrancid mrancid par rancid-fe rancid \
-rename rrancid xrancid
-PROGRAMS = $(bin_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir) -I../include
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-hpfilter_OBJECTS = hpfilter.o
-hpfilter_LDADD = $(LDADD)
-hpfilter_DEPENDENCIES =
-hpfilter_LDFLAGS =
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON = Makefile.am Makefile.in alogin.in arancid.in blogin.in \
-brancid.in cat5rancid.in clogin.in control_rancid.in create_cvs.in \
-do-diffs.in elogin.in env.in erancid.in f10rancid.in flogin.in \
-francid.in hlogin.in hrancid.in jlogin.in jrancid.in mrancid.in par.in \
-rancid-fe.in rancid.in rename.in rrancid.in xrancid.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+#clean:
+# rm -f Makefile env $(BIN_DATAS) $(BIN_PROGS)
-GZIP_ENV = --best
-SOURCES = $(hpfilter_SOURCES)
-OBJECTS = $(hpfilter_OBJECTS)
+# auto_edit does the autoconf variable substitution. This allows the
+# substitution to have the full expansion of the variables, e.g.: $sysconfdir
+# will be /prefix/etc instead of ${prefix}/etc.
+#
+# This is a bit of a PITA, but is the method recommended by the autoconf
+# documentation.
+auto_edit = sed \
+ -e 's,@prefix\@,$(prefix),g' \
+ -e 's,@localstatedir\@,$(localstatedir),g' \
+ -e 's,@sysconfdir\@,$(sysconfdir),g' \
+ -e 's,@EXPECT_PATH\@,$(EXPECT_PATH),g' \
+ -e 's,@PERLV\@,$(PERLV),g' \
+ -e 's,@PERLV_PATH\@,$(PERLV_PATH),g' \
+ -e 's,@LG_PING_CMD\@,$(LG_PING_CMD),g' \
+ -e 's,@ADMINMAILPLUS\@,$(ADMINMAILPLUS),g' \
+ -e 's,@MAILPLUS\@,$(MAILPLUS),g'
+
+all: all-am
-all: all-redirect
.SUFFIXES:
-.SUFFIXES: .S .c .o .s
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps bin/Makefile
-
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- cd $(top_builddir) \
- && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-alogin: $(top_builddir)/config.status alogin.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-arancid: $(top_builddir)/config.status arancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-blogin: $(top_builddir)/config.status blogin.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-brancid: $(top_builddir)/config.status brancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-cat5rancid: $(top_builddir)/config.status cat5rancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-clogin: $(top_builddir)/config.status clogin.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-control_rancid: $(top_builddir)/config.status control_rancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-create_cvs: $(top_builddir)/config.status create_cvs.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-do-diffs: $(top_builddir)/config.status do-diffs.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-elogin: $(top_builddir)/config.status elogin.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-env: $(top_builddir)/config.status env.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-erancid: $(top_builddir)/config.status erancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-f10rancid: $(top_builddir)/config.status f10rancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-flogin: $(top_builddir)/config.status flogin.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-francid: $(top_builddir)/config.status francid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-jlogin: $(top_builddir)/config.status jlogin.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-jrancid: $(top_builddir)/config.status jrancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-hlogin: $(top_builddir)/config.status hlogin.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-hrancid: $(top_builddir)/config.status hrancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-mrancid: $(top_builddir)/config.status mrancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-par: $(top_builddir)/config.status par.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-rancid-fe: $(top_builddir)/config.status rancid-fe.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-rancid: $(top_builddir)/config.status rancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-rename: $(top_builddir)/config.status rename.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-rrancid: $(top_builddir)/config.status rrancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-xrancid: $(top_builddir)/config.status xrancid.in
- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
-
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+control_rancid: $(top_builddir)/config.status $(srcdir)/control_rancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+par: $(top_builddir)/config.status $(srcdir)/par.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rancid-fe: $(top_builddir)/config.status $(srcdir)/rancid-fe.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+alogin: $(top_builddir)/config.status $(srcdir)/alogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+arancid: $(top_builddir)/config.status $(srcdir)/arancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+blogin: $(top_builddir)/config.status $(srcdir)/blogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+brancid: $(top_builddir)/config.status $(srcdir)/brancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+cat5rancid: $(top_builddir)/config.status $(srcdir)/cat5rancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+clogin: $(top_builddir)/config.status $(srcdir)/clogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rancid: $(top_builddir)/config.status $(srcdir)/rancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+cssrancid: $(top_builddir)/config.status $(srcdir)/cssrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+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)/$@
+f10rancid: $(top_builddir)/config.status $(srcdir)/f10rancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+flogin: $(top_builddir)/config.status $(srcdir)/flogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+francid: $(top_builddir)/config.status $(srcdir)/francid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+fnrancid: $(top_builddir)/config.status $(srcdir)/fnrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+jlogin: $(top_builddir)/config.status $(srcdir)/jlogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+jrancid: $(top_builddir)/config.status $(srcdir)/jrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+jerancid: $(top_builddir)/config.status $(srcdir)/jerancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+hlogin: $(top_builddir)/config.status $(srcdir)/hlogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+hrancid: $(top_builddir)/config.status $(srcdir)/hrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+htlogin: $(top_builddir)/config.status $(srcdir)/htlogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+htrancid: $(top_builddir)/config.status $(srcdir)/htrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+mrancid: $(top_builddir)/config.status $(srcdir)/mrancid.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
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+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)/$@
+prancid: $(top_builddir)/config.status $(srcdir)/prancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rivlogin: $(top_builddir)/config.status $(srcdir)/rivlogin.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rivrancid: $(top_builddir)/config.status $(srcdir)/rivrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+rrancid: $(top_builddir)/config.status $(srcdir)/rrancid.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)/$@
+xrancid: $(top_builddir)/config.status $(srcdir)/xrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+zrancid: $(top_builddir)/config.status $(srcdir)/zrancid.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
- $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(mkdir_p) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
- if test -f $$p; then \
- echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
- $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
- list='$(bin_PROGRAMS)'; for p in $$list; do \
- rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+ rm -f $(DESTDIR)$(bindir)/$$f; \
done
-.c.o:
- $(COMPILE) -c $<
-
-.s.o:
- $(COMPILE) -c $<
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+hpuifilter$(EXEEXT): $(hpuifilter_OBJECTS) $(hpuifilter_DEPENDENCIES)
+ @rm -f hpuifilter$(EXEEXT)
+ $(LINK) $(hpuifilter_LDFLAGS) $(hpuifilter_OBJECTS) $(hpuifilter_LDADD) $(LIBS)
+install-binSCRIPTS: $(bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ $(mkdir_p) $(DESTDIR)$(bindir)
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f $$d$$p; then \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " $(binSCRIPT_INSTALL) $$d$$p $(DESTDIR)$(bindir)/$$f"; \
+ $(binSCRIPT_INSTALL) $$d$$p $(DESTDIR)$(bindir)/$$f; \
+ else :; fi; \
+ done
-.S.o:
- $(COMPILE) -c $<
+uninstall-binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+ rm -f $(DESTDIR)$(bindir)/$$f; \
+ done
mostlyclean-compile:
- -rm -f *.o core *.core
-
-clean-compile:
+ -rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
-maintainer-clean-compile:
-
-hpfilter: $(hpfilter_OBJECTS) $(hpfilter_DEPENDENCIES)
- @rm -f hpfilter
- $(LINK) $(hpfilter_LDFLAGS) $(hpfilter_OBJECTS) $(hpfilter_LDADD) $(LIBS)
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hpuifilter.Po@am__quote@
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ 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; }'`; \
+ mkid -fID $$unique
tags: TAGS
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
+ 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; }'`; \
- test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+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; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
-clean-tags:
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
- -rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = bin
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
- @for file in $(DISTFILES); do \
- d=$(srcdir); \
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
if test -d $$d/$$file; then \
- cp -pr $$d/$$file $(distdir)/$$file; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
fi; \
done
-
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
check-am: all-am
check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am: install-binPROGRAMS
+all-am: Makefile $(PROGRAMS) $(SCRIPTS)
+installdirs:
+ $(mkdir_p) $(DESTDIR)$(bindir) $(DESTDIR)$(bindir)
+install: install-am
install-exec: install-exec-am
-
-install-data-am:
install-data: install-data-am
+uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am: uninstall-binPROGRAMS
-uninstall: uninstall-am
-all-am: Makefile $(PROGRAMS)
-all-redirect: all-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
-installdirs:
- $(mkinstalldirs) $(DESTDIR)$(bindir)
-
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
- -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \
- mostlyclean-tags mostlyclean-generic
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
-mostlyclean: mostlyclean-am
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
-clean-am: clean-binPROGRAMS clean-compile clean-tags clean-generic \
- mostlyclean-am
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
-clean: clean-am
+dvi: dvi-am
-distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \
- distclean-generic clean-am
+dvi-am:
-distclean: distclean-am
+html: html-am
-maintainer-clean-am: maintainer-clean-binPROGRAMS \
- maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-generic distclean-am
- @echo "This command is intended for maintainers to use;"
- @echo "it deletes files that may require special tools to rebuild."
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS install-binSCRIPTS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
-check-am installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
-
-
-install: all
- for prog in $(BIN_PROGS) ; do \
- $(INSTALL) $$prog $(bindir); \
- done; \
- if test -f $(bindir)/env ; then \
- echo "WARNING: *** $(bindir)/env exists: installing as env.new."; \
- echo " *** review env.new for new/deprecated switches"; \
- $(INSTALL_DATA) env $(bindir)/env.new; \
- else \
- $(INSTALL_DATA) env $(bindir); \
- fi
-# BIN_DATAS are empty at the moment.
-# for prog in $(BIN_DATAS) ; do \
-# $(INSTALL_DATA) $$prog $(PREFIX)/bin; \
-# done; \
+mostlyclean: mostlyclean-am
-#clean:
-# rm -f Makefile env $(BIN_DATAS) $(BIN_PROGS)
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
+ uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-binSCRIPTS install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-binPROGRAMS \
+ uninstall-binSCRIPTS uninstall-info-am
+
+
+lg.cgi: Makefile $(srcdir)/lg.cgi.in
+ rm -f lg.cgi lg.cgi.tmp; \
+ $(auto_edit) $(srcdir)/lg.cgi.in >lg.cgi.tmp; \
+ chmod +x lg.cgi.tmp; \
+ mv lg.cgi.tmp lg.cgi
-#distclean: clean
-# rm -f config.log config.status
+lgform.cgi: Makefile $(srcdir)/lgform.cgi.in
+ rm -f lgform.cgi lgform.cgi.tmp; \
+ $(auto_edit) $(srcdir)/lgform.cgi.in >lgform.cgi.tmp; \
+ chmod +x lgform.cgi.tmp; \
+ mv lgform.cgi.tmp lgform.cgi
-#distdir:
-# for file in Makefile.in configure.in env.in $(BIN_DATAS:=.in) ; do \
-# $(INSTALL_DATA) $$file $(distdir); \
-# done
-# for file in configure $(BIN_PROGS:=.in) ; do \
-# $(INSTALL) $$file $(distdir); \
-# done
+rancid-cvs: Makefile $(srcdir)/rancid-cvs.in
+ rm -f rancid-cvs rancid-cvs.tmp; \
+ $(auto_edit) $(srcdir)/rancid-cvs.in >rancid-cvs.tmp; \
+ chmod +x rancid-cvs.tmp; \
+ mv rancid-cvs.tmp rancid-cvs
+rancid-run: Makefile $(srcdir)/rancid-run.in
+ rm -f rancid-run rancid-run.tmp; \
+ $(auto_edit) $(srcdir)/rancid-run.in >rancid-run.tmp; \
+ chmod +x rancid-run.tmp; \
+ mv rancid-run.tmp rancid-run
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/bin/alogin.in b/bin/alogin.in
index 03f12ca..91623fb 100644
--- a/bin/alogin.in
+++ b/bin/alogin.in
@@ -1,21 +1,26 @@
-#!@EXPECT_PATH@ --
+#! @EXPECT_PATH@ --
##
+## $Id: alogin.in,v 1.22 2004/01/11 05:39:15 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
+#
# alogin - Alteon WebOS switch login
#
# afort@choqolat.org is responsible for this particular mess
@@ -39,8 +44,9 @@ set do_command 0
set do_script 0
# The default is to automatically enable
set enable 1
-# The default is that you login non-enabled (tacacs can have you login already enabled)
-set autoenable 0
+# 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
@@ -50,12 +56,14 @@ 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 "Error: could not exec id: $reason\n"
+ send_error "\nError: could not exec id: $reason\n"
exit 1
}
regexp {\(([^)]*)} "$reason" junk default_user
@@ -95,7 +103,7 @@ for {set i 0} {$i < $argc} {incr i} {
incr i
set E$varname $varvalue
} else {
- send_user "Error: invalid format for -E in $arg\n"
+ send_user "\nError: invalid format for -E in $arg\n"
exit 1
}
# Enable Password
@@ -118,7 +126,7 @@ for {set i 0} {$i < $argc} {incr i} {
set sfile [ lindex $argv $i ]
}
if { ! [ file readable $sfile ] } {
- send_user "Error: Can't read $sfile\n"
+ send_user "\nError: Can't read $sfile\n"
exit 1
}
set do_script 1
@@ -160,12 +168,12 @@ for {set i 0} {$i < $argc} {incr i} {
set do_command 1
# Do we enable?
} -noenable {
- # ignore -noenable
+ # ignore -noenable
# Does tacacs automatically enable us?
} -autoenable {
- # ignore -autoenable
+ # ignore -autoenable
} -* {
- send_user "Error: Unknown argument! $arg\n"
+ send_user "\nError: Unknown argument! $arg\n"
send_user $usage
exit 1
} default {
@@ -175,7 +183,7 @@ for {set i 0} {$i < $argc} {incr i} {
}
# Process routers...no routers listed is an error.
if { $i == $argc } {
- send_user "Error: $usage"
+ send_user "\nError: $usage"
}
# Only be quiet if we are running a script (it can log its output
@@ -241,16 +249,16 @@ proc find {var router} {
proc source_password_file { password_file } {
global env
if { ! [file exists $password_file] } {
- send_user "Error: password file ($password_file) does not exist\n"
+ 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 "Error: $password_file must not be world readable/writable\n"
+ send_user "\nError: $password_file must not be world readable/writable\n"
exit 1
}
if [ catch {source $password_file} reason ] {
- send_user "Error: $reason\n"
+ send_user "\nError: $reason\n"
exit 1
}
}
@@ -258,7 +266,7 @@ proc source_password_file { password_file } {
# Log into the router.
proc login { router user userpswd passwd prompt cmethod cyphertype } {
global spawn_id in_proc do_command do_script
- global u_prompt p_prompt
+ global u_prompt p_prompt sshcmd
set in_proc 1
set uprompt_seen 0
@@ -277,17 +285,17 @@ proc login { router user userpswd passwd prompt cmethod cyphertype } {
exit 1
}
} elseif ![string compare $prog "ssh"] {
- if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
- send_user "Error: ssh failed: $reason\n"
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: $sshcmd failed: $reason\n"
exit 1
}
} elseif ![string compare $prog "rsh"] {
if [ catch {spawn rsh -l $user $router} reason ] {
- send_user "Error: rsh failed: $reason\n"
+ send_user "\nError: rsh failed: $reason\n"
exit 1
}
} else {
- puts "ERROR: unknown connection method: $prog"
+ puts "\nError: unknown connection method: $prog"
return 1
}
incr progs -1
@@ -319,17 +327,17 @@ proc login { router user userpswd passwd prompt cmethod cyphertype } {
close; wait
sleep 0.3
expect eof
- send_user "Error: Connection Refused\n"; wait; return 1
- } eof { send_user "Error: Couldn't login\n"; wait; return 1
+ send_user "\nError: Connection Refused\n"; wait; return 1
+ } eof { send_user "\nError: Couldn't login\n"; wait; return 1
} "Unknown host\r\n" {
expect eof
- send_user "Error: Unknown host\n"; wait; return 1
+ send_user "\nError: Unknown host\n"; wait; return 1
} "Host is unreachable" {
expect eof
- send_user "Error: Host Unreachable!\n"; wait; return 1
+ send_user "\nError: Host Unreachable!\n"; wait; return 1
} "No address associated with name" {
expect eof
- send_user "Error: Unknown host\n"; wait; return 1
+ send_user "\nError: Unknown host\n"; wait; return 1
}
-re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
send "yes\r"
@@ -362,10 +370,10 @@ proc login { router user userpswd passwd prompt cmethod cyphertype } {
send "y\r"
exp_continue
}
- "Password incorrect" { send_user "Error: Check your password for $router\n";
+ "Password incorrect" { send_user "\nError: Check your password for $router\n";
catch {close}; wait; return 1 }
-re "$prompt" { break; }
- denied { send_user "Error: Check your passwd for $router\n"
+ denied { send_user "\nError: Check your passwd for $router\n"
catch {close}; wait; return 1
}
"\r\n" { exp_continue; }
@@ -439,10 +447,10 @@ foreach router [lrange $argv $i end] {
if { $do_passwd } {
set pswd [find password $router]
if { [llength $pswd] == 0 } {
- send_user "Error - no password for $router in $password_file.\n"
+ send_user "\nError - no password for $router in $password_file.\n"
continue
}
- set passwd [lindex $pswd 0]
+ set passwd [join [lindex $pswd 0] ""]
}
# Figure out username
@@ -450,7 +458,7 @@ foreach router [lrange $argv $i end] {
# command line username
set ruser $username
} else {
- set ruser [find user $router]
+ set ruser [join [find user $router] ""]
if { "$ruser" == "" } { set ruser $default_user }
}
@@ -459,7 +467,7 @@ foreach router [lrange $argv $i end] {
# command line username
set userpswd $userpasswd
} else {
- set userpswd [find userpassword $router]
+ set userpswd [join [find userpassword $router] ""]
if { "$userpswd" == "" } { set userpswd $passwd }
}
@@ -468,13 +476,13 @@ foreach router [lrange $argv $i end] {
if { "$u_prompt" == "" } {
set u_prompt "(Username|login| Login):"
} else {
- set u_prompt [lindex $u_prompt 0]
+ set u_prompt [join [lindex $u_prompt 0] ""]
}
set p_prompt [find passprompt $router]
if { "$p_prompt" == "" } {
set p_prompt "\[Pp]assword:"
} else {
- set p_prompt [lindex $p_prompt 0]
+ set p_prompt [join [lindex $p_prompt 0] ""]
}
# Figure out cypher type
@@ -490,6 +498,10 @@ foreach router [lrange $argv $i end] {
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 $prompt $cmethod $cyphertype]} {
continue
diff --git a/bin/arancid.in b/bin/arancid.in
index f51a6c3..a2bf1ef 100644
--- a/bin/arancid.in
+++ b/bin/arancid.in
@@ -1,23 +1,26 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
+##
+## $Id: arancid.in,v 1.14 2004/01/11 03:49:13 heas Exp $
##
## Hacked version of rancid for Alteon WebOS switches
## tested with: ad3 v8.1.18
## afort@choqolat.org (andrew fort)
##
-##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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
@@ -27,7 +30,7 @@
# usage: arancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -240,7 +243,11 @@ TOP: while(<INPUT>) {
while (/>>.*$prompt\s*($cmds_regexp)\s*$/) {
$cmd = $1;
- if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; }
+ 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";
diff --git a/bin/blogin.in b/bin/blogin.in
index 23bf97c..92d2e8c 100644
--- a/bin/blogin.in
+++ b/bin/blogin.in
@@ -1,26 +1,33 @@
-#!@EXPECT_PATH@ --
+#! @EXPECT_PATH@ --
##
+## $Id: blogin.in,v 1.22 2004/01/11 05:39:15 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
+#
# blogin - Bay Networks(Nortel) login
#
-# Unlike the Cisco's, there is no enable function on the Bay's.
-# Instead there are seperate User and Manager accounts. A 'system' command
-# exists, which i am told does nothing.
+# Unlike the Cisco's, there is no enable function on the Bay's. Instead
+# there are seperate User and Manager accounts. A 'system' command exists,
+# which I am told does nothing.
+#
+# The "bcc>" prompt changes to "box#", not "bcc#" after the config command.
#
# Usage line
@@ -40,8 +47,9 @@ set do_command 0
set do_script 0
# The default is to automatically enable
set enable 0
-# The default is that you login non-enabled (tacacs can have you login already enabled)
-set autoenable 0
+# 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
@@ -52,6 +60,8 @@ 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 -
@@ -107,7 +117,7 @@ for {set i 0} {$i < $argc} {incr i} {
if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
- send_user "Error: invalid format for -E in $arg\n"
+ send_user "\nError: invalid format for -E in $arg\n"
exit 1
}
# Enable Password
@@ -176,7 +186,7 @@ for {set i 0} {$i < $argc} {incr i} {
set enable 0
# Does tacacs automatically enable us?
} -autoenable {
- set autoenable 1
+ set avautoenable 1
set enable 0
} -* {
send_user "\nError: Unknown argument! $arg\n"
@@ -272,7 +282,7 @@ proc source_password_file { password_file } {
# Log into the router.
proc login { router user userpswd passwd enapasswd prompt cmethod cyphertype } {
global spawn_id in_proc do_command do_script
- global u_prompt p_prompt e_prompt
+ global u_prompt p_prompt e_prompt sshcmd
set in_proc 1
# try each of the connection methods in $cmethod until one is successful
@@ -290,8 +300,8 @@ proc login { router user userpswd passwd enapasswd prompt cmethod cyphertype } {
exit 1
}
} elseif ![string compare $prog "ssh"] {
- if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
- send_user "\nError: ssh failed: $reason\n"
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: $sshcmd failed: $reason\n"
exit 1
}
} elseif ![string compare $prog "rsh"] {
@@ -408,10 +418,13 @@ proc do_enable { enauser enapasswd } {
-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}
- "% Bad passwords" { send_user "\nError: Check your Enable passwd\n"
- return 1
- }
+ denied { 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.
@@ -440,7 +453,7 @@ proc run_commands { prompt command } {
expect {
-re "^\[^\n\r *]*$reprompt" {}
-re "^\[^\n\r]*$reprompt." { exp_continue }
- -re "\[\n\r]" { exp_continue }
+ -re "\[\n\r]+" { exp_continue }
}
}
} else {
@@ -448,7 +461,7 @@ proc run_commands { prompt command } {
expect {
-re "^\[^\n\r *]*$reprompt" {}
-re "^\[^\n\r]*$reprompt." { exp_continue }
- -re "\[\n\r]" { exp_continue }
+ -re "\[\n\r]+" { exp_continue }
}
}
send "logout\r"
@@ -473,7 +486,9 @@ foreach router [lrange $argv $i end] {
# 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 $autoenable {
+ if $avautoenable {
+ set autoenable 1
+ set enable 0
set prompt "#"
} else {
set ae [find autoenable $router]
@@ -496,15 +511,15 @@ foreach router [lrange $argv $i end] {
if { $do_passwd || $do_enapasswd } {
set pswd [find password $router]
if { [llength $pswd] == 0 } {
- send_user "Error - no password for $router in $password_file.\n"
+ send_user "\nError - no password for $router in $password_file.\n"
continue
}
if { $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
- send_user "Error - no enable password for $router in $password_file.\n"
+ send_user "\nError - no enable password for $router in $password_file.\n"
continue
}
- set passwd [lindex $pswd 0]
- set enapasswd [lindex $pswd 1]
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
}
# Figure out username
@@ -512,7 +527,7 @@ foreach router [lrange $argv $i end] {
# command line username
set ruser $username
} else {
- set ruser [find user $router]
+ set ruser [join [find user $router] ""]
if { "$ruser" == "" } { set ruser $default_user }
}
@@ -521,7 +536,7 @@ foreach router [lrange $argv $i end] {
# command line username
set userpswd $userpasswd
} else {
- set userpswd [find userpassword $router]
+ set userpswd [join [find userpassword $router] ""]
if { "$userpswd" == "" } { set userpswd $passwd }
}
@@ -530,7 +545,7 @@ foreach router [lrange $argv $i end] {
# command line enausername
set enauser $enausername
} else {
- set enauser [find enauser $router]
+ set enauser [join [find enauser $router] ""]
if { "$enauser" == "" } { set enauser $ruser }
}
@@ -539,19 +554,19 @@ foreach router [lrange $argv $i end] {
if { "$u_prompt" == "" } {
set u_prompt "(Username|login|user name):"
} else {
- set u_prompt [lindex $u_prompt 0]
+ 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 [lindex $p_prompt 0]
+ 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 [lindex $e_prompt 0]
+ set e_prompt [join [lindex $e_prompt 0] ""]
}
# Figure out cypher type
@@ -567,6 +582,10 @@ foreach router [lrange $argv $i end] {
set cmethod [find method $router]
if { "$cmethod" == "" } { set cmethod {{telnet}} }
+ # 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 $prompt $cmethod $cyphertype]} {
continue
diff --git a/bin/brancid.in b/bin/brancid.in
index 2ea7e3b..c2e602e 100644
--- a/bin/brancid.in
+++ b/bin/brancid.in
@@ -1,20 +1,23 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
+## $Id: brancid.in,v 1.16 2004/01/11 03:49:13 heas Exp $
## hacked version of Hank's rancid - this one tries to deal with Bay's.
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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
@@ -22,7 +25,7 @@
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -246,7 +249,8 @@ TOP: while(<INPUT>) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^>]+>)/)[0];
- $prompt =~ s/([][])/\\$1/g;
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
diff --git a/bin/cat5rancid.in b/bin/cat5rancid.in
index c8219d8..f1214a1 100755..100644
--- a/bin/cat5rancid.in
+++ b/bin/cat5rancid.in
@@ -1,19 +1,22 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
+## $Id: cat5rancid.in,v 1.36 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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
@@ -21,7 +24,7 @@
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -783,7 +786,7 @@ sub ShowPortIfindex {
}
}
-# This routine processes a "write term"
+# This routine processes a "write term {all}"
sub WriteTerm {
print STDERR " In WriteTerm: $_" if ($debug);
@@ -791,7 +794,10 @@ sub WriteTerm {
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
+ last if (/^Unknown host /); # error when write term all
+ # is not supported
next if (/^\.+$/ | /^$/);
+ return(0) if ($found_end);
/Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
# skip the crap
next if (/^This command shows non-default configurations only./i);
@@ -862,6 +868,7 @@ sub WriteTerm {
next;
}
/fair-queue individual-limit/ && next;
+ /^set port security \d+\/\d+ \S+-\S+\-/ && next;
# sort ip explicit-paths.
if (/^ip explicit-path name (\S+)/) {
my($key) = $1;
@@ -995,6 +1002,7 @@ sub DoNothing {print STDOUT;}
'dir sup-microcode:' => "DirSlotN",
'show module' => "ShowModule",
'show port ifindex' => "ShowPortIfindex",
+ 'write term all' => "WriteTerm",
'write term' => "WriteTerm"
);
# keys() doesnt return things in the order entered and the order of the
@@ -1010,6 +1018,7 @@ sub DoNothing {print STDOUT;}
"dir sup-microcode:",
"show module",
"show port ifindex",
+ "write term all",
"write term"
);
$cisco_cmds=join(";",@commands);
@@ -1062,7 +1071,11 @@ TOP: while(<INPUT>) {
}
while (/> \(enable\)\s*($cmds_regexp)\s*$/) {
$cmd = $1;
- if (!defined($prompt)) {$prompt = ($_ =~ /^([^>]+>)/)[0]; }
+ 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";
diff --git a/bin/clogin.in b/bin/clogin.in
index c026699..281d634 100755..100644
--- a/bin/clogin.in
+++ b/bin/clogin.in
@@ -1,21 +1,26 @@
-#!@EXPECT_PATH@ --
+#! @EXPECT_PATH@ --
##
+## $Id: clogin.in,v 1.72 2004/01/11 05:39:15 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
+#
# clogin - Cisco login
#
# Most options are intuitive for logging into a Cisco router.
@@ -43,8 +48,9 @@ set do_command 0
set do_script 0
# The default is to automatically enable
set enable 1
-# The default is that you login non-enabled (tacacs can have you login already enabled)
-set autoenable 0
+# 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
@@ -57,6 +63,8 @@ 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 -
@@ -112,7 +120,7 @@ for {set i 0} {$i < $argc} {incr i} {
if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
- send_user "Error: invalid format for -E in $arg\n"
+ send_user "\nError: invalid format for -E in $arg\n"
exit 1
}
# Enable Password
@@ -184,7 +192,7 @@ for {set i 0} {$i < $argc} {incr i} {
set enable 0
# Does tacacs automatically enable us?
} -autoenable {
- set autoenable 1
+ set avautoenable 1
set enable 0
} -* {
send_user "\nError: Unknown argument! $arg\n"
@@ -280,7 +288,7 @@ proc source_password_file { password_file } {
# 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
+ global prompt u_prompt p_prompt e_prompt sshcmd
set in_proc 1
set uprompt_seen 0
@@ -299,8 +307,8 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
exit 1
}
} elseif ![string compare $prog "ssh"] {
- if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
- send_user "\nError: ssh failed: $reason\n"
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: $sshcmd failed: $reason\n"
exit 1
}
} elseif ![string compare $prog "rsh"] {
@@ -344,24 +352,32 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
# then it will just send the passwd.
# if telnet fails with connection refused, try ssh
expect {
- -re "(Connection refused|Secure connection \[^\n\r]+ refused|Connection closed by)" {
+ -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 Refused ($prog)\n"; return 1
+ send_user "\nError: Connection closed ($prog): $router\n"
+ return 1
}
}
- eof { send_user "\nError: Couldn't login\n"; wait; 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\n"; wait; return 1
+ send_user "\nError: Unknown host $router\n"; wait; return 1
}
"Host is unreachable" {
catch {close};
- send_user "\nError: Host Unreachable!\n"; wait; return 1
+ send_user "\nError: Host Unreachable: $router\n"; wait; return 1
}
"No address associated with name" {
catch {close};
- send_user "\nError: Unknown host\n"; wait; return 1
+ 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"
@@ -387,6 +403,12 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
send_user "\nError: Check your passwd for $router\n"
return 1
}
+ -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
@@ -407,9 +429,9 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
}
exp_continue
}
- "$prompt" { break; }
+ -re "$prompt" { break; }
"Login invalid" {
- send_user "\nError: Invalid login\n";
+ send_user "\nError: Invalid login: $router\n";
catch {close}; wait; return 1
}
}
@@ -431,10 +453,19 @@ proc do_enable { enauser enapasswd } {
-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}
- "% Bad passwords" { send_user "\nError: Check your Enable passwd\n"
- return 1
- }
+ "denied" {
+ # % Access denied - from local auth
+ 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.
@@ -449,16 +480,19 @@ proc run_commands { prompt command } {
# 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.
+ # 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"
} else {
send "term length 0\r"
}
- regsub -all "\[)(]" $prompt {\\&} reprompt
- # match cisco config mode prompts too, but not for catalyst ie: (enable)
- regsub -all "\[#>]$" $reprompt {(\\([^\\r\\n]+\\))?&} reprompt
+ # 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 }
@@ -466,6 +500,7 @@ proc run_commands { prompt command } {
} 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
# Is this a multi-command?
@@ -540,11 +575,18 @@ proc run_commands { prompt command } {
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
}
- "\n" { exp_continue }
+ -re "\[\n\r]+" { exp_continue }
timeout { return 0 }
eof { return 0 }
}
@@ -564,14 +606,16 @@ foreach router [lrange $argv $i end] {
# 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 $autoenable {
- set prompt "#"
+ 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 "#"
+ set prompt "(#| \\(enable\\))"
} else {
set autoenable 0
set prompt ">"
@@ -587,15 +631,15 @@ foreach router [lrange $argv $i end] {
if { $do_passwd || $do_enapasswd } {
set pswd [find password $router]
if { [llength $pswd] == 0 } {
- send_user "Error: no password for $router in $password_file.\n"
+ send_user "\nError: no password for $router in $password_file.\n"
continue
}
if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
- send_user "Error: no enable password for $router in $password_file.\n"
+ send_user "\nError: no enable password for $router in $password_file.\n"
continue
}
- set passwd [lindex $pswd 0]
- set enapasswd [lindex $pswd 1]
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
}
# Figure out username
@@ -603,7 +647,7 @@ foreach router [lrange $argv $i end] {
# command line username
set ruser $username
} else {
- set ruser [find user $router]
+ set ruser [join [find user $router] ""]
if { "$ruser" == "" } { set ruser $default_user }
}
@@ -612,7 +656,7 @@ foreach router [lrange $argv $i end] {
# command line username
set userpswd $userpasswd
} else {
- set userpswd [find userpassword $router]
+ set userpswd [join [find userpassword $router] ""]
if { "$userpswd" == "" } { set userpswd $passwd }
}
@@ -621,7 +665,7 @@ foreach router [lrange $argv $i end] {
# command line enausername
set enauser $enausername
} else {
- set enauser [find enauser $router]
+ set enauser [join [find enauser $router] ""]
if { "$enauser" == "" } { set enauser $ruser }
}
@@ -630,34 +674,38 @@ foreach router [lrange $argv $i end] {
if { "$u_prompt" == "" } {
set u_prompt "(Username|Login|login|user name):"
} else {
- set u_prompt [lindex $u_prompt 0]
+ 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 [lindex $p_prompt 0]
+ 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 [lindex $e_prompt 0]
+ set e_prompt [join [lindex $e_prompt 0] ""]
}
# Figure out cypher type
if {[info exists cypher]} {
- # command line cypher type
- set cyphertype $cypher
+ # command line cypher type
+ set cyphertype $cypher
} else {
- set cyphertype [find cyphertype $router]
- if { "$cyphertype" == "" } { set cyphertype "3des" }
+ 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]} {
continue
@@ -675,16 +723,20 @@ foreach router [lrange $argv $i end] {
expect {
-re "\[\r\n]+" { exp_continue; }
-re "^(.+:)1 $prompt" { # stoopid extreme cmd-line numbers and
- # prompt based on state of config changes
+ # 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]+ $prompt";
+ 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;
+ }
+ -re "^.+> \\\(enable\\\)" {
+ set junk $expect_out(0,string);
+ regsub -all "\[\]\[]" $junk {\\&} prompt;
+ }
}
if { $do_command } {
diff --git a/bin/control_rancid.in b/bin/control_rancid.in
index 42f14ae..f51a21b 100755..100644
--- a/bin/control_rancid.in
+++ b/bin/control_rancid.in
@@ -1,19 +1,22 @@
-#!/bin/sh
+#! /bin/sh
##
+## $Id: control_rancid.in,v 1.61 2004/01/11 05:25:13 hank Exp $
##
-## Copyright (C) 1996-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
# control_rancid $GROUP
@@ -80,6 +83,7 @@ trap 'rm -fr $TMP;' 1 2 15
# the receipient(s) of diffs
mailrcpt=${mailrcpt:-"@MAILPLUS@$GROUP"}; export mailrcpt
+adminmailrcpt=${mailrcpt:-"@ADMINMAILPLUS@$GROUP"}; export adminmailrcpt
# Number of things par should run in parallel.
PAR_COUNT=${PAR_COUNT:-5}
@@ -88,14 +92,14 @@ PAR_COUNT=${PAR_COUNT:-5}
if [ ! -d $DIR ]
then
echo "$DIR does not exist."
- echo "Run bin/create_cvs $GROUP to make all of the needed directories."
+ echo "Run bin/rancid-cvs $GROUP to make all of the needed directories."
(
- echo "To: @MAILPLUS@admin-$GROUP"
+ echo "To: $adminmailrcpt"
echo "Subject: no $GROUP directory"
echo "Precedence: bulk"
echo ""
echo "$DIR does not exist."
- echo "Run bin/create_cvs $GROUP to make all of the needed directories."
+ echo "Run bin/rancid-cvs $GROUP to make all of the needed directories."
) | sendmail -t
exit 1
fi
@@ -116,7 +120,7 @@ rm -f $TMP
if [ ! -f $DIR/router.db ]
then
(
- echo "To: @MAILPLUS@admin-$GROUP"
+ echo "To: $adminmailrcpt"
echo "Subject: no $GROUP/router.db file"
echo "Precedence: bulk"
echo ""
@@ -132,16 +136,17 @@ fi
cd $DIR
trap 'rm -fr routers.db routers.all.new routers.down.new routers.up.new \
routers.mail routers.added routers.deleted $TMP;' 1 2 15
-grep -v '^#' router.db > routers.db
-cut -d: -f1,2 routers.db | sort -u > routers.all.new
+sed -e '/^#/d' -e 's/^ *//' -e 's/ *$//' -e 's/ *: */:/g' router.db |
+ sort -u > routers.db
+cut -d: -f1,2 routers.db > routers.all.new
if [ ! -f routers.all ] ; then touch routers.all; fi
diff routers.all routers.all.new > /dev/null 2>&1; RALL=$?
@PERLV@ -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print $_)
- if ($F[2] !~ /^up$/i);}' routers.db | sort -u > routers.down.new
+ if ($F[2] !~ /^up$/i);}' routers.db > routers.down.new
if [ ! -f routers.down ] ; then touch routers.down; fi
diff routers.down routers.down.new > /dev/null 2>&1; RDOWN=$?
@PERLV@ -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print "$F[0]:$F[1]\n")
- if ($F[2] =~ /^up$/i);}' routers.db | sort -u > routers.up.new
+ if ($F[2] =~ /^up$/i);}' routers.db > routers.up.new
if [ ! -f routers.up ] ; then touch routers.up; fi
diff routers.up routers.up.new > /dev/null 2>&1; RUP=$?
@@ -207,7 +212,7 @@ then
if [ -s routers.mail ] ; then
(
- echo "To: @MAILPLUS@admin-$GROUP"
+ echo "To: $adminmailrcpt"
echo "Subject: changes in $GROUP routers"
echo "Precedence: bulk"
echo ""
@@ -236,9 +241,18 @@ then
cd $DIR
fi
-mv routers.all.new routers.all
-mv routers.down.new routers.down
-mv routers.up.new routers.up
+mv -f routers.all.new routers.all
+if [ $? -ne 0 ]; then
+ echo "Error: could not rename routers.all.new"
+fi
+mv -f routers.down.new routers.down
+if [ $? -ne 0 ]; then
+ echo "Error: could not rename routers.down.new"
+fi
+mv -f routers.up.new routers.up
+if [ $? -ne 0 ]; then
+ echo "Error: could not rename routers.up.new"
+fi
rm -f routers.db
trap 'rm -fr $TMP;' 1 2 15
@@ -290,6 +304,7 @@ cd $DIR/configs
# The number of processes running at any given time can be
# tailored to the specific installation.
+echo ""
echo "Trying to get all of the configs."
par -q -n $PAR_COUNT -c "rancid-fe \{}" $devlistfile
@@ -331,19 +346,27 @@ do
done
echo
-# Make sure that all of the new configs are not empty.
-for config in *.new
-do
- if [ ! -s $config ]
+# Make sure that no empty configs are accepted. Those that are non-empty
+# are renamed from device_name.new -> device_name.
+for router in `cat $devlistfile`
+do
+ OFS=$IFS
+ IFS=':'
+ set $router
+ IFS=$OFS
+ router=$1;
+
+ if [ ! -s $router.new ]
then
- rm -f $config
+ rm -f $router.new
+ else
+ mv $router.new $router
+ if [ $? -ne 0 ]; then
+ echo "Error: could not rename $router.new to $router"
+ fi
fi
done
-# Now that we have the new configs, rename them to their proper
-# name.
-rename 's/.new$//' *.new
-
# This has been different for different machines...
# Diff the directory and then checkin.
trap 'rm -fr $TMP $TMP.diff $DIR/routers.single;' 1 2 15
@@ -387,7 +410,7 @@ fi
if [ -s $DIR/routers.failed ]
then
(
- echo "To: @MAILPLUS@admin-$GROUP"
+ echo "To: $adminmailrcpt"
echo "Subject: config fetcher problems - $GROUP"
echo "Precedence: bulk"
echo ""
diff --git a/bin/cssrancid.in b/bin/cssrancid.in
new file mode 100644
index 0000000..27049df
--- /dev/null
+++ b/bin/cssrancid.in
@@ -0,0 +1,660 @@
+#! @PERLV_PATH@
+##
+## $Id: cssrancid.in,v 1.4 2004/01/11 03:49:13 heas Exp $
+##
+## 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]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # clogin timeout in seconds
+
+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;
+ study;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ return(-1) if (/command authorization failed/i);
+ if (/^Slave in slot (\d+) is running/) {
+ $slave = " Slave:";
+ next;
+ }
+ /^Cisco Secure PIX /i &&
+ ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
+ /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F1",
+ "!Image:$slave Software: $1, $2\n") && next;
+ /^([A-Za-z-0-9_]*) Synced to mainline version: (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F2",
+ "!Image:$slave $1 Synced to mainline version: $2\n") && next;
+ /^Compiled (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F3",
+ "!Image:$slave Compiled: $1\n") && next;
+ /^ROM: (System )?Bootstrap.*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G1",
+ "!ROM Bootstrap: $2\n") && next;
+ if (/^Hardware:\s+(.*), (.* RAM), CPU (.*)$/) {
+ ProcessHistory("COMMENTS","keysort","A1",
+ "!Chassis type: $1 - a PIX\n");
+ ProcessHistory("COMMENTS","keysort","A2",
+ "!CPU: $3\n");
+ ProcessHistory("COMMENTS","keysort","B1", "!Memory: $2\n");
+ }
+ /^Serial Number:\s+(.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","C1", "!$_") && next;
+ /^Activation Key:\s+(.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","C2", "!$_") && next;
+ /^ROM: \d+ Bootstrap .*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G2",
+ "!ROM Image: Bootstrap $1\n!\n") && next;
+ /^ROM: .*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G3","!ROM Image: $1\n") && next;
+ /^BOOTFLASH: .*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G4","!BOOTFLASH: $1\n") && next;
+ /^BOOTLDR: .*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G4","!BOOTLDR: $1\n") && next;
+ /^System image file is "([^\"]*)", booted via (\S*)/ &&
+ ProcessHistory("COMMENTS","keysort","F4","!Image: booted $1\n") &&
+ next;
+ /^System image file is "([^\"]*)"$/ &&
+ ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") && next;
+ if (/(\S+)\s+\((\S+)\)\s+processor.*with (\S+[kK]) bytes/) {
+ my($proc) = $1;
+ my($cpu) = $2;
+ my($mem) = $3;
+ my($device) = "router";
+ $type = "CSS";
+ print STDERR "TYPE = $type\n" if ($debug);
+ ProcessHistory("COMMENTS","keysort","A1",
+ "!Chassis type:$slave $proc - a $type $device\n");
+ ProcessHistory("COMMENTS","keysort","B1",
+ "!Memory:$slave main $mem\n");
+ ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu\n");
+ next;
+ }
+ if (/(\S+) Silicon\s*Switch Processor/) {
+ if (!defined($C0)) {
+ $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");
+ }
+ ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n");
+ $ssp = 1;
+ $sspmem = $1;
+ next;
+ }
+ /^(\d+[kK]) bytes of multibus/ &&
+ ProcessHistory("COMMENTS","keysort","B2",
+ "!Memory: multibus $1\n") && next;
+ /^(\d+[kK]) bytes of non-volatile/ &&
+ ProcessHistory("COMMENTS","keysort","B3",
+ "!Memory: nvram $1\n") && next;
+ /^(\d+[kK]) bytes of flash memory/ &&
+ ProcessHistory("COMMENTS","keysort","B5","!Memory: flash $1\n") &&
+ next;
+ /^(\d+[kK]) bytes of .*flash partition/ &&
+ ProcessHistory("COMMENTS","keysort","B6",
+ "!Memory: flash partition $1\n") && next;
+ /^(\d+[kK]) bytes of Flash internal/ &&
+ ProcessHistory("COMMENTS","keysort","B4",
+ "!Memory: bootflash $1\n") && next;
+ if(/^(\d+[kK]) bytes of (Flash|ATA)?.*PCMCIA .*(slot|disk) ?(\d)/i) {
+ ProcessHistory("COMMENTS","keysort","B7",
+ "!Memory: pcmcia $2 $3$4 $1\n");
+ next;
+ }
+ if(/^WARNING/) {
+ if (!defined($I0)) {
+ $I0=1;
+ ProcessHistory("COMMENTS","keysort","I0","!\n");
+ }
+ ProcessHistory("COMMENTS","keysort","I1","! $_");
+ # The line after the WARNING is what to do about it.
+ $_ = <INPUT>; tr/\015//d;
+ ProcessHistory("COMMENTS","keysort","I1","! $_");
+ }
+ if (/^Configuration register is (.*)$/) {
+ $config_register=$1;
+ next;
+ }
+ }
+ return(0);
+}
+
+
+# Dummy routine to set term length....
+sub TermLength {
+ # Dummy subroutine.. need to set term length differently for CSS
+ # boxes as term length 0 doesnt work correctly. POS.
+ return(0);
+}
+
+# Dummy routine to copy profile...
+sub CopyProfile {
+ ## Because the term length gets changed twice, the stupid
+ ## box will ask you to save or discard changes. This prompt
+ ## of couse breaks the interaction... strangely enough tho
+ ## in a failover environment, only the secondary behaves this
+ ## way.. the primary lets you log out and does not complain.
+ return(0);
+}
+
+
+# This routine parses "show boot"
+sub ShowBoot {
+ # Pick up boot variables if 7000/7200/7500/12000/2900/3500;
+ # otherwise pick up bootflash.
+ 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 (/command authorization failed/i);
+ return(1) if /Ambiguous command/i;
+ # return(1) if /(Invalid input detected|Type help or )/;
+ return(1) if /(Open device \S+ failed|Error opening \S+:)/;
+ next if /CONFGEN variable/;
+ if (!defined($H0)) {
+ $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n");
+ }
+ if ($type !~ /^(12[04]|7)/) {
+ if ($type !~ /^(29|35)00/) {
+ ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_");
+ } else {
+ ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
+ }
+ } elsif (/variable/) {
+ ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
+ }
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
+}
+
+
+# This routine processes a "show run"
+sub ShowRun {
+ print STDERR " In ShowRun: $_" if ($debug);
+ my($lineauto) = 0;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ study;
+ last if(/^$prompt/);
+ 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
+ $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;
+ ## CSS specific....
+ /Generated on/ && next;
+
+ # 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) / && $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;
+ }
+ 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>$2\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;
+ }
+ if (/^((crypto )?isakmp key) \S+ / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed> $'"); next;
+ }
+ # i am told these are plain-text on the PIX
+ if (/^(vpdn username \S+ password)/ && $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","ipsort","$3","$_") && next;
+ # order extended access-lists
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
+ ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
+ ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ &&
+ ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next;
+ # order arp lists
+ /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
+ ProcessHistory("ARP","ipsort","$1","$_") && next;
+ /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
+ ProcessHistory("PACL $1 $3","ipsort","$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 (defined($ENV{'NOCOMMSTR'})) {
+ 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)));
+ } 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 (defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 <removed>$'") && next;
+ } else {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && 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;
+ # 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$/ || /CSS.*#/ || /$prompt/ ) {
+ $found_end = 1;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'term length 65535' => "TermLength",
+ 'copy profile user-profile' => "CopyProfile",
+ 'show version' => "ShowVersion",
+ 'show boot' => "ShowBoot",
+ 'show run' => "ShowRun"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and show run last). pita
+@commands=(
+ "term length 65535",
+ "copy profile user-profile",
+ "show version",
+ "show boot",
+ "show run"
+);
+$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 -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 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-css\n!\n");
+ProcessHistory("COMMENTS","keysort","B0","!\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 error: $_");
+ print STDERR ("$host clogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; }
+ print STDERR ("HIT COMMAND:$_") if ($debug);
+ if (! defined($commands{$cmd})) {
+ print STDERR "$host: found unexpected command - \"$cmd\"\n";
+ # $clean_run = 0;
+ # last TOP;
+ next TOP;
+ } else {
+ $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/elogin.in b/bin/elogin.in
index 1b647fa..651d7fb 100755..100644
--- a/bin/elogin.in
+++ b/bin/elogin.in
@@ -1,19 +1,22 @@
-#!@EXPECT_PATH@ --
+#! @EXPECT_PATH@ --
##
+## $Id: elogin.in,v 1.27 2004/01/11 05:39:15 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
# elogin - ADC EZT3 login
@@ -38,8 +41,9 @@ set do_command 0
set do_script 0
# The default is to automatically enable
set enable 1
-# The default is that you login non-enabled (tacacs can have you login already enabled)
-set autoenable 0
+# 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
@@ -49,6 +53,8 @@ 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 -
@@ -101,7 +107,7 @@ for {set i 0} {$i < $argc} {incr i} {
if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
- send_user "Error: invalid format for -E in $arg\n"
+ send_user "\nError: invalid format for -E in $arg\n"
exit 1
}
# Enable Password
@@ -166,10 +172,10 @@ for {set i 0} {$i < $argc} {incr i} {
set do_command 1
# Do we enable?
} -noenable {
- # ignore -noenable
+ # ignore -noenable
# Does tacacs automatically enable us?
} -autoenable {
- # ignore -autoenable
+ # ignore -autoenable
} -* {
send_user "\nError: Unknown argument! $arg\n"
send_user $usage
@@ -406,17 +412,17 @@ foreach router [lrange $argv $i end] {
# Figure out prompt.
set prompt "Active) > "
- set autoenable 1
- set enable 0
+ set autoenable 1
+ set enable 0
# Figure out passwords
if { $do_passwd } {
set pswd [find password $router]
if { [llength $pswd] == 0 } {
- send_user "Error: no password for $router in $password_file.\n"
+ send_user "\nError: no password for $router in $password_file.\n"
continue
}
- set passwd [lindex $pswd 0]
+ set passwd [join [lindex $pswd 0] ""]
}
# Figure out username
@@ -424,7 +430,7 @@ foreach router [lrange $argv $i end] {
# command line username
set ruser $username
} else {
- set ruser [find user $router]
+ set ruser [join [find user $router] ""]
if { "$ruser" == "" } { set ruser $default_user }
}
@@ -433,7 +439,7 @@ foreach router [lrange $argv $i end] {
# command line username
set userpswd $userpasswd
} else {
- set userpswd [find userpassword $router]
+ set userpswd [join [find userpassword $router] ""]
if { "$userpswd" == "" } { set userpswd $passwd }
}
@@ -442,13 +448,13 @@ foreach router [lrange $argv $i end] {
if { "$u_prompt" == "" } {
set u_prompt "(Username|login| Login):"
} else {
- set u_prompt [lindex $u_prompt 0]
+ set u_prompt [join [lindex $u_prompt 0] ""]
}
set p_prompt [find passprompt $router]
if { "$p_prompt" == "" } {
set p_prompt "\[Pp]assword:"
} else {
- set p_prompt [lindex $p_prompt 0]
+ set p_prompt [join [lindex $p_prompt 0] ""]
}
# Figure out cypher type
diff --git a/bin/env.in b/bin/env.in
deleted file mode 100644
index e3c2ba4..0000000
--- a/bin/env.in
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# This file setups up the environment used for rancid. see env(5)
-#
-# This will be site specific
-#
-TERM=network;export TERM
-#
-# Under $BASEDIR, there will be a bin directory for the rancid programs,
-# a log directory for the logs from rancid and a directory for each group
-# of routers (LIST_OF_GROUPS). In addition to these directories, there
-# will be the CVS repositories as well.
-# use a full path (no sym-links) for BASEDIR. some versions of CVS seemingly
-# don't take kindly to sym-links.
-#
-TMPDIR=/tmp; export TMPDIR
-BASEDIR=@prefix@; export BASEDIR
-PATH=$BASEDIR/bin:@ENV_PATH@; export PATH
-CVSROOT=$BASEDIR/CVS; export CVSROOT
-#
-# if NOPIPE is set, temp files will be used instead of a cmd pipe during
-# collection from the router(s).
-#NOPIPE=YES; export NOPIPE
-#
-# FILTER_PWDS determines which passwords are filtered from configs by the
-# value set (NO | YES | ALL). see env(5).
-#FILTER_PWDS=YES; export FILTER_PWDS
-#
-# if NOCOMMSTR is set, snmp community strings will be stripped from the configs
-#NOCOMMSTR=YES; export NOCOMMSTR
-#
-# How many hours to go by before complaining about routers that
-# can not be reached. The value should be greater than the number
-# of hours between your do-diffs cron job.
-OLDTIME=4; export OLDTIME
-#
-# The number of devices to collect simultaneously.
-#PAR_COUNT=5; export PAR_COUNT
-#
-# list of rancid groups
-LIST_OF_GROUPS="sl joebobisp"
-#
-# For each group, define a list of people to receive the diffs.
-# in sendmail's /etc/aliases.
-# rancid-group: joe,moe@foo
-# rancid-group-admin: hostmaster
-# be sure to read ../README regarding aliases.
-#
-umask 027
diff --git a/bin/erancid.in b/bin/erancid.in
index 01a6268..20da43d 100755..100644
--- a/bin/erancid.in
+++ b/bin/erancid.in
@@ -1,22 +1,22 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
-## Hacked version of rancid for ADC EZT3 series muxes. Only tested
-## with switch software 1.50 so far - terry@tmk.com
+## $Id: erancid.in,v 1.18 2004/01/11 03:49:13 heas Exp $
##
-##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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
@@ -24,7 +24,7 @@
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -268,7 +268,8 @@ while(<INPUT>) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^#]+#)/)[0];
- $prompt =~ s/([}{)(\\])/\\$1/g;
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
diff --git a/bin/f10rancid.in b/bin/f10rancid.in
index 06528c5..2c4e485 100755..100644
--- a/bin/f10rancid.in
+++ b/bin/f10rancid.in
@@ -1,28 +1,32 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
-## This version of rancid tries to deal with Force10s.
+## $Id: f10rancid.in,v 1.11 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
+# This version of rancid tries to deal with Force10s.
+#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -139,7 +143,6 @@ sub ShowVersion {
while (<INPUT>) {
tr/\015//d;
- study;
last if(/^$prompt/);
next if(/^(\s*|\s*$cmd\s*)$/);
return(-1) if (/command authorization failed/i);
@@ -479,7 +482,6 @@ sub ShowContAll {
while (<INPUT>) {
tr/\015//d;
- study;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type =~ /^(12[40]|7[05])/);
@@ -583,7 +585,6 @@ sub ShowDiagbus {
while (<INPUT>) {
tr/\015//d;
- study;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^7[05]/);
@@ -670,7 +671,6 @@ sub ShowDiag {
while (<INPUT>) {
tr/\015//d;
- study;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type !~ /^(12[40]|720|36|26)/);
@@ -882,7 +882,6 @@ sub WriteTerm {
while (<INPUT>) {
tr/\015//d;
- study;
last if(/^$prompt/);
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
@@ -1216,7 +1215,11 @@ TOP: while(<INPUT>) {
}
while (/#\s*($cmds_regexp)\s*$/) {
$cmd = $1;
- if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; }
+ 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";
diff --git a/bin/flogin.in b/bin/flogin.in
index 1a34068..169e522 100755..100644
--- a/bin/flogin.in
+++ b/bin/flogin.in
@@ -1,21 +1,26 @@
-#!@EXPECT_PATH@ --
+#! @EXPECT_PATH@ --
##
+## $Id: flogin.in,v 1.32 2004/01/11 05:39:15 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
-##
+## 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
+## 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.
+#
# flogin - foundry login
#
# Most options are intuitive for logging into a foundry switch.
@@ -46,8 +51,9 @@ set do_command 0
set do_script 0
# The default is to automatically enable
set enable 1
-# The default is that you login non-enabled (tacacs can have you login already enabled)
-set autoenable 0
+# 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
@@ -58,6 +64,8 @@ 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 -
@@ -113,7 +121,7 @@ for {set i 0} {$i < $argc} {incr i} {
if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
- send_user "Error: invalid format for -E in $arg\n"
+ send_user "\nError: invalid format for -E in $arg\n"
exit 1
}
# Enable Password
@@ -181,7 +189,7 @@ for {set i 0} {$i < $argc} {incr i} {
set enable 0
# Does tacacs automatically enable us?
} -autoenable {
- set autoenable 1
+ set avautoenable 1
set enable 0
} -* {
send_user "\nError: Unknown argument! $arg\n"
@@ -277,7 +285,7 @@ proc source_password_file { password_file } {
# 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
+ global prompt u_prompt p_prompt e_prompt sshcmd
set in_proc 1
set uprompt_seen 0
@@ -296,8 +304,8 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
exit 1
}
} elseif ![string compare $prog "ssh"] {
- if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
- send_user "\nError: ssh failed: $reason\n"
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: $sshcmd failed: $reason\n"
exit 1
}
} elseif ![string compare $prog "rsh"] {
@@ -341,24 +349,39 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
# then it will just send the passwd.
# if telnet fails with connection refused, try ssh
expect {
- -re "(Connection refused|Secure connection \[^\n\r]+ refused|Connection closed by|Telnet server disabled)" {
+ -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 Refused ($prog)\n"; return 1
+ send_user "\nError: Connection closed ($prog): $router\n"
+ return 1
+ }
+ }
+ -re "Telnet server disabled" {
+ catch {close}; wait
+ if !$progs {
+ send_user "\nError: Connection Refused ($prog): $router\n"
+ return 1
}
}
eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
-nocase "unknown host\r" {
catch {close};
- send_user "\nError: Unknown host\n"; wait; return 1
+ send_user "\nError: Unknown host $router\n"; wait; return 1
}
"Host is unreachable" {
catch {close};
- send_user "\nError: Host Unreachable!\n"; wait; return 1
+ send_user "\nError: Host Unreachable: $router\n"; wait; return 1
}
"No address associated with name" {
catch {close};
- send_user "\nError: Unknown host\n"; wait; return 1
+ 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"
@@ -406,7 +429,7 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
}
"$prompt" { break; }
"Login invalid" {
- send_user "\nError: Invalid login\n";
+ send_user "\nError: Invalid login: $router\n";
catch {close}; wait; return 1
}
}
@@ -432,6 +455,10 @@ proc do_enable { enauser enapasswd } {
denied { send_user "\nError: Check your Enable passwd\n";
return 1
}
+ "Incorrect username or password" {
+ send_user "\nError: Check your Enable passwd\n";
+ return 1
+ }
"% Bad passwords" { send_user "\nError: Check your Enable passwd\n";
return 1
}
@@ -496,7 +523,9 @@ foreach router [lrange $argv $i end] {
# 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 $autoenable {
+ if $avautoenable {
+ set autoenable 1
+ set enable 0
set prompt "#"
} else {
set ae [find autoenable $router]
@@ -514,15 +543,15 @@ foreach router [lrange $argv $i end] {
if { $do_passwd || $do_enapasswd } {
set pswd [find password $router]
if { [llength $pswd] == 0 } {
- send_user "Error: no password for $router in $password_file.\n"
+ send_user "\nError: no password for $router in $password_file.\n"
continue
}
if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
- send_user "Error: no enable password for $router in $password_file.\n"
+ send_user "\nError: no enable password for $router in $password_file.\n"
continue
}
- set passwd [lindex $pswd 0]
- set enapasswd [lindex $pswd 1]
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
}
# Figure out username
@@ -530,7 +559,7 @@ foreach router [lrange $argv $i end] {
# command line username
set ruser $username
} else {
- set ruser [find user $router]
+ set ruser [join [find user $router] ""]
if { "$ruser" == "" } { set ruser $default_user }
}
@@ -539,7 +568,7 @@ foreach router [lrange $argv $i end] {
# command line username
set userpswd $userpasswd
} else {
- set userpswd [find userpassword $router]
+ set userpswd [join [find userpassword $router] ""]
if { "$userpswd" == "" } { set userpswd $passwd }
}
@@ -548,7 +577,7 @@ foreach router [lrange $argv $i end] {
# command line enausername
set enauser $enausername
} else {
- set enauser [find enauser $router]
+ set enauser [join [find enauser $router] ""]
if { "$enauser" == "" } { set enauser $ruser }
}
@@ -557,19 +586,19 @@ foreach router [lrange $argv $i end] {
if { "$u_prompt" == "" } {
set u_prompt "(Username|login|Name|User Name):"
} else {
- set u_prompt [lindex $u_prompt 0]
+ set u_prompt [join [lindex $u_prompt 0] ""]
}
set p_prompt [find passprompt $router]
if { "$p_prompt" == "" } {
set p_prompt "(\[Pp]assword):"
} else {
- set p_prompt [lindex $p_prompt 0]
+ 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 [lindex $e_prompt 0]
+ set e_prompt [join [lindex $e_prompt 0] ""]
}
# Figure out cypher tpye
@@ -585,6 +614,10 @@ foreach router [lrange $argv $i end] {
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]} {
continue
diff --git a/bin/fnrancid.in b/bin/fnrancid.in
new file mode 100644
index 0000000..815227b
--- /dev/null
+++ b/bin/fnrancid.in
@@ -0,0 +1,275 @@
+#! @PERLV_PATH@
+##
+## $Id: fnrancid.in,v 1.3 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# A library built on Stephen Gill's Netscreen stuff to accomodate
+# the Fortinet product line. [d_pfleger@juniper.net]
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+#$debug = 1;
+$file = $opt_f;
+$host = $ARGV[0];
+$found_end = 0;
+$timeo = 90; # nlogin timeout in seconds
+
+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 "get system"
+sub GetSystem {
+ print STDERR " In GetSystem: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ next if /^\s*$/;
+ last if(/$prompt/);
+ ProcessHistory("","","","$_");
+ #print STDOUT "$_";
+ }
+ print STDOUT "Vendor: $vendor";
+ ProcessHistory("SYSTEM","","","\n");
+ return(0);
+}
+
+sub GetFile {
+ print STDERR " In GetFile: $_" if ($debug);
+ while (<INPUT>) {
+ last if(/$prompt/);
+ }
+ ProcessHistory("FILE","","","\n");
+ return(0);
+}
+
+sub GetConf {
+ print STDERR " In GetConf: $_" if ($debug);
+ while (<INPUT>) {
+ tr/\015//d;
+ next if /^\s*$/;
+ last if(/$prompt/);
+ if (/(^set.*)('Enc .*')(.*)/) {
+ ProcessHistory("ENC","","","!$1 'Enc **encoding removed**' $3\n");
+ next;
+ }
+ ProcessHistory("","","","$_");
+ #print STDOUT "$_";
+ }
+ $found_end=1;
+ return(1);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'get system status' => "GetSystem",
+ 'get conf' => "GetConf"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important. pita
+@commands=(
+ "get system status",
+ "get conf"
+);
+$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 nlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing nlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "nlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "nlogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "nlogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"nlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "nlogin 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: Fortigate\n\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/^Error:/) {
+ print STDOUT ("$host nlogin error: $_");
+ print STDERR ("$host nlogin error: $_") if ($debug);
+ last;
+ }
+ while (/>\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) { $prompt = " >\s*"; }
+ print STDERR ("HIT COMMAND:$_") if ($debug);
+ if (!defined($commands{$cmd})) {
+ print STDERR "$host: found unexpected command - \"$cmd\"\n";
+ last TOP;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -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) || !$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 (!$found_end) {
+ print STDOUT "$found_end: 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");
+ }
+ unlink "$host.new" if (! $debug);
+}
diff --git a/bin/francid.in b/bin/francid.in
index b03052e..e1fd284 100755..100644
--- a/bin/francid.in
+++ b/bin/francid.in
@@ -1,29 +1,33 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
-## Amazingly hacked version of Hank's rancid - this one tries to
-## deal with foundrys and foundrys OEM'd by HP as Procurves.
+## $Id: francid.in,v 1.26 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
+# Amazingly hacked version of Hank's rancid - this one tries to
+# deal with foundrys and foundrys OEM'd by HP as Procurves.
+#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -376,7 +380,8 @@ TOP: while(<INPUT>) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^#]+#)/)[0];
- $prompt =~ s/([}{)(\\])/\\$1/g;
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
diff --git a/bin/hlogin.in b/bin/hlogin.in
index 917ea83..6af11b4 100755..100644
--- a/bin/hlogin.in
+++ b/bin/hlogin.in
@@ -1,21 +1,26 @@
-#!@EXPECT_PATH@ --
+#! @EXPECT_PATH@ --
##
+## $Id: hlogin.in,v 1.21 2004/01/11 05:39:15 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
+#
# hlogin - hp login
#
# Most options are intuitive for logging into a Cisco router.
@@ -43,8 +48,9 @@ set do_command 0
set do_script 0
# The default is to automatically enable
set enable 1
-# The default is that you login non-enabled (tacacs can have you login already enabled)
-set autoenable 0
+# 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
@@ -57,6 +63,8 @@ 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 -
@@ -112,7 +120,7 @@ for {set i 0} {$i < $argc} {incr i} {
if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
- send_user "Error: invalid format for -E in $arg\n"
+ send_user "\nError: invalid format for -E in $arg\n"
exit 1
}
# Enable Password
@@ -281,30 +289,35 @@ proc source_password_file { password_file } {
# 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
+ global prompt u_prompt p_prompt e_prompt sshcmd
set in_proc 1
# try each of the connection methods in $cmethod until one is successful
set progs [llength $cmethod]
foreach prog [lrange $cmethod 0 end] {
+ regexp {(telnet|ssh)(:([^[:space:]]+))*} $prog command suffix junk port
if [string match "telnet*" $prog] {
- regexp {telnet(:([^[:space:]]+))*} $prog command suffix port
if {"$port" == ""} {
- set retval [ catch {spawn hpfilter telnet $router} reason ]
+ set retval [ catch {spawn hpuifilter telnet $router} reason ]
} else {
- set retval [ catch {spawn hpfilter telnet $router $port} reason ]
+ set retval [ catch {spawn hpuifilter telnet $router $port} reason ]
}
if { $retval } {
send_user "\nError: telnet failed: $reason\n"
exit 1
}
- } elseif ![string compare $prog "ssh"] {
- if [ catch {spawn hpfilter ssh -c $cyphertype -x -l $user $router} reason ] {
- send_user "\nError: ssh failed: $reason\n"
+ } elseif [string match "ssh*" $prog] {
+ if {"$port" == ""} {
+ set retval [ catch {spawn hpuifilter $sshcmd -c $cyphertype -x -l $user $router} reason ]
+ } else {
+ set retval [ catch {spawn hpuifilter $sshcmd -c $cyphertype -p $port -x -l $user $router} reason ]
+ }
+ if { $retval } {
+ send_user "\nError: $sshcmd failed: $reason\n"
exit 1
}
} elseif ![string compare $prog "rsh"] {
- if [ catch {spawn hpfilter rsh -l $user $router} reason ] {
+ if [ catch {spawn hpuifilter rsh -l $user $router} reason ] {
send_user "\nError: rsh failed: $reason\n"
exit 1
}
@@ -353,14 +366,17 @@ proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
if !$progs {
send_user "\nError: Connection Refused ($prog)\n"; return 1
}
- } eof { send_user "\nError: Couldn't login\n"; wait; return 1
- } -nocase "unknown host\r" {
+ }
+ eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
+ -nocase "unknown host\r" {
catch {close};
send_user "\nError: Unknown host\n"; wait; return 1
- } "Host is unreachable" {
+ }
+ "Host is unreachable" {
catch {close};
send_user "\nError: Host Unreachable!\n"; wait; return 1
- } "No address associated with name" {
+ }
+ "No address associated with name" {
catch {close};
send_user "\nError: Unknown host\n"; wait; return 1
}
@@ -542,7 +558,9 @@ foreach router [lrange $argv $i end] {
# 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 $autoenable {
+ if $avautoenable {
+ set autoenable 1
+ set enable 0
set prompt "#"
} else {
set ae [find autoenable $router]
@@ -565,15 +583,15 @@ foreach router [lrange $argv $i end] {
if { $do_passwd || $do_enapasswd } {
set pswd [find password $router]
if { [llength $pswd] == 0 } {
- send_user "Error: no password for $router in $password_file.\n"
+ send_user "\nError: no password for $router in $password_file.\n"
continue
}
if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
- send_user "Error: no enable password for $router in $password_file.\n"
+ send_user "\nError: no enable password for $router in $password_file.\n"
continue
}
- set passwd [lindex $pswd 0]
- set enapasswd [lindex $pswd 1]
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
}
# Figure out username
@@ -581,7 +599,7 @@ foreach router [lrange $argv $i end] {
# command line username
set ruser $username
} else {
- set ruser [find user $router]
+ set ruser [join [find user $router] ""]
if { "$ruser" == "" } { set ruser $default_user }
}
@@ -590,7 +608,7 @@ foreach router [lrange $argv $i end] {
# command line username
set userpswd $userpasswd
} else {
- set userpswd [find userpassword $router]
+ set userpswd [join [find userpassword $router] ""]
if { "$userpswd" == "" } { set userpswd $passwd }
}
@@ -599,7 +617,7 @@ foreach router [lrange $argv $i end] {
# command line enausername
set enauser $enausername
} else {
- set enauser [find enauser $router]
+ set enauser [join [find enauser $router] ""]
if { "$enauser" == "" } { set enauser $ruser }
}
@@ -608,19 +626,19 @@ foreach router [lrange $argv $i end] {
if { "$u_prompt" == "" } {
set u_prompt "(Username|login|user name):"
} else {
- set u_prompt [lindex $u_prompt 0]
+ 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 [lindex $p_prompt 0]
+ 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 [lindex $e_prompt 0]
+ set e_prompt [join [lindex $e_prompt 0] ""]
}
# Figure out cypher type
@@ -636,6 +654,16 @@ foreach router [lrange $argv $i end] {
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} }
+
+ # Adjust our path to find hpuifilter
+ regexp {(.*)/[^/]+} $argv0 junk hpf_path
+ if { "$hpf_path" != "" && "$hpf_path" != "." } {
+ append env(PATH) ":$hpf_path"
+ }
+
# Login to the router
if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype]} {
continue
diff --git a/bin/hpfilter.c b/bin/hpuifilter.c
index 83d799e..8f7005a 100644
--- a/bin/hpfilter.c
+++ b/bin/hpuifilter.c
@@ -1,21 +1,26 @@
/*
- * Copyright (C) 1997-2002 by Henry Kilmer, Erik Sherk and Pete Whiting.
+ * $Id: hpuifilter.c,v 1.17 2004/01/11 03:49:13 heas Exp $
+ *
+ * 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 copyright notice is
- * preserved intact on all copies and modified copies.
+ * 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
+ * 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.
*
- * run telnet or ssh to connect to device specified on the command line. the
+ * Run telnet or ssh to connect to device specified on the command line. The
* point of hpfilter is to filter all the bloody vt100 (curses) escape codes
- * that the HP procurve switches belch and make hlogin a real bitch.
+ * that the HP procurve switches belch out, which are a real bitch to handle
+ * in hlogin.
*/
#define DFLT_TO 60 /* default timeout */
@@ -83,7 +88,7 @@ main(int argc, char **argv)
return(EX_USAGE);
}
- if (argc - optind != 2) {
+ if (argc - optind < 2) {
usage();
return(EX_USAGE);
}
@@ -382,16 +387,14 @@ void
usage(void)
{
fprintf(stderr,
-"usage: %s [-hv] <telnet|ssh> <hostname>
-", progname);
+"usage: %s [-hv] <telnet|ssh> [<ssh options>] <hostname> [<telnet_port>]\n",
+ progname);
return;
}
void
vers(void)
{
- fprintf(stderr,
-"%s: %s version %s
-", progname, package, version);
+ fprintf(stderr, "%s: %s version %s\n", progname, package, version);
return;
}
diff --git a/bin/hrancid.in b/bin/hrancid.in
index d0bcc55..fa048ce 100755..100644
--- a/bin/hrancid.in
+++ b/bin/hrancid.in
@@ -1,29 +1,33 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
-## Amazingly hacked version of Hank's rancid - this one tries to
-## deal with HP procurves.
+## $Id: hrancid.in,v 1.17 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
+# Amazingly hacked version of Hank's rancid - this one tries to
+# deal with HP procurves.
+#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -334,7 +338,7 @@ sub WriteTerm {
ProcessHistory("","","",";$_") && next;
- # the rest are from rancid (ie: cisco), but suspect they will someday
+ # the rest are from rancid (i.e.: cisco), but suspect they will someday
# be applicable or close to it.
/^tftp-server flash / && next; # kill any tftp remains
@@ -493,8 +497,12 @@ TOP: while(<INPUT>) {
}
while (/#\s*($cmds_regexp)\s*$/) {
$cmd = $1;
- if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+)/)[0];
- $prompt .= "[#>]"; }
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]+)/)[0];
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ $prompt .= "[#>]";
+ 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";
diff --git a/bin/htlogin.in b/bin/htlogin.in
new file mode 100644
index 0000000..8e9c5f5
--- /dev/null
+++ b/bin/htlogin.in
@@ -0,0 +1,492 @@
+#! @EXPECT_PATH@ --
+##
+## $Id: htlogin.in,v 1.7 2004/01/11 05:39:15 heas Exp $
+##
+## 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.
+##
+#
+# The login expect scripts were based on Erik Sherk's gwtn, by permission.
+#
+# htlogin - Hitachi router login
+#
+# Most options are intuitive for logging into an Hitachi router login.
+#
+
+# Usage line
+set usage "Usage: $argv0 \[-noenable\] \[-c command\] \
+\[-Evar=x\] \[-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 enable 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
+
+# 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* {
+ # ignore -w
+ # Environment variable to pass to -s scripts
+ } -E*
+ {
+ if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ set E$varname $varvalue
+ } else {
+ send_user "Error: invalid format for -E in $arg\n"
+ exit 1
+ }
+ # Enable Password
+ } -e*
+ {
+ # ignore -e
+ # 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 {
+ # ignore -noenable
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ # ignore -autoenable
+ } -* {
+ 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 prompt cmethod cyphertype } {
+ global spawn_id in_proc do_command do_script
+ global u_prompt p_prompt
+ 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
+ }
+ } 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
+ }
+ }
+ }
+
+ expect {
+ "Connection refused" {
+ close; wait
+ sleep 0.3
+ expect eof
+ send_user "\nError: Connection Refused\n"; wait; return 1
+ } eof { send_user "\nError: Couldn't login\n"; wait; return 1
+ } "Unknown host\r\n" {
+ expect eof
+ send_user "\nError: Unknown host\n"; wait; return 1
+ } "Host is unreachable" {
+ expect eof
+ send_user "\nError: Host Unreachable!\n"; wait; return 1
+ } "No address associated with name" {
+ expect eof
+ send_user "\nError: Unknown host\n"; wait; return 1
+ }
+ -re "$u_prompt" {
+ send "$user\r"
+ set uprompt_seen 1
+ exp_continue
+ }
+ -re "$p_prompt" {
+ sleep 1
+ if {$uprompt_seen == 1} {
+ send "$userpswd\r"
+ } else {
+ send "$passwd\r"
+ }
+ exp_continue
+ }
+ "Password incorrect" { send_user "\nError: Check your password for $router\n";
+ catch {close}; wait; return 1
+ }
+ "$prompt" { break; }
+ denied { send_user "\nError: Check your passwd for $router\n"
+ catch {close}; wait; return 1
+ }
+ "\r\n" { exp_continue; }
+ }
+ }
+ 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
+
+ # 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"
+ expect {
+ -re "^\[^\n\r]*$prompt" {}
+ -re "^\[^\n\r *]*$prompt" {}
+ -re "\[\n\r]" { exp_continue }
+ }
+ }
+ send "exit\r"
+ expect {
+ "\n" { exp_continue }
+ timeout { 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.
+ set prompt "command: "
+ set autoenable 1
+ set enable 0
+
+ # Figure out passwords
+ if { $do_passwd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ send_user "Error: no password for $router in $password_file.\n"
+ continue
+ }
+ set passwd [join [lindex $pswd 0] ""]
+ }
+
+ # 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 prompts
+ set u_prompt [find userprompt $router]
+ if { "$u_prompt" == "" } {
+ set u_prompt "(Username|login| Login):"
+ } else {
+ set u_prompt [join [lindex $u_prompt 0] ""]
+ }
+ set p_prompt [find passprompt $router]
+ if { "$p_prompt" == "" } {
+ set p_prompt "\[Pp]assword:"
+ } else {
+ set p_prompt [join [lindex $p_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}} }
+
+ # Login to the router
+ if {[login $router $ruser $userpswd $passwd $prompt $cmethod $cyphertype]} {
+ continue
+ }
+
+ if { $do_command } {
+ if {[run_commands $prompt $command]} {
+ continue
+ }
+ } elseif { $do_script } {
+ 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/htrancid.in b/bin/htrancid.in
new file mode 100644
index 0000000..2b2eaaa
--- /dev/null
+++ b/bin/htrancid.in
@@ -0,0 +1,266 @@
+#! @PERLV_PATH@
+##
+## $Id: htrancid.in,v 1.5 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# hacked version of Hank's rancid - this one tries to deal with Hitachi's.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: htrancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # blogin timeout in seconds
+
+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 config"
+sub ShowConfig {
+ print STDERR " In ShowConfig: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ ProcessHistory("","","","$_");
+ }
+ return(0);
+}
+
+# This routine parses single command's that return no required info
+sub ShowVersion {
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ }
+ return(0)
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'version -a' => "ShowVersion",
+ 'cat /config/router.cnf' => "ShowConfig"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and write term last). pita
+@commands=(
+ "version -a",
+ "cat /config/router.cnf"
+);
+$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 htlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing htlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "htlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "htlogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "htlogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"htlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "htlogin 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: hitachi\n!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/^.*logout$/) {
+ $clean_run=1;
+ last;
+ }
+ if (/^Error:/) {
+ print STDOUT ("$host htlogin error: $_");
+ print STDERR ("$host htlogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/command:\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^:]+:)/)[0];
+ }
+ 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 ) {
+ 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 ) {
+ 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/jerancid.in b/bin/jerancid.in
new file mode 100644
index 0000000..1b72737
--- /dev/null
+++ b/bin/jerancid.in
@@ -0,0 +1,645 @@
+#! @PERLV_PATH@
+##
+## $Id: jerancid.in,v 1.25 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# jerancid - tries to deal with Juniper ERXs.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # clogin timeout in seconds
+
+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);
+ my($slots);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ next if (/^Please wait/i);
+ return(-1) if (/command authorization failed/i);
+
+ /^Juniper Edge .* (\S+)$/ &&
+ ProcessHistory("COMMENTS","keysort","A1",
+ "!Chassis type: $1 - a $_") && next;
+ /^System Release: / &&
+ ProcessHistory("COMMENTS","keysort","B1", "!$_") && next;
+ /^\s+(Version: .*)$/ &&
+ ProcessHistory("COMMENTS","keysort","B1", "!System $1\n") &&
+ next;
+
+ if (/^(slot .*)\s+slot uptime/i) {
+ ($slots++);
+ ProcessHistory("COMMENTS","keysort","B2", "!\n! $1\n");
+ next;
+ }
+ /^(--.*) --+$/ && $slots &&
+ ProcessHistory("COMMENTS","keysort","B2", "! $1\n") && next;
+ if (/^(\d+ +\S+ +(\S+).*) \S+$/ && $slots) {
+ my($line) = $1;
+ if ($2 != /--+/) {
+ ProcessHistory("COMMENTS","keysort","B3", "! $line\n");
+ }
+ next;
+ }
+ }
+ ProcessHistory("COMMENTS","keysort","B4","!\n");
+ return(0);
+}
+
+# This routine parses "show redundancy"
+sub ShowRedundancy {
+ print STDERR " In ShowRedundancy: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ next if (/^Please wait/i);
+
+ ProcessHistory("","","","! $_");
+ }
+ ProcessHistory("","","","!\n");
+ return(0);
+}
+
+# This routine parses "show environment all"
+sub ShowEnv {
+ print STDERR " In ShowEnv: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ next if (/^Please wait/i);
+ return(-1) if (/command authorization failed/i);
+
+ # skip the temperature goop
+ if (/processor\s+processor/) {
+ <INPUT>; <INPUT>; <INPUT>;
+ next;
+ }
+ /^\d+\s+\d+\s+\S+/ && next;
+
+ # strip nvs usage
+ s/, \d+% \S+\)/\)/;
+
+ s/^ //;
+ ProcessHistory("COMMENTS","keysort","D1","! $_");
+ }
+ ProcessHistory("COMMENTS","keysort","D1","!\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*)$/);
+ next if (/^Please wait/i);
+ next if (/^\s*$/);
+ return(1) if /^\s*\^\s*$/;
+ return(-1) if (/command authorization failed/i);
+ return(1) if /Ambiguous command/i;
+
+ /System Release:\s+(.*)/ &&
+ ProcessHistory("COMMENTS","keysort","C1","!Boot Release: $1\n")
+ && next;
+ /System Configuration:\s+(.*)/ &&
+ ProcessHistory("COMMENTS","keysort","C1",
+ "!Boot Configuration: $1\n") && next;
+
+ ProcessHistory("COMMENTS","keysort","C1","!$_");
+ }
+ ProcessHistory("COMMENTS","keysort","C1","!\n");
+ return(0);
+}
+
+# This routine parses "dir"
+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*)$/);
+ next if (/^Please wait/i);
+ next if (/^system\.log/);
+
+ ProcessHistory("FLASH","","","!Flash: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return(0);
+}
+
+# This routine parses "show hardware"
+sub ShowHardware {
+ print STDERR " In ShowHardware: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ next if (/^Please wait/i);
+ # return(1) if ($type =~ /^(12[40]|7[05])/);
+ return(-1) if (/command authorization failed/i);
+ next if (/^Please wait/i);
+
+ # wow...a clean table
+ ProcessHistory("","","","!$_");
+ }
+ ProcessHistory("","","","!\n");
+ return(0);
+}
+
+# This routine processes a "show configuration"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+ my($lineauto) = 0;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if (/^Please wait/i);
+ return(-1) if (/command authorization failed/i);
+ /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ $lineauto = 0 if (/^[^ ]/);
+
+ # skip the crap
+ /^! Configuration script /i && next;
+ /^! Copyright /i && next;
+
+ # Dog gone Cool matches to process the rest of the config
+ /^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) / && $filter_pwds >= 1) {
+ ProcessHistory("ENABLE","","","!$1$2 <removed>\n");
+ next;
+ }
+ if (/^(enable secret) / && $filter_pwds >= 2) {
+ ProcessHistory("ENABLE","","","!$1 <removed>\n");
+ next;
+ }
+
+ # XXX: ERX appears to not have local usernames, but leaving these in
+ # case I am wrong.
+ 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;
+ }
+ if (/^(ppp .* password) 7 .*/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+ if (/^( ip ospf authentication-key) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+ # isis interface passwords
+ if (/^(\s+isis authentication-key \S+)( \d)? \S+/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'\n"); next;
+ }
+ if (/^(\s+isis message-digest-key \d+ hmac-md5)( \d)?( \S+)/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'"); next;
+ }
+
+ # this is reversable, despite 'md5' in the cmd
+ if (/^(\s+ip ospf authentication-key \S+)( \d)? \S+/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'\n"); next;
+ }
+ if (/^(\s+ip ospf message-digest-key \d+ hmac-md5)( \d)?( \S+)/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'"); next;
+ }
+ if (/^( ip ospf message-digest-key \d+ md5) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+
+ # filter VRRP passwords
+ if (/^(\s+ip vrrp authentication-key \d+)( \d)? \s+ / &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+
+ # ftp host encrypted password oscillates
+ if (/^(host \S+ \S+ ftp) /) {
+ if ($filter_pwds >= 1 || /^host \S+ \S+ ftp \d /) {
+ ProcessHistory("","","","!$1 <removed>\n"); 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 arp lists
+ /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
+ ProcessHistory("ARP","ipsort","$1","$_") && next;
+
+ /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
+ ProcessHistory("PACL $1 $3","ipsort","$4","ip prefix-list $1 $3 $4$5\n")
+ && 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 (defined($ENV{'NOCOMMSTR'})) {
+ my($ip) = $1;
+ my($line) = "snmp-server host $ip";
+ my(@tokens) = split(' ', $');
+ my($token);
+ while ($token = shift(@tokens)) {
+ if ($token eq 'version' || $tokens[0] == 1) {
+ $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 (defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 <removed>$'");
+ next;
+ } else {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
+ }
+ }
+
+ # prune tacacs/radius server keys
+ if (/^(tacacs-server|radius-server) key / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 key <removed>\n"); next;
+ }
+ if (/^((tacacs-server|radius-server) host \S+ key)( \d)? \S+/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'"); next;
+ }
+ if (/^( key )(\d )?\S+/ && $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;
+ # filter isis keys
+ if (/^( (area|domain)-message-digest-key \d+ hmac-md5)( \d)? \S+/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'\n"); next;
+ }
+ if (/^( (area|domain)-authentication-key)( \d)? \S+( \d)?/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'\n"); 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;
+ }
+
+ # catch anything that wasnt matched above.
+ ProcessHistory("","","","$_");
+ # end of config...is a comment.
+ if (/^! end of /i) {
+ $found_end = 1;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'show version' => "ShowVersion",
+ 'show redundancy' => "ShowRedundancy",
+ 'show boot' => "ShowBoot",
+ 'show environment all' => "ShowEnv",
+ 'dir' => "DirSlotN",
+ 'show hardware' => "ShowHardware",
+ 'show configuration' => "WriteTerm"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and write term last). pita
+@commands=(
+ "show version",
+ "show redundancy",
+ "show boot",
+ "show environment all",
+ "dir",
+ "show hardware",
+ "show configuration"
+);
+$jnxe_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 -t $timeo -c\"$jnxe_cmds\" $host\n" if ($debug);
+ print STDOUT "executing clogin -t $timeo -c\"$jnxe_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "clogin -t $timeo -c \"$jnxe_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 \"$jnxe_cmds\" $host </dev/null |") || die "clogin 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: Juniper_ERX\n!\n");
+ProcessHistory("COMMENTS","keysort","B0","!\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 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;
+ }
+ }
+}
+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/jlogin.in b/bin/jlogin.in
index 0f005d7..31be4f6 100755..100644
--- a/bin/jlogin.in
+++ b/bin/jlogin.in
@@ -1,25 +1,30 @@
-#!@EXPECT_PATH@ --
+#! @EXPECT_PATH@ --
##
+## $Id: jlogin.in,v 1.41 2004/01/11 05:39:15 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
-# jlogin - juniper ssh login
+# The login expect scripts were based on Erik Sherk's gwtn, by permission.
#
-## Most options are intuitive for logging into a Cisco router.
-## The default username password is the same as the vty password.
+# jlogin - juniper login
+#
+# Most options are intuitive for logging into a Cisco router.
+# The default username password is the same as the vty password.
#
# Usage line
@@ -49,6 +54,8 @@ 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 -
@@ -82,7 +89,7 @@ for {set i 0} {$i < $argc} {incr i} {
if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
set E$varname $varvalue
} else {
- send_user "Error: invalid format for -E in $arg\n"
+ send_user "\nError: invalid format for -E in $arg\n"
exit 1
}
# alternate cloginrc file
@@ -249,6 +256,7 @@ proc source_password_file { password_file } {
# Log into the router.
proc login { router user passwd cmethod cyphertype identfile} {
global spawn_id in_proc do_command do_script passphrase prompt
+ global sshcmd
set in_proc 1
# try each of the connection methods in $cmethod until one is successful
@@ -270,13 +278,13 @@ proc login { router user passwd cmethod cyphertype identfile} {
# We use two calls to spawn since spawn does not seem to parse
# spaces correctly.
if {$identfile != ""} {
- if [ catch {spawn ssh -c $cyphertype -x -l $user -i $identfile $router} reason ] {
- send_user "\nError: failed to ssh: $reason\n"
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user -i $identfile $router} reason ] {
+ send_user "\nError: failed to $sshcmd: $reason\n"
exit 1
}
} else {
- if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
- send_user "\nError: failed to ssh: $reason\n"
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: failed to $sshcmd: $reason\n"
exit 1
}
}
@@ -438,7 +446,7 @@ foreach router [lrange $argv $i end] {
# command line username
set loginname $username
} else {
- set loginname [find user $router]
+ set loginname [join [find user $router] ""]
if { "$loginname" == "" } { set loginname $default_user }
}
@@ -447,11 +455,11 @@ foreach router [lrange $argv $i end] {
# command line passwd
set passwd $userpasswd
} else {
- set passwd [lindex [find userpassword $router] 0]
+ set passwd [join [lindex [find userpassword $router] 0] ""]
if { "$passwd" == "" } {
- set passwd [lindex [find password $router] 0]
+ set passwd [join [lindex [find password $router] 0] ""]
if { "$passwd" == "" } {
- send_user "Error: no password for $router in $password_file.\n"
+ send_user "\nError: no password for $router in $password_file.\n"
continue
}
}
@@ -460,7 +468,7 @@ foreach router [lrange $argv $i end] {
# figure out identity file to use
set identfile ""
if {[info exists identity]} {
- set identfile [lindex [find identity $router] 0]
+ set identfile [join [lindex [find identity $router] 0] ""]
}
# Figure out ssh cypher type
@@ -476,6 +484,10 @@ foreach router [lrange $argv $i end] {
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 $loginname $passwd $cmethod $cyphertype $identfile]} {
continue
diff --git a/bin/jrancid.in b/bin/jrancid.in
index 238e704..2793446 100755..100644
--- a/bin/jrancid.in
+++ b/bin/jrancid.in
@@ -1,23 +1,27 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
-## Amazingly hacked version of Hank's rancid - this one tries to
-## deal with Junipers.
+## $Id: jrancid.in,v 1.58 2004/01/11 03:49:13 heas Exp $
##
-## Original Rancid: Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
+# Amazingly hacked version of Hank's rancid - this one tries to
+# deal with Junipers.
+#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: jrancid [-d] [-l] [-f filename | $host]
@@ -147,6 +151,8 @@ sub ShowChassisClocks {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/error: the chassis subsystem is not running/ && return;
/Couldn\'t initiate connection/ && return;
@@ -171,6 +177,8 @@ sub ShowChassisEnvironment {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/error: the chassis subsystem is not running/ && return;
/Couldn\'t initiate connection/ && return;
@@ -199,6 +207,8 @@ sub ShowChassisFirmware {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/error: the chassis subsystem is not running/ && return;
/Couldn\'t initiate connection/ && return;
@@ -220,6 +230,8 @@ sub ShowChassisFpcDetail {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/error: the chassis subsystem is not running/ && return;
/Couldn\'t initiate connection/ && return;
@@ -244,6 +256,8 @@ sub ShowChassisHardware {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/error: the chassis subsystem is not running/ && return;
/Couldn\'t initiate connection/ && return;
@@ -266,6 +280,8 @@ sub ShowChassisRoutingEngine {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/error: the chassis subsystem is not running/ && return;
/Couldn\'t initiate connection/ && return;
@@ -284,8 +300,8 @@ sub ShowChassisRoutingEngine {
return;
}
-# This routine parses "show chassis feb" "show chassis scb", "show
-# chassis sfm detail", and "show chassis ssb".
+# This routine parses "show chassis cfeb", "show chassis feb", "show
+# chassis scb", "show chassis sfm detail", and "show chassis ssb".
# Only do this routine once.
sub ShowChassisSCB {
print STDERR " In ShowChassisSCB: $_" if ($debug);
@@ -295,6 +311,8 @@ sub ShowChassisSCB {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
return if ($ShowChassisSCB);
/error: the chassis subsystem is not running/ && return;
@@ -316,6 +334,25 @@ sub ShowChassisSCB {
}
# This routine parses "show system boot-messages"
+sub ShowChassisAlarms {
+ print STDERR " In ShowChassisAlarms: $_" if ($debug);
+
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
+
+ /Unrecognized command/ && return;
+ /^\s+\^/ && return;
+ /syntax error/ && return;
+ ProcessHistory("","","","# $_");
+ }
+ return;
+}
+
+# This routine parses "show system boot-messages"
sub ShowSystemBootMessages {
print STDERR " In ShowSystemBootMessages: $_" if ($debug);
@@ -324,6 +361,8 @@ sub ShowSystemBootMessages {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/Unrecognized command/ && return;
/^\s+\^/ && return;
@@ -347,10 +386,15 @@ sub ShowVersion {
while (<INPUT>) {
tr/\015//d;
last if(/^$prompt/);
+ next if(/^\s*$/);
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
/^Juniper Networks is:/ && ProcessHistory("","","","# \n# $_") && next;
ProcessHistory("","","","# $_");
}
+ ProcessHistory("","","","#\n");
+
return;
}
@@ -371,11 +415,14 @@ sub ShowConfiguration {
$found_end++;
last;
}
+ next if(/^system (shutdown message from|going down )/i);
+ next if(/^\{(master|backup)}/);
$lines++;
/^database header mismatch: / && return(-1);
/^version .*;\d+$/ && return(-1);
+ s/ # SECRET-DATA$//;
# filter snmp community, when in snmp { stanza }
/^snmp/ && $snmp++;
/^}/ && ($snmp = 0);
@@ -384,24 +431,30 @@ sub ShowConfiguration {
$_ = "$1$2 \"<removed>\"$3\n";
}
}
- if (/(\s*authentication-key ).*$/ && $filter_pwds >= 1) {
- s/(\s*authentication-key ).*$/#$1<removed>;/;
+ if (/(\s*authentication-key )[^ ;]+/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","#$1<removed>$'");
+ next;
}
- if (/(\s*hello-authentication-key ).*$/ && $filter_pwds >= 1) {
- s/(\s*hello-authentication-key ).*$/#$1<removed>;/;
+ if (/(\s*hello-authentication-key )[^ ;]+/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","#$1<removed>$'");
+ next;
}
- if (/^(.*\ssecret \")\$9\$.*(\".*)$/ && $filter_pwds >= 1) {
- s/^(.*\ssecret \")\$9\$.*(\".*)$/#$1<removed>$2/;
+ if (/^(.*\ssecret )[^ ;]+/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","#$1<removed>$'");
+ next;
}
- if (/(\s+encrypted-password ).*$/ && $filter_pwds >= 2) {
- ProcessHistory("","","","#$1<removed>;\n");
+ if (/(\s+encrypted-password )[^ ;]+/ && $filter_pwds >= 2) {
+ ProcessHistory("","","","#$1<removed>$'");
next;
}
if (/(\s+ssh-(rsa|dsa) )\"/ && $filter_pwds >= 2) {
ProcessHistory("","","","#$1<removed>;\n");
next;
}
- s/ # SECRET-DATA$//;
+ if (/^(\s+(pre-shared-|)key (ascii-text|hexadecimal) )[^ ;]+/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","#$1<removed>$'");
+ next;
+ }
ProcessHistory("","","","$_");
}
@@ -433,8 +486,10 @@ sub DoNothing {print STDOUT;}
"show chassis sfm detail" => "ShowChassisSCB",
"show chassis ssb" => "ShowChassisSCB",
"show chassis feb" => "ShowChassisSCB",
+ "show chassis cfeb" => "ShowChassisSCB",
+ "show chassis alarms" => "ShowChassisAlarms",
"show system boot-messages" => "ShowSystemBootMessages",
- "show version" => "ShowVersion",
+ "show version detail" => "ShowVersion",
"show configuration" => "ShowConfiguration"
);
@commands=(
@@ -448,8 +503,10 @@ sub DoNothing {print STDOUT;}
"show chassis sfm detail",
"show chassis ssb",
"show chassis feb",
+ "show chassis cfeb",
+ "show chassis alarms",
"show system boot-messages",
- "show version",
+ "show version detail",
"show configuration"
);
@@ -512,7 +569,8 @@ TOP: while(<INPUT>) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^>]+>)/)[0];
- $prompt =~ s/([}{)(\\])/\\$1/g;
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
diff --git a/bin/lg.cgi.in b/bin/lg.cgi.in
new file mode 100644
index 0000000..ad08c68
--- /dev/null
+++ b/bin/lg.cgi.in
@@ -0,0 +1,867 @@
+#! @PERLV_PATH@
+##
+## $Id: lg.cgi.in,v 1.47 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# The original original lookingglass s/w was written by Ed Kern. It was
+# a single script that used to be available at http://nitrous.digex.net/.
+# Provided by permission and modified beyond recognition.
+#
+# Looking glass
+# vars: query, router, args
+
+BEGIN {
+$me = $0;
+$me =~ s/.*\/(\S+)$/$1/;
+}
+
+use CGI qw/:standard escapeHTML/;
+use POSIX qw(strftime);
+use Sys::Syslog;
+use LockFile::Simple qw(lock trylock unlock);
+
+my($BASEDIR) = "@prefix@";
+my($SYSCONFDIR) = "@sysconfdir@";
+my($pingcmd) = "@LG_PING_CMD@";
+
+my($query, $max_time_diff, $cache_dir, $cloginrc, @results);
+my($type, $router_param, $remote_user, $arg, $router, $mfg);
+
+my($LG_CACHE_DIR, $LG_CLOGINRC, $LG_IMAGE, $LG_LOG, $LG_ROUTERDB, $LG_AS_REG);
+my($LG_BGP_RT, $LG_CACHE_TIME, $LG_SINGLE, $LG_STRIP);
+
+if (!defined($ENV{HOME})) { $ENV{HOME} = "."; }
+
+# note: the following functions are duplicated between lgform.cgi and lg.cgi
+# to avoid the need for module inclusion headaches from within a httpd context.
+# it is just easier to be self-contained.
+# SO, ANY CHANGES HERE SHOULD BE REFLECTED IN THE OTHER .cgi.
+
+# logging
+sub dolog
+{
+ my($level, $msg) = @_;
+
+ if (defined($LG_LOG) && $LG_LOG !~ /\//) {
+ openlog($me, "pid", $LG_LOG);
+ syslog($level, "%s", $msg);
+ closelog;
+ } else {
+ local(*LOG);
+ my($file);
+ if (defined($LG_LOG)) {
+ $file = $LG_LOG;
+ } else {
+ $file = "$cache_dir/lg.log";
+ }
+ # log date, hostname, query, addr
+ if (open(LOG, ">>$file") == 0) {
+ # stderr, if all else fails
+ printf(STDERR "[" . strftime("%a %b %e %H:%M:%S %Y", gmtime) .
+ "] could not open log file $file: $!\n");
+ printf(STDERR $msg);
+ } else {
+ printf(LOG $msg);
+ close(LOG);
+ }
+ }
+ return;
+}
+
+# read LG configuration file
+sub readconf
+{
+ my($conffile, $cmds);
+ local(*CONF);
+ if (defined($ENV{LG_CONF})) {
+ $conffile = $ENV{LG_CONF};
+ } elsif (-e "lg.conf") {
+ $conffile = "lg.conf";
+ } else {
+ $conffile = "$SYSCONFDIR/lg.conf";
+ }
+
+ if (! -f $conffile) {
+ return;
+ }
+
+ if (open(CONF, "< $conffile")) {
+ while (<CONF>) {
+ next if (/^\s*(#|$)/);
+ $cmds .= $_;
+ }
+ close(CONF);
+ eval $cmds;
+ } else {
+ printf(STDERR "ERROR: couldn\'t open the configuration file: " .
+ "$conffile: $!\n");
+ exit(1);
+ }
+
+ return;
+}
+
+# read router.db file
+sub readrouters
+{
+ my($rtrdb);
+ local(*RTR);
+
+ if (defined($LG_ROUTERDB)) {
+ $rtrdb = $LG_ROUTERDB;
+ } else {
+ $rtrdb = "$SYSCONFDIR/router.db";
+ }
+
+ if (! -f $rtrdb) {
+ my(@dirs, $dir);
+ # if the router.db file does not exist, try to compile the list from
+ # the rancid group router.db files.
+ local(*DIR);
+ if (! opendir(DIR, $BASEDIR)) {
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR: $!\n");
+ } else {
+ while ($dir = readdir(DIR)) {
+ next if ($dir =~ /^(\.|\.\.|CVS|bin|etc|logs|util)$/);
+ push(@dirs, $dir) if (-d "$BASEDIR/$dir");
+ }
+ closedir(DIR);
+
+ foreach $dir (@dirs) {
+ if (! opendir(DIR, "$BASEDIR/$dir")) {
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR/$dir: $!\n");
+ next;
+ }
+ closedir(DIR);
+ next if (! -f "$BASEDIR/$dir/router.db");
+ if (open(RTR, "< $BASEDIR/$dir/router.db")) {
+ while (<RTR>) {
+ next if (/^\s*(#|$)/);
+ # fqdn:mfg:state
+ @record = split('\:', $_);
+ next if ($record[2] !~ /up/i || $record[1] !~ /(cisco|foundry|juniper)/);
+ push(@rtrlist, join(':', ($record[0], $record[1])));
+ $rtrlabels{join(':', ($record[0], $record[1]))} = $record[0];
+ }
+ close(RTR);
+ } else {
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db " .
+ "file: $BASEDIR/$dir/router.db: $!\n");
+ }
+ }
+ }
+ } else {
+ if (open(RTR, "< $rtrdb")) {
+ while (<RTR>) {
+ next if (/^\s*(#|$)/);
+ # fqdn:mfg:state
+ @record = split('\:', $_);
+ next if ($record[2] !~ /up/i || $record[1] !~ /(cisco|foundry|juniper)/);
+ push(@rtrlist, join(':', ($record[0], $record[1])));
+ $rtrlabels{join(':', ($record[0], $record[1]))} = $record[0];
+ }
+ close(RTR);
+ } else {
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db file: " .
+ "$rtrdb: $!\n");
+ exit(1);
+ }
+ }
+
+ return;
+}
+
+# the remaining functions are particular to lg.cgi.
+
+# return true if $router is a member of @rtrlist
+sub arraymember {
+ my($rtrlist) = shift;
+ my($router) = shift;
+ my($r);
+
+ foreach $r (@$rtrlist) {
+ $r = (split(':', $r))[0];
+ return(1) if ($r eq $router);
+ }
+
+ return(0);
+}
+
+# check reachability and lock file before attempting to connect to device
+# return non-zero on error.
+sub DoRsh
+{
+ my ($router, $mfg, $cmd, $arg) = @_;
+ my($ctime) = time();
+ my($val);
+
+ my($lckobj) = LockFile::Simple->make(-delay => $lock_int,
+ -max => $max_lock_wait, -hold => $max_lock_hold);
+
+ if ($pingcmd =~ /\d$/) {
+ `$pingcmd $router`;
+ } else {
+ `$pingcmd $router 56 1`;
+ }
+ if ($?) {
+ print "$router is unreachable. Try again later.\n";
+ return(-1);
+ }
+ if (! $lckobj->lock("$cache_dir/$router")) {
+ print "$router is busy. Try again later.\n";
+ return(-1);
+ }
+ $val = &DoCmd($router, $mfg, $cmd, $arg);
+ $lckobj->unlock("$cache_dir/$router");
+ return($val);
+}
+
+# run commands on the router. return non-zero on error.
+sub DoCmd
+{
+ my($rtr, $mfg, $cmd, $arg) = @_;
+ local(*CMD);
+
+ if ($mfg =~ /foundry/i) {
+ open(CMD, "sh -c \"flogin -f $cloginrc -c \'$cmd $arg\' $rtr\" 2>&1 |");
+ } elsif ($mfg =~ /juniper/i) {
+ open(CMD, "sh -c \"jlogin -f $cloginrc -c \'$cmd $arg\' $rtr\" 2>&1 |");
+ } else {
+ open(CMD, "sh -c \"clogin -noenable -f $cloginrc -c \'$cmd $arg\' $rtr\" 2>&1 |");
+ }
+ while (<CMD>) {
+ tr/\015//d;
+ if (/^error:/i) {
+ dolog(LOG_ERR, $_);
+ if ($LG_STRIP) { undef(@results); }
+ push(@results, $_);
+ print @results;
+ return(-1);
+ }
+ push(@results, $_);
+ if (/$cmd/) {
+ ($prompt) = /^(\S*)[\#>]/;
+ if ($LG_STRIP) {
+ undef(@results);
+ } else {
+ print @results;
+ }
+ last;
+ }
+ }
+
+ while (<CMD>) {
+ last if /^$prompt[\#>]/;
+ tr/\015//d;
+ print $_;
+ push(@results, $_);
+ }
+ while (<CMD>) {}
+ close(CMD);
+
+ return(0);
+}
+
+##
+# Subroutine: Error
+# Usage: &Error("msg"));
+# Description: displays an error and exits.
+##
+sub Error {
+ my($msg) = @_;
+
+ my($q) = new CGI();
+ print $q->header;
+ if ($LG_STYLE) {
+ print $query->start_html(-title => "LookingGlass Results - $router",
+ -style => {'src' => $LG_STYLE});
+ } else {
+ print $query->start_html(-title => "LookingGlass Results - $router");
+ }
+
+ # add the company image, LG_IMAGE
+ print $LG_IMAGE;
+
+
+ print <<EOF ;
+ <br>
+ <B><FONT SIZE=+2>Looking Glass Error:</FONT></B>
+ <p>
+ $msg
+ <br>
+ <hr>
+ $LG_INFO
+EOF
+
+ print $q->end_html;
+ exit(0);
+}
+
+# convert an ipv4 address mask to prefix length
+sub mask2len {
+ my($mask) = shift;
+ my($a, $b, $c, $d) = split('\.', $mask);
+ my($p, $len);
+
+ $p = ~ (($a << 24) + ($b << 16) + ($c << 8) + $d);
+ for ($len = 32; $p > 0; $len --) {
+ $p = $p >> 1;
+ }
+
+ return($len);
+}
+
+# end the page and exit.
+sub end_page {
+
+ print <<END ;
+ </pre>
+ <!--- end page content --->
+ </body>
+END
+
+ print $query->end_html;
+ exit(0);
+}
+
+# start the page and log the transaction...
+sub start_page {
+ my($mfg) = @_;
+ my($cmd);
+
+ my($timestr) = strftime("%a %b %e %H:%M:%S %Y", gmtime);
+ dolog(LOG_INFO, sprintf("%s %s %s %s\n",
+ $ENV{REMOTE_HOST}, $ENV{REMOTE_ADDR}, $ENV{REMOTE_USER},
+ "- - [$timestr] $type $router $arg"));
+ print $query->header;
+ if ($LG_STYLE) {
+ print $query->start_html(-title =>"LookingGlass form",
+ -style => {'src' => $LG_STYLE});
+ } else {
+ print $query->start_html(-title =>"LookingGlass from");
+ }
+
+ $timestr = strftime("%a %b %e %H:%M:%S %Y %Z", gmtime);
+
+ # add the company image, LG_IMAGE
+ print $LG_IMAGE;
+
+ if ($mfg =~ /foundry/i) {
+ $cmd = $foundryCmd{$type};
+ } elsif ($mfg =~ /juniper/i) {
+ $cmd = $juniperCmd{$type};
+ } else {
+ $cmd = $ciscoCmd{$type};
+ }
+
+ print <<HEAD ;
+ </b></font>
+ <font size=+3><b><h1>Looking Glass Results - $router
+ </b></h1></font>
+ <hr>
+
+ <center>
+ <b>Date:</b> $timestr
+ <p>
+ <b>Query:</b> $cmd
+ <br>
+HEAD
+
+ if ($arg) { print "<b>Argument(s):</b> $arg\n"; }
+ print "</center>\n";
+
+ print <<END ;
+ <!--$cached-->
+ </center>
+ <p>
+ <pre>
+END
+
+ return;
+}
+
+
+# Main()
+# read the configuration file if it exists.
+readconf();
+
+# The script will now cache the results as simple files in the $cache_dir,
+# named after the type of query (queries must, of course, be one word with
+# no spaces). Modify $LG_CACHE_TIME to set the lifetime for cache entries.
+# for most web servers, cache_dir must be writable by uid nobody
+if (defined($LG_CACHE_DIR)) {
+ $cache_dir = $LG_CACHE_DIR;
+} else {
+ $cache_dir = "./tmp";
+}
+
+# read routers table to get @rtrlist
+readrouters();
+
+# when to display cache? max time difference (in seconds)
+if (defined($LG_CACHE_TIME)) {
+ $max_time_diff = $LG_CACHE_TIME;
+} else {
+ $max_time_diff = "600" ;
+}
+
+# max seconds to wait for a 'router' lock to free up
+$max_lock_wait = 30;
+$lock_int = 5;
+$max_lock_hold = 300;
+
+# clogin setup
+if (defined($LG_CLOGINRC)) {
+ $cloginrc = $LG_CLOGINRC;
+} else {
+ $cloginrc = "$ENV(HOME)/.cloginrc";
+}
+
+$query = new CGI;
+
+# get form data and validate
+$type = ($query->param('query'))[0];
+$router_param = ($query->param('router'))[0];
+$remote_user = $ENV{REMOTE_USER};
+$arg = ($query->param('args'))[0];
+# handle multiple args
+$arg =~ s/["'`]//g; # these are BS in any arg for any query
+@arg = split(' ', $arg);
+
+# verify router, commands, arguments, etc.
+($router, $mfg) = split(':', $router_param);
+if (!defined($type) || !defined($router) || $router eq "") {
+ &Error("You must at least choose a Query and a router. Try buying " .
+ "a clue.\n");
+}
+
+if ($arg !~ /^[-A-Za-z0-9|_\/ \.^\$]*$/) {
+ &Error("Funny characters in argument; ignoring.\n");
+}
+if (length($arg) >= 50) {
+ &Error("Argument string too long; ignoring. \n");
+}
+
+if (! arraymember(\@rtrlist, $router)) {
+ my($timestr) = strftime("%a %b %e %H:%M:%S %Y", gmtime);
+ dolog(LOG_WARNING, sprintf("%s %s %s %s\n",
+ $ENV{REMOTE_HOST}, $ENV{REMOTE_ADDR}, $ENV{REMOTE_USER},
+ "- - [$timestr] lg.cgi: attempt to access $router\n"));
+ Error("access to $router not permitted");
+}
+
+# conversion of command "type" passed from lgform.cgi to the vendor's syntax.
+if ($mfg =~ /cisco/i) {
+ %mfgCmd = (
+ # Debug Queries
+ log => "show logging",
+ # Interface Queries
+ framerelay => "show frame-relay pvc",
+ interface => "show interface",
+ intbrief => "show ip interface", # switch in {interface}
+ # Routing Queries
+ damp => "show ip bgp dampened-paths",
+ neighbor => "show ip bgp neighbor",
+ # Multicast Queries
+ mbgp => "show ip mbgp",
+ mbgpsum => "show ip mbgp summary",
+ mneighbor => "show ip bgp neighbor",
+ msdp => "show ip msdp summary",
+ msdpsa => "show ip msdp sa-cache",
+ msess => "show ip sdr",
+ mroute => "show ip mroute",
+ pim_interface => "show ip pim interface",
+ pim_neighbor => "show ip pim neighbor",
+ pim_rp => "show ip pim rp mapping",
+ # IPv6 Queries
+ #
+ #acl => "show access-list",
+ #aspath => "show ip as-path-access-list",
+ #communitylist => "show ip community-list",
+ ping => "ping",
+ prefix => "show ip bgp",
+ prefixlist => "show ip prefix-list",
+ regex => "show ip bgp regex",
+ route => "show ip route",
+ routemap => "show route-map",
+ rpf => "show ip rpf",
+ summary => "show ip bgp summary",
+ trace => "traceroute",
+ v6_bgp => "show bgp ipv6",
+ v6_interface => "show ipv6 interface",
+ v6_summary => "show bgp ipv6 summary"
+ );
+} elsif ($mfg =~ /foundry/i) {
+ %mfgCmd = (
+ # Debug Queries
+ log => "show log",
+ ping => "ping",
+ trace => "traceroute",
+ # Interface Queries
+ #framerelay => "show frame-relay pvc", # no compatible command
+ interface => "show interface",
+ # Routing Queries
+ damp => "show ip bgp dampened-paths",
+ neighbor => "show ip bgp neighbor",
+ #regex => "show ip bgp aspath-regex",
+ route => "show ip route",
+ summary => "show ip bgp summary",
+ # Multicast Queries
+ #mbgp => "show ip mbgp",
+ #mbgpsum => "show bgp summary",
+ #mneighbor => "show ip bgp neighbor",
+ mroute => "show ip mroute",
+ msdp => "show ip msdp summary",
+ msdpsa => "show ip msdp sa-cache",
+ msess => "show ip sdr",
+ pim_interface => "show ip pim interface",
+ pim_neighbor => "show ip pim neighbor",
+ pim_rp => "show ip pim rp mapping",
+ rpf => "show ip rpf",
+ # IPv6 Queries
+ # v6_bgp => "show bgp ipv6",
+ # v6_interface => "show ipv6 interface",
+ # v6_summary => "show bgp ipv6 summary"
+ #
+ #acl => "show access-list",
+ #aspath => "show ip as-path-access-list",
+ #communitylist => "show ip community-list",
+ routemap => "show route-map",
+ prefix => "show ip bgp",
+ prefixlist => "show ip prefix-list"
+ );
+} elsif ($mfg =~ /juniper/i) {
+ %mfgCmd = (
+ # Debug Queries
+ log => "show log messages",
+ ping => "ping rapid count 5",
+ trace => "traceroute",
+ # Interface Queries
+ framerelay => "show frame-relay pvc",
+ interface => "show interface",
+ #intbrief => "show ip interface", # switch in {interface}
+ # Routing Queries
+ damp => "show route damping suppressed terse table inet.0",
+ neighbor => "show bgp neighbor",
+ regex => "show route table inet.0 aspath-regex",
+ summary => "show bgp summary",
+ # Multicast Queries
+ mbgp => "show route table inet.2 terse",
+ mbgpsum => "show bgp summary",
+ mneighbor => "show bgp neighbor",
+ mroute => "show multicast route extensive",
+ msdp => "show msdp",
+ msdpsa => "show msdp source-active",
+ msess => "show multicast sessions",
+ pim_interface => "show pim interface",
+ pim_neighbor => "show pim neighbors",
+ pim_rp => "show pim rps",
+ pim_join => "show pim join",
+ rpf => "show multicast rpf",
+ # IPv6 Queries
+ v6_bgp => "show route table inet6.0",
+ v6_interface => "show interface",
+ v6_summary => "show bgp summary",
+ #
+ #acl => "show access-list",
+ #aspath => "show ip as-path-access-list",
+ #communitylist => "show ip community-list",
+ prefix => "show route table inet.0",
+ prefixlist => "show policy",
+ route => "show route table inet.0 terse",
+ routemap => "show policy"
+ );
+}
+
+# construct Display command from configuration
+%cmdDisp=();
+foreach $qtype (sort keys(%$queries)) {
+ next if (! scalar(%{$queries->{$qtype}}));
+ foreach $sub_type (sort keys(%{$queries->{$qtype}})) {
+ $cmdDisp{$sub_type} = $queries->{$qtype}->{$sub_type};
+ }
+}
+
+# make sure the command is not disabled
+if (! defined($cmdDisp{$type})) {
+ &Error("Unknown command type: $type\n");
+}
+
+# not all cmds/queries are implemented for all platforms
+if (! defined($mfgCmd{$type})) {
+ Error("$cmdDisp{$type} not implemented for $mfg or no suitable " .
+ "equivalent exists. sorry.\n");
+}
+$cmd = $mfgCmd{$type};
+
+# handle each query/command type
+if ($type eq "prefix" || $type eq "mbgp" || $type eq "route" ) {
+ if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
+ &Error("The IP address \"$arg[0]\" is not valid and lacking an " .
+ "address would over-burden our router.\n");
+ } elsif (defined($arg[1]) && $arg[1] !~ /^\d+\.\d+\.\d+\.\d+$/) {
+ &Error("The IP netmask \"$arg[1]\" is not valid.\n");
+ }
+ if ($mfg =~ /juniper/i && defined($arg[1])) {
+ $arg = $arg[0] . "/" . mask2len($arg[1]);
+ }
+} elsif ($type eq "v6_route" ){
+ # XXX: is this check of the address arg correct and pedantic?
+ if ($arg[0] !~ /[0-9a-fA-F:]+$/) {
+ &Error("The IPv6 address \"$arg[0]\" is not valid.\n");
+ }
+} elsif ($type eq "framerelay") {
+ if ($mfg =~ /juniper/) {
+ &Error("Juniper does not have a show frame-relay pvc command. " .
+ "Use show interface.\n");
+ }
+ if ($arg[0] > 15 && $arg[0] < 1024) {
+ $arg = $arg[0];
+ } else {
+ undef($arg);
+ }
+} elsif ($type eq "interface" || $type eq "v6_interface") {
+
+ # XXX: wtf is arg[1]?
+# if ($arg[1] =~ /[-\/0-9:.]+/) {
+# $arg = $arg[0] . " " . $arg[1];
+# } else {
+
+ if ($mfg =~ /(cisco|foundry)/) {
+ if ($arg[0] !~ /^b[^ ]+[0-9]/i && $arg[0] =~ /^b/i) {
+ $type = "intbrief";
+ $arg = "brief";
+ } else {
+ $arg = $arg[0];
+ }
+ } elsif ($mfg =~ /juniper/) {
+ my($optind) = 0;
+ # arg 0 may be an intf name or a display option, but there can
+ # only be 2 args
+ $arg = "";
+ while ($optind <= $#arg && $optind < 2) {
+ $arg[$optind] =~ s/brief/terse/;
+ if ($arg[$optind] =~ /^([a-z0-9]{2}\-\d+\/\d+\/\d+(:\d+)?)/i) {
+ $arg .= " $1";
+ } elsif ($arg[$optind] =~ /^det/i) {
+ $arg .= " detail";
+ } elsif ($arg[$optind] =~ /^ter/i) {
+ $arg .= " terse";
+ } elsif ($arg[$optind] =~ /^ext/i) {
+ $arg .= " extensive";
+ }
+ $optind += 1;
+ }
+ }
+} elsif ($type eq "log") {
+ if ($arg[0] =~ /^\s*\|?$/) {
+ shift(@arg);
+ }
+ $arg[0] =~ s/^\s*\|?//;
+ if ($arg[0] !~ /^\s*$/) {
+ if ($mfg =~ /cisco/i) {
+ $arg = " | include " . join(' ', @arg);
+ } elsif ($mfg =~ /juniper/i) {
+ $arg = " | match \"" . join(' ', @arg) . "\"";
+ } else {
+ undef($arg);
+ }
+ } else {
+ undef($arg);
+ }
+} elsif ($type eq "ping" || $type eq "trace") {
+ if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
+ if ($arg[0] !~ /^[A-Za-z0-9._-]+$/) {
+ &Error("That argument ($arg[0]) is not valid.\n");
+ }
+ }
+ $arg = $arg[0];
+} elsif ($type eq "aspath" || $type eq "communitylist") {
+ if ($arg[0] !~ /^\d+$/ || ($arg[0] < 1 && $arg[0] > 199)) {
+ &Error("That argument ($arg[0]) is not valid.\n");
+ }
+ $arg = $arg[0];
+} elsif ($type eq "acl") {
+ if ($arg[0] !~ /^\d+$/ || ($arg[0] < 100 && $arg[0] > 199) ||
+ ($arg[0] < 1300 && $arg[0] > 2699)) {
+ &Error("That argument ($arg[0]) is not valid.\n");
+ }
+ $arg = $arg[0];
+ # don't show the jewels
+ # XXX: this error msg is useless, but show acl is un-implemented.
+ &Error($mfg) if ($arg == 98 || $arg == 99);
+} elsif ($type eq "prefixlist" || $type eq "routemap") {
+ if ($arg[0] !~ /^[0-9A-Za-z][^\s\"]*$/) {
+ &Error("That argument ($arg[0]) is not valid.\n");
+ }
+ $arg = $arg[0];
+} elsif ($type eq "regex") {
+ # bgp as-path regex
+ $arg = $arg[0];
+ if ($#arg >= 1) {
+ for ($n = 1; $n <= $#arg; $n++) { $arg .= " " . $arg[$n]; }
+ }
+ # remove leading/trailing whitespace
+ $arg =~ s/^\s*//; $arg =~ s/\s*$//;
+ if ($arg !~ /^[0-9_ ^.*+?[\])\(-]*\$?$/ || $arg =~ /^\s*$/) {
+ &Error("That argument ($arg[0]) is not valid.\n");
+ }
+ # pathetic excuses for lookups
+ if ($arg =~ /^[_.* ^]*(\*|1|701|1239|1280|1740|3561|5462|10303)+[_\$]*$/ ||
+ $arg =~ /^[_.* ^]*(1|701|1239|1280|1740|3561|5462|10303)+[_ .]*[\[*.]/) {
+ &Error("Get real. Such a query has potential to over-burden our " .
+ "router.\nLook that up on your own router.\n");
+ }
+ if ($mfg =~ /juniper/) {
+ $arg =~ s/_/ /g;
+ # pre-junos 4.4 does not allow anchors
+ if ($arg =~ /\^\$/) {
+ $arg =~ "()";
+ } else {
+ $arg =~ s/[\$^]/ /g;
+ }
+ $arg = "\"$arg\"";
+ }
+ # escape any ()s
+ $arg =~ s/([\(\)])/\\$1/g;
+} elsif ($type eq "neighbor") {
+ if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
+ if ($arg[0] !~ /([A-Za-z0-9-]*.)*[A-Za-z0-9-]*.(com|edu|net|org)/) {
+ &Error("That argument ($arg[0]) is not valid.\n");
+ }
+ }
+ $arg = $arg[0];
+ if (defined($arg[1]) && $arg[1] =~ /^(a|ro|f|re)/) {
+ if ($mfg =~ /juniper/) {
+ if ($arg[1] =~ /^a/) {
+ if (defined($LG_BGP_RT)) {
+ $cmd = "show route table inet.0 all advertising-protocol ".
+ "bgp";
+ }
+ } elsif ($arg[1] =~ /^f/) {
+ if (defined($LG_BGP_RT)) {
+ $cmd = "show route damping table inet.0 all ".
+ "receive-protocol bgp";
+ }
+ } elsif ($arg[1] =~ /^r/) {
+ if (defined($LG_BGP_RT)) {
+ $cmd = "show route table inet.0 all receive-protocol bgp";
+ }
+ }
+ } else {
+ if ($arg[1] =~ /^a/) {
+ if (defined($LG_BGP_RT)) { $arg .= " advertised-routes"; }
+ } elsif ($arg[1] =~ /^f/) {
+ $arg .= " flap-statistics";
+ } elsif ($arg[1] =~ /^ro/) {
+ if (defined($LG_BGP_RT)) { $arg .= " routes"; }
+ } elsif ($arg[1] =~ /^re/) {
+ if (defined($LG_BGP_RT)) { $arg .= " received-routes"; }
+ }
+ }
+ }
+} elsif ($type eq "mneighbor") {
+ if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
+ if ($arg[0] !~ /([A-Za-z0-9-]*.)*[A-Za-z0-9-]*.(com|edu|net|org)/) {
+ &Error("That argument ($arg[0]) is not valid.\n");
+ }
+ }
+ $arg = $arg[0];
+ if (defined($arg[1]) && $arg[1] =~ /^(a|ro|f|re)/) {
+ if ($mfg =~ /juniper/) {
+ if ($arg[1] =~ /^a/) {
+ $cmd .= " advertised-routes";
+ } elsif ($arg[1] =~ /^f/) {
+ $cmd .= " flap-statistics";
+ } elsif ($arg[1] =~ /^ro/) {
+ $cmd .= " routes";
+ } elsif ($arg[1] =~ /^re/) {
+ $cmd .= " received-routes";
+ }
+ } else {
+ if ($arg[1] =~ /^a/) {
+ $arg .= " advertised-routes";
+ } elsif ($arg[1] =~ /^f/) {
+ $arg .= " flap-statistics";
+ } elsif ($arg[1] =~ /^ro/) {
+ $arg .= " routes";
+ } elsif ($arg[1] =~ /^re/) {
+ $arg .= " received-routes";
+ }
+ }
+ }
+} elsif ($type eq "damp" || $type eq "summary" || $type eq "mbgpsum") {
+ undef($arg);
+}
+
+# make stdout unbuffered, so result page streams.
+$| = 1;
+start_page();
+
+# cache the following
+if ($type eq "summary" || $type eq "mbgpsu" || $type eq "damp"
+ || $type eq "log") {
+ if (!$arg) {
+ # cache requests with no addr/argument
+ local(*CACHE);
+
+ my($file) = "$cache_dir/$type" ;
+ $file =~ s/\s+/_/g;
+ $file .= "_$router";
+
+ if (-e $file) {
+ # see if cache exists
+ @stat = stat($file);
+ $ftime = $stat[9];
+ $dtime = time() - $stat[9];
+
+ # see if we are within cache time
+ if ($dtime <= $max_time_diff) {
+ if (open(CACHE, "<$file") == 0) {
+ dolog(LOG_ERR, "couldnt open cache file $file: $!\n");
+ } else {
+ print "<b>From cache (number of seconds old (max " .
+ "$max_time_diff)):</b> $dtime\n\n";
+ while (<CACHE>) { print $_; }
+ close(CACHE);
+ &end_page();
+ }
+ }
+ }
+
+ # else, execute command and save to a new cache file
+ if (! &DoRsh($router, $mfg, $cmd, $arg)) {
+ if (open(CACHE, ">$file") == 0) {
+ dolog(LOG_ERR, "couldnt create cache file $file: $!\n");
+ exit(1);
+ } else {
+ printf(CACHE "@results");
+ close(CACHE);
+ }
+ }
+ } else {
+ &DoRsh($router, $mfg, $cmd, $arg);
+ }
+ &end_page();
+} else {
+ &DoRsh($router, $mfg, $cmd, $arg);
+ &end_page();
+}
+
+exit(0);
diff --git a/bin/lgform.cgi.in b/bin/lgform.cgi.in
new file mode 100644
index 0000000..461ae68
--- /dev/null
+++ b/bin/lgform.cgi.in
@@ -0,0 +1,259 @@
+#! @PERLV_PATH@
+##
+## $Id: lgform.cgi.in,v 1.25 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# The original original lookingglass s/w was written by Ed Kern. It was
+# a single script that used to be available at http://nitrous.digex.net/.
+# Provided by permission and modified beyond recognition.
+#
+# lgform.cgi - Looking glass front-end
+# produces html form for calling lg.cgi
+
+use CGI qw/:standard/;
+
+my(@rtrlist, %rtrlabels);
+my($BASEDIR) = "@prefix@";
+my($SYSCONFDIR) = "@sysconfdir@";
+
+# note: the following functions are duplicated between lgform.cgi and lg.cgi
+# to avoid the need for module inclusion headaches from within a httpd context.
+# it is just easier to be self-contained.
+# SO, ANY CHANGES HERE SHOULD BE REFLECTED IN THE OTHER .cgi.
+
+# logging
+sub dolog
+{
+ my($level, $msg) = @_;
+
+ if (defined($LG_LOG) && $LG_LOG !~ /\//) {
+ openlog($me, "pid", $LG_LOG);
+ syslog($level, "%s", $msg);
+ closelog;
+ } else {
+ local(*LOG);
+ my($file);
+ if (defined($LG_LOG)) {
+ $file = $LG_LOG;
+ } else {
+ $file = "$cache_dir/lg.log";
+ }
+ # log date, hostname, query, addr
+ if (open(LOG, ">>$file") == 0) {
+ # stderr, if all else fails
+ printf(STDERR "[" . strftime("%a %b %e %H:%M:%S %Y", gmtime) .
+ "] could not open log file $file: $!\n");
+ printf(STDERR $msg);
+ } else {
+ printf(LOG $msg);
+ close(LOG);
+ }
+ }
+ return;
+}
+
+# read LG configuration file
+sub readconf
+{
+ my($conffile, $cmds);
+ local(*CONF);
+ if (defined($ENV{LG_CONF})) {
+ $conffile = $ENV{LG_CONF};
+ } elsif (-e "lg.conf") {
+ $conffile = "lg.conf";
+ } else {
+ $conffile = "$SYSCONFDIR/lg.conf";
+ }
+
+ if (! -f $conffile) {
+ return;
+ }
+
+ if (open(CONF, "< $conffile")) {
+ while (<CONF>) {
+ next if (/^\s*(#|$)/);
+ $cmds .= $_;
+ }
+ close(CONF);
+ eval $cmds;
+ } else {
+ printf(STDERR "ERROR: couldn\'t open the configuration file: " .
+ "$conffile: $!\n");
+ exit(1);
+ }
+
+ return;
+}
+
+# read router.db file
+sub readrouters
+{
+ my($rtrdb);
+ local(*RTR);
+
+ if (defined($LG_ROUTERDB)) {
+ $rtrdb = $LG_ROUTERDB;
+ } else {
+ $rtrdb = "$SYSCONFDIR/router.db";
+ }
+
+ if (! -f $rtrdb) {
+ my(@dirs, $dir);
+ # if the router.db file does not exist, try to compile the list from
+ # the rancid group router.db files.
+ local(*DIR);
+ if (! opendir(DIR, $BASEDIR)) {
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR: $!\n");
+ } else {
+ while ($dir = readdir(DIR)) {
+ next if ($dir =~ /^(\.|\.\.|CVS|bin|etc|logs|util)$/);
+ push(@dirs, $dir) if (-d "$BASEDIR/$dir");
+ }
+ closedir(DIR);
+
+ foreach $dir (@dirs) {
+ if (! opendir(DIR, "$BASEDIR/$dir")) {
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR/$dir: $!\n");
+ next;
+ }
+ closedir(DIR);
+ next if (! -f "$BASEDIR/$dir/router.db");
+ if (open(RTR, "< $BASEDIR/$dir/router.db")) {
+ while (<RTR>) {
+ next if (/^\s*(#|$)/);
+ # fqdn:mfg:state
+ @record = split('\:', $_);
+ next if ($record[2] !~ /up/i || $record[1] !~ /(cisco|foundry|juniper)/);
+ push(@rtrlist, join(':', ($record[0], $record[1])));
+ $rtrlabels{join(':', ($record[0], $record[1]))} = $record[0];
+ }
+ close(RTR);
+ } else {
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db " .
+ "file: $BASEDIR/$dir/router.db: $!\n");
+ }
+ }
+ }
+ } else {
+ if (open(RTR, "< $rtrdb")) {
+ while (<RTR>) {
+ next if (/^\s*(#|$)/);
+ # fqdn:mfg:state
+ @record = split('\:', $_);
+ next if ($record[2] !~ /up/i || $record[1] !~ /(cisco|foundry|juniper)/);
+ push(@rtrlist, join(':', ($record[0], $record[1])));
+ $rtrlabels{join(':', ($record[0], $record[1]))} = $record[0];
+ }
+ close(RTR);
+ } else {
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db file: " .
+ "$rtrdb: $!\n");
+ exit(1);
+ }
+ }
+
+ return;
+}
+
+# Main()
+# read the configuration file if it exists.
+readconf();
+
+$query = new CGI;
+
+print $query->header;
+if ($LG_STYLE) {
+ print $query->start_html(-title =>"LookingGlass form",
+ -style => {'src' => $LG_STYLE});
+} else {
+ print $query->start_html(-title =>"LookingGlass form");
+}
+
+# add the company image, LG_IMAGE
+print $LG_IMAGE;
+
+print <<HEAD ;
+<br>
+<B><FONT SIZE=+2>Looking Glass</FONT></B>
+<br>
+<hr>
+HEAD
+
+# start table, etc here
+print $query->startform( -action => 'lg.cgi', -method => 'POST');
+print <<DOTABLE ;
+<center>
+<table border cellspacing=0 width=575 align=center>
+
+DOTABLE
+
+# available query types here
+print <<TABLEHEAD ;
+<tr valign=top>
+ <th align=left><B>Query:</B></th>
+ <th align=left><B>Router:</B></th>
+</tr>
+<tr><td>
+TABLEHEAD
+
+foreach $sub_type (sort keys(%$queries)) {
+ next if (! scalar(%{$queries->{$sub_type}}));
+ print $query->radio_group (-name => 'query',
+ -values => $queries->{$sub_type},
+ -default => '-', -linebreak => 'true');
+ print "\n" . $query->hr . "\n";
+}
+
+print <<QTYPES ;
+
+<P><B>Argument(s):</B> <INPUT name="args" size=30></P>
+ </TD>
+ <td aligh=left valign=top>
+QTYPES
+
+# read routers table and create the scrolling list
+readrouters();
+print $query->scrolling_list(-name => 'router',
+ -values => \@rtrlist,
+ -size => 20,
+ -labels => \%rtrlabels);
+
+# end
+print <<TABLEEND ;
+</dd>
+</td>
+</TABLE>
+<p>
+TABLEEND
+
+print $query->submit(-name => 'submit', -value =>'Submit');
+print $query->reset;
+print $query->endform;
+
+print <<TAIL ;
+</center>
+<br>
+<a href=lgnotes.html>Looking Glass notes</a>
+<p>
+$LG_INFO
+TAIL
+
+print $query->end_html;
+
+exit(0);
diff --git a/bin/mrancid.in b/bin/mrancid.in
index 8054917..8d52c27 100755..100644
--- a/bin/mrancid.in
+++ b/bin/mrancid.in
@@ -1,29 +1,33 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
-## Amazingly hacked version of Hank's rancid - this one tries to
-## deal with MRTd.
+## $Id: mrancid.in,v 1.11 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
+# Amazingly hacked version of Hank's rancid - this one tries to
+# deal with MRTd.
+#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -355,8 +359,12 @@ TOP: while(<INPUT>) {
}
while (/#\s*($cmds_regexp)\s*$/) {
$cmd = $1;
- if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+)/)[0];
- $prompt .= "[#>]"; }
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]+)/)[0];
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ $prompt .= "[#>]";
+ 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";
diff --git a/bin/nlogin.in b/bin/nlogin.in
new file mode 100644
index 0000000..685c759
--- /dev/null
+++ b/bin/nlogin.in
@@ -0,0 +1,524 @@
+#! @EXPECT_PATH@ --
+##
+## $Id: nlogin.in,v 1.14 2004/01/11 05:39:15 heas Exp $
+##
+## 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.
+##
+#
+# The login expect scripts were based on Erik Sherk's gwtn, by permission.
+#
+# nlogin - netscreen login
+#
+# Most options are intuitive for logging into a netscreen firewall.
+#
+
+# Usage line
+set usage "Usage: $argv0 \[-c command\] \[-Evar=x\] \[-f cloginrc-file\]
+\[-s script-file\] \[-t timeout\] \[-u user\] \
+\[-p user-password\] \[-y ssh_cypher_type\] firewall \[firewall...\]\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 firewall
+set do_command 0
+set do_script 0
+# The default is to automatically enable
+set enable 0
+# The default is that you login non-enabled (tacacs can have you login already
+# enabled)
+set avautoenable 1
+# 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
+
+# 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 firewall 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
+ # 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
+ }
+ # 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
+ # 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 ]
+ }
+ } -t* -
+ -T* {
+ incr i
+ set timeout [ lindex $argv $i ]
+ } -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
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ # ignore autoenable
+ #set avautoenable 1
+ } -* {
+ send_user "\nError: Unknown argument! $arg\n"
+ send_user $usage
+ exit 1
+ } default {
+ break
+ }
+ }
+}
+# Process firewalls...no firewalls 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 firewall} {
+ upvar int_$var list
+ if { [info exists list] } {
+ foreach line $list {
+ if { [string match [lindex $line 0] $firewall ] } {
+ 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 firewall.
+proc login { firewall user userpswd passwd enapasswd prompt cmethod
+cyphertype } {
+ global spawn_id in_proc do_command do_script sshcmd
+ set in_proc 1
+ set uprompt_seen 0
+
+ # Telnet to the firewall & try to login.
+ 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 $firewall} reason ]
+ } else {
+ set retval [ catch {spawn telnet $firewall $port} reason ]
+ }
+ if { $retval } {
+ send_user "\nError: telnet failed: $reason\n"
+ exit 1
+ }
+ } elseif ![string compare $prog "ssh"] {
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $firewall} reason ] {
+ send_user "\nError: $sshcmd failed: $reason\n"
+ exit 1
+ }
+ } elseif ![string compare $prog "rsh"] {
+ if [ catch {spawn rsh -l $user $firewall} 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 firewall 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 firewall might not have TACACS turned on,
+ # then it will just send the passwd.
+ # if telnet fails with connection refused, try ssh
+ expect {
+ "Connection refused" {
+ send_user "\nError: Connection Refused\n"; wait; return 1
+ } eof { send_user "\nError: Couldn't login\n"; wait; return 1
+ } "Unknown host\r\n" {
+ expect eof
+ send_user "\nError: Unknown host\n"; wait; return 1
+ } "Host is unreachable" {
+ expect eof
+ send_user "\nError: Host Unreachable!\n"; wait; return 1
+ } "No address associated with name" {
+ expect eof
+ send_user "\nError: Unknown host\n"; wait; return 1
+ }
+ -re "Are you sure you want to continue connecting .*" {
+ send "yes\r"
+ send_user "Host $firewall added to the list of known hosts.\n"
+ exp_continue }
+ -re "Host key not found .* \(yes\/no\)\?" {
+ send "yes\r"
+ send_user "Host $firewall 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 $firewall 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 $firewall. Update the SSH known_hosts file accordingly.\n"
+ return 1 }
+ denied { send_user "\nError: Check your passwd for $firewall\n"
+ catch {close}; wait; return 1
+ }
+ " ### Login failed" {send_user "\nError: Check your passwd for $firewall\n"; return 1 }
+ -re "(login:)" {
+ sleep 1;
+ send "$user\r"
+ set uprompt_seen 1
+ exp_continue
+ }
+ "@\[^\r\n]+\[Pp]assword:" {
+ # ssh pwd prompt
+ sleep 1
+ send "$userpswd\r"
+ exp_continue
+ }
+ "\[Pp]assword:" {
+ sleep 1;
+ if {$uprompt_seen == 1} {
+ send "$userpswd\r"
+ } else {
+ send "$passwd\r"
+ }
+ exp_continue
+ }
+ "$prompt" { break; }
+ }
+ }
+ 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 "set console page 0\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 "$prompt" {}
+ }
+ }
+ } else {
+ send "[subst $command]\r"
+ expect {
+ -re "$prompt" {}
+ }
+ }
+ send "exit\r"
+ expect {
+ "\n" { exp_continue }
+ -re "$prompt" {
+ send "exit\r"
+ exp_continue }
+ -re "Configuration modified, save?" {
+ send "n\r"
+ exp_continue }
+ timeout { return 0 }
+ eof { return 0 }
+ }
+ set in_proc 0
+}
+
+#
+# For each firewall... (this is main loop)
+#
+source_password_file $password_file
+set in_proc 0
+foreach firewall [lrange $argv $i end] {
+ set firewall [string tolower $firewall]
+ send_user "$firewall\n"
+
+ set prompt ">"
+
+ # Figure out passwords
+ if { $do_passwd || $do_enapasswd } {
+ set pswd [find password $firewall]
+ if { [llength $pswd] == 0 } {
+ send_user "\nError: no password for $firewall 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 $firewall] ""]
+ 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 $firewall] ""]
+ 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 $firewall] ""]
+ if { "$enauser" == "" } { set enauser $ruser }
+ }
+
+ # Figure out cypher type
+ if {[info exists cypher]} {
+ # command line cypher type
+ set cyphertype $cypher
+ } else {
+ set cyphertype [find cyphertype $firewall]
+ if { "$cyphertype" == "" } { set cyphertype "3des" }
+ }
+
+ # Figure out connection method
+ set cmethod [find method $firewall]
+ 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 firewall
+ if {[login $firewall $ruser $userpswd $passwd $enapasswd $prompt $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 "^.+$prompt" { set junk $expect_out(0,string);
+ regsub -all "\[\]\(\)\[]" $junk {\\&} prompt;
+ }
+ }
+
+ if { $do_command } {
+ if {[run_commands $prompt $command]} {
+ continue
+ }
+ } elseif { $do_script } {
+ send "set console page 0\r"
+ expect $prompt {}
+ source $sfile
+ close
+ } else {
+ label $firewall
+ log_user 1
+ interact
+ }
+
+ # End of for each firewall
+ wait
+ sleep 0.3
+}
+exit 0
diff --git a/bin/nrancid.in b/bin/nrancid.in
new file mode 100644
index 0000000..9b965a2
--- /dev/null
+++ b/bin/nrancid.in
@@ -0,0 +1,302 @@
+#! @PERLV_PATH@
+##
+## $Id: nrancid.in,v 1.13 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# Amazingly hacked version of Hank's rancid - this one tries to
+# deal with Netscreen firewalls
+#
+# Original Netscreen hacks implemented by Stephen Gill [gillsr@yahoo.com]
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$found_end = 0;
+$timeo = 90; # nlogin timeout in seconds
+
+my(%filter_pwds); # password filtering mode
+
+# This routine is used to print out the firewall 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 "get system"
+sub GetSystem {
+ print STDERR " In GetSystem: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ next if /^\s*$/;
+ last if(/$prompt/);
+
+ /^Serial Number: (\d+), Control Number: \d+$/ &&
+ ProcessHistory("SYSTEM","","", "!SN: $1\n") && next;
+ /^Product Name: (\S+)$/ &&
+ ProcessHistory("SYSTEM","","", "!Product: $1\n") && next;
+ /^Hardware Version: (\S+), / &&
+ ProcessHistory("SYSTEM","","", "!HW: $1\n") && next;
+ /^Software Version: (\S+), Type: (\S+)$/ &&
+ ProcessHistory("SYSTEM","","", "!Netscreen Type: $2\n!Software Version: $1\n") && next;
+ /^Image: (\S+), / &&
+ ProcessHistory("SYSTEM","","", "!Image: $1\n") && next;
+ /^Feature: (\S+)$/ &&
+ ProcessHistory("SYSTEM","","", "!Feature: $1\n") && next;
+ /^File Name: (\S+), Checksum: (\S+)$/ &&
+ ProcessHistory("SYSTEM","","", "!File Name: $1, Checksum: $2\n") && next;
+
+ }
+ ProcessHistory("SYSTEM","","","!\n");
+ return(0);
+}
+
+sub GetFile {
+ print STDERR " In GetFile: $_" if ($debug);
+ while (<INPUT>) {
+ last if(/$prompt/);
+ }
+ ProcessHistory("FILE","","","!\n");
+ return(0);
+}
+
+sub GetConf {
+ print STDERR " In GetConf: $_" if ($debug);
+ while (<INPUT>) {
+ tr/\015//d;
+ next if /^\s*$/;
+ last if(/$prompt/);
+
+ if (/^set admin name "(\S+)"$/ && $filter_pwds >= 1) {
+ ProcessHistory("ADMIN","","","!set admin name <removed>\n");
+ next;
+ }
+ if (/^set admin password (\S+)$/ && $filter_pwds >= 1) {
+ ProcessHistory("ADMIN","","","!set admin password <removed>\n");
+ next;
+ }
+ if (/^set admin user (\S+) password (\S+) privilege (\S+)$/ &&
+ $filter_pwds >= 1) {
+ ProcessHistory("ADMIN","","",
+ "!set admin user $1 password <removed> privilege $3\n");
+ next;
+ ProcessHistory("","","","$_");
+ }
+ $found_end=1;
+ return(1);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'get system' => "GetSystem",
+ 'get conf' => "GetConf"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important. pita
+@commands=(
+ "get system",
+ "get conf"
+);
+$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 nlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing nlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "nlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "nlogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "nlogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"nlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "nlogin 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: netscreen\n!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/^Error:/) {
+ print STDOUT ("$host nlogin error: $_");
+ print STDERR ("$host nlogin error: $_") if ($debug);
+ last;
+ }
+ while (/>\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = "\-\>\s*";
+ 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";
+ last TOP;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -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) || !$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 (!$found_end) {
+ print STDOUT "$found_end: 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");
+ }
+ unlink "$host.new" if (! $debug);
+}
diff --git a/bin/nslogin.in b/bin/nslogin.in
new file mode 100644
index 0000000..385f530
--- /dev/null
+++ b/bin/nslogin.in
@@ -0,0 +1,642 @@
+#! @EXPECT_PATH@ --
+##
+## $Id: nslogin.in,v 1.10 2004/01/11 05:39:15 heas Exp $
+##
+## 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.
+##
+#
+# The login expect scripts were based on Erik Sherk's gwtn, by permission.
+#
+# nslogin - Netscaler login
+#
+# Hacks from Anshuman Kanwar.
+#
+# 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 \[-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 1
+set do_script 0
+# The default is to automatically enable
+set enable 0
+# 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 enable 0
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ set avautoenable 1
+ set enable 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.
+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
+ 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 compare $prog "ssh"] {
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: $sshcmd 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|Connection closed by)" {
+ catch {close}; wait
+ if !$progs {
+ send_user "\nError: Connection Refused ($prog)\n"; return 1
+ }
+ }
+ eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
+ -nocase "unknown host\r" {
+ catch {close};
+ send_user "\nError: Unknown host\n"; wait; return 1
+ }
+ "Host is unreachable" {
+ catch {close};
+ send_user "\nError: Host Unreachable!\n"; wait; return 1
+ }
+ "No address associated with name" {
+ catch {close};
+ send_user "\nError: Unknown host\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
+ }
+ -re "@\[^\r\n]+ $p_prompt" {
+ # ssh pwd prompt
+ sleep 1
+ send "$userpswd\r"
+ exp_continue
+ }
+
+ "$prompt" { break; }
+ "Login invalid" {
+ send_user "\nError: Invalid login\n";
+ catch {close}; wait; return 1
+ }
+ }
+ }
+
+ 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
+
+ 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 }
+ }
+ }
+ log_user 1
+
+ if { [ string compare "extreme" "$platform" ] } {
+ send "exit\r"
+ } else {
+ send "quit\r"
+ }
+ expect {
+ "Do you wish to save your configuration changes" {
+ send "n\r"
+ exp_continue
+ }
+ "\n" { exp_continue }
+ timeout { 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.
+ set prompt "#"
+
+ # look for noenable option in .cloginrc
+ if { [find noenable $router] != "" } {
+ set enable 0
+ }
+
+ # Figure out passwords
+ if { $do_passwd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ send_user "\nError: no password for $router in $password_file.\n"
+ continue
+ }
+ if { $enable && $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] ""]
+ }
+
+ # 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]} {
+ 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
+ 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 } {
+ 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"
+ } 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/nsrancid.in b/bin/nsrancid.in
new file mode 100644
index 0000000..40a286f
--- /dev/null
+++ b/bin/nsrancid.in
@@ -0,0 +1,313 @@
+#! @PERLV_PATH@
+##
+## $Id: nsrancid.in,v 1.7 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# hacked version of Hank's rancid - this one tries to deal with Netscalers.
+# Hacks from Anshuman Kanwar.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # nslogin timeout in seconds
+
+
+@temp1 = split (/\./,$host);
+$prompt = "$temp1[0]#";
+$prompt = "netscaler#";
+
+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 config"
+sub ShowConfig {
+ print STDERR " In ShowConfig: $_" 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*$/);
+ next if (/lock-address .*$/);
+ next if (/^\# *uptime +\d+\s*$/);
+ if (/community label /) {
+ if (defined($ENV{'NOCOMMSTR'})) {
+ $_ =~ s/community label .*$/community label <removed>/;
+ }
+ }
+ return(1) if /(invalid command name)/;
+ ProcessHistory("","","","$_");
+ }
+
+ if (/exit$/) {
+ $found_end = 1;
+ $clean_run = 1;
+ return(1);
+ }
+ 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);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ }
+ return(0)
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+#--------------------------------------------------
+%commands=(
+ 'cat /etc/ns.conf' => "ShowConfig",
+ 'get log setting' => "GetLogSet"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and write term last). pita
+@commands=(
+ "cat /etc/ns.conf",
+ "get log setting"
+);
+$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 nslogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing nslogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "nslogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "nslogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "nslogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"nslogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "nslogin 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;
+}
+
+#print STDOUT "$prompt \n";
+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;
+ last;
+ }
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ 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/par.in b/bin/par.in
index 02a5383..b50bd05 100755..100644
--- a/bin/par.in
+++ b/bin/par.in
@@ -1,19 +1,22 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
+## $Id: par.in,v 1.10 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer and Peter Whiting.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
-##
+## 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
+## 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.
##
#
# PAR - parallel processing of command
diff --git a/bin/prancid.in b/bin/prancid.in
new file mode 100755
index 0000000..7ded178
--- /dev/null
+++ b/bin/prancid.in
@@ -0,0 +1,569 @@
+#! @PERLV_PATH@
+##
+## $Id: prancid.in,v 1.29 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# This version of rancid tries to deal with Prockets.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # clogin timeout in seconds
+
+my($platform); # platform/cpu type
+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;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ return(-1) if (/command authorization failed/i);
+
+ if (/(lynxos|kernel) Version: .* (\S+)/i) {
+ $platform = $2;
+ }
+ /Procket/ && ProcessHistory("COMMENTS","keysort","B0", "! $_") && next;
+ /System Uptime:/ && next;
+ /Protocol Uptime:/ && next;
+ ProcessHistory("COMMENTS","keysort","B0", "!$_") && next;
+
+ }
+ return(0);
+}
+
+# This routine parses "show package"
+sub ShowPackage {
+ print STDERR " In ShowPackage: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("COMMENTS","keysort","C0", "! $_") && next;
+
+ }
+ return(0);
+}
+
+# This routine parses "show hardware"
+sub ShowHardware {
+ print STDERR " In ShowHardware: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ # skip show hardware on titanium
+ return(0) if ($platform =~ /i386/i);
+ return(-1) if (/command authorization failed/i);
+ return(-1) if (/cli: couldn.t communicate with/);
+
+ ProcessHistory("COMMENTS","keysort","D0", "! $_") && next;
+
+ }
+ return(0);
+}
+
+# This routine parses "show inventory"
+sub ShowInventory {
+ print STDERR " In ShowInventory: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ return(0) if (/^\s+\^/);
+ return(-1) if (/command authorization failed/i);
+
+ /Procket/ && ProcessHistory("COMMENTS","keysort","E0", "! $_") && next;
+ /System Uptime:/ && next;
+ /Protocol Uptime:/ && next;
+ ProcessHistory("COMMENTS","keysort","E0", "!$_") && next;
+
+ }
+ return(0);
+}
+
+# This routine processes a "write term"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ return(-1) if (/command authorization failed/i);
+
+ /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ # skip the crap
+ if (/^(##+$|(Building|Current) configuration)/i) {
+ while (<INPUT>) {
+ next if (/^Current configuration\s*:/i);
+ next if (/^([%!].*|\s*)$/);
+ last;
+ }
+ tr/\015//d;
+ }
+ # some versions have other crap mixed in with the bits in the
+ # block above
+ /^! Last Changed:/ && next;
+
+ # 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
+# /^ clockrate / && next; # kill clockrate on serial interfaces
+
+ if (/^(enable secret( level \d)?) / && $filter_pwds >= 2) {
+ ProcessHistory("ENABLE","","","!$1 <removed>\n");
+ 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;
+ }
+
+ # prune passwords {bgp, ...}
+ if (/^(\s*)password / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1password <removed>\n");
+ next;
+ }
+ # prune authentication keys {vrrp vrid N, router isis...}
+ if (/^(\s*authentication \S+ key) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n");
+ next;
+ }
+ if (/^(\s*authentication-key) \d \S+( .*)/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$2\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;
+# }
+
+ # prune ospf keys
+ if (/^( ip ospf authentication-key) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\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 reversable, despite 'md5' in the cmd
+ if (/^(\s*message-digest-key \d+ md5) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+
+# if (/^((crypto )?isakmp key) \S+ / && $filter_pwds >= 1) {
+# ProcessHistory("","","","!$1 <removed> $'"); 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","ipsort","$3","$_") && next;
+# # order extended access-lists
+# /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
+# ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+# /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
+# ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+# /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ &&
+# ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next;
+# # order arp lists
+# /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
+# ProcessHistory("ARP","ipsort","$1","$_") && next;
+# /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
+# ProcessHistory("PACL $1 $3","ipsort","$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 (defined($ENV{'NOCOMMSTR'})) {
+ 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)));
+ } 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 (defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 <removed>$'") && next;
+ } else {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
+ }
+ }
+
+ # prune tacacs/radius server keys
+ if (/^(tacacs-server|radius-server) key / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 key <removed>\n"); next;
+ }
+ if (/^(tacacs-server host \S+( .*)? key) (\d )?\S+/
+ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+
+ # order clns host statements
+# /^clns host \S+ (\S+)/ &&
+# ProcessHistory("CLNS","keysort","$1","$_") && next;
+
+ # prune vrrp password
+ if (/^( ip vrrp authentication .* key) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+ # prune isis password
+ if (/^( isis authentication-key) \d \S+/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'"); next;
+ }
+ # prune msdp password
+ if (/^(ip msdp password \S+) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); 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;
+# # 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;
+
+ # catch anything that wasnt matched above.
+ ProcessHistory("","","","$_");
+ # end of config.
+ if (/^end$/) {
+ $found_end = 1;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'show version all' => "ShowVersion",
+ 'show package' => "ShowPackage",
+ 'show hardware' => "ShowHardware",
+ 'show inventory' => "ShowInventory",
+ 'write term' => "WriteTerm"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and write term last). pita
+@commands=(
+ "show version all",
+ "show package",
+ "show hardware",
+ "show inventory",
+ "write term"
+);
+$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 -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 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: procket\n!\n");
+ProcessHistory("COMMENTS","keysort","B0","!\n"); # show version
+ProcessHistory("COMMENTS","keysort","C0","!\n"); # show package
+ProcessHistory("COMMENTS","keysort","D0","!\n"); # show hardware
+ProcessHistory("COMMENTS","keysort","E0","!\n"); # show inventory
+ProcessHistory("COMMENTS","keysort","Z0","!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/\#\s?exit$/) {
+ $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]; }
+ 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/create_cvs.in b/bin/rancid-cvs.in
index 06d414b..22d5fd2 100755..100644
--- a/bin/create_cvs.in
+++ b/bin/rancid-cvs.in
@@ -1,34 +1,39 @@
-#!/bin/sh
+#! /bin/sh
##
+## $Id: rancid-cvs.in,v 1.16 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1996-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
-##
+## 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
+## 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.
##
#
-# Create all of the misc files & dirs needed.
+# Create all of the misc files & dirs needed for each group and import them
+# into CVS.
#
-# create_cvs
+# rancid-cvs
#
# Read in the environment
-ENVFILE="`dirname $0`/env"
+ENVFILE="@sysconfdir@/rancid.conf"
. $ENVFILE
# Base dir
if [ ! -d $BASEDIR ]; then
- mkdir -p $BASEDIR
+ mkdir -p $BASEDIR ||
+ (echo "Could not create local state directory: $BASEDIR"; exit 1)
fi
cd $BASEDIR
diff --git a/bin/rancid-fe.in b/bin/rancid-fe.in
index b25dcb1..b80a194 100755..100644
--- a/bin/rancid-fe.in
+++ b/bin/rancid-fe.in
@@ -1,22 +1,25 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
+## $Id: rancid-fe.in,v 1.36 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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-FE - front-end to rancid/jrancid for use with par.
+# rancid-FE - front-end to rancid/jrancid/etc. for use with par.
#
# usage: rancid-fe <router>:<vendor>
#
@@ -25,18 +28,28 @@ require 5;
($router, $vendor) = split('\:', $ARGV[0]);
- if ($vendor =~ /^alteon$/i) { exec('arancid', $router); }
-elsif ($vendor =~ /^baynet$/i) { exec('brancid', $router); }
-elsif ($vendor =~ /^cat5$/i) { exec('cat5rancid', $router); }
-elsif ($vendor =~ /^cisco$/i) { exec('rancid', $router); }
-elsif ($vendor =~ /^extreme$/i) { exec('xrancid', $router); }
-elsif ($vendor =~ /^ezt3$/i) { exec('erancid', $router); }
-elsif ($vendor =~ /^force10$/i) { exec('f10rancid', $router); }
-elsif ($vendor =~ /^foundry$/i) { exec('francid', $router); }
-elsif ($vendor =~ /^hp$/i) { exec('hrancid', $router); }
-elsif ($vendor =~ /^juniper$/i) { exec('jrancid', $router); }
-elsif ($vendor =~ /^mrtd$/i) { exec('mrancid', $router); }
-elsif ($vendor =~ /^redback$/i) { exec('rrancid', $router); }
+ if ($vendor =~ /^alteon$/i) { exec('arancid', $router); }
+elsif ($vendor =~ /^baynet$/i) { exec('brancid', $router); }
+elsif ($vendor =~ /^cat5$/i) { exec('cat5rancid', $router); }
+elsif ($vendor =~ /^cisco$/i) { exec('rancid', $router); }
+elsif ($vendor =~ /^css$/i) { exec('cssrancid', $router); }
+elsif ($vendor =~ /^enterasys$/i) { exec('rivrancid', $router); }
+elsif ($vendor =~ /^erx$/i) { exec('jerancid', $router); }
+elsif ($vendor =~ /^extreme$/i) { exec('xrancid', $router); }
+elsif ($vendor =~ /^ezt3$/i) { exec('erancid', $router); }
+elsif ($vendor =~ /^force10$/i) { exec('f10rancid', $router); }
+elsif ($vendor =~ /^foundry$/i) { exec('francid', $router); }
+elsif ($vendor =~ /^hitachi$/i) { exec('htrancid', $router); }
+elsif ($vendor =~ /^hp$/i) { exec('hrancid', $router); }
+elsif ($vendor =~ /^juniper$/i) { exec('jrancid', $router); }
+elsif ($vendor =~ /^mrtd$/i) { exec('mrancid', $router); }
+elsif ($vendor =~ /^netscaler$/i) { exec('nsrancid', $router); }
+elsif ($vendor =~ /^netscreen$/i) { exec('nrancid', $router); }
+elsif ($vendor =~ /^procket$/i) { exec('prancid', $router); }
+elsif ($vendor =~ /^redback$/i) { exec('rrancid', $router); }
+elsif ($vendor =~ /^riverstone$/i) { exec('rivrancid', $router); }
+elsif ($vendor =~ /^tnt$/i) { exec('tntrancid', $router); }
+elsif ($vendor =~ /^zebra$/i) { exec('zrancid', $router); }
else {
printf(STDERR "unknown router manufacturer for $router: $vendor\n");
exit(-1);
diff --git a/bin/do-diffs.in b/bin/rancid-run.in
index 874007c..b59b026 100755..100644
--- a/bin/do-diffs.in
+++ b/bin/rancid-run.in
@@ -1,21 +1,29 @@
-#!/bin/sh
-## Copyright (C) 1997-2001 by Henry Kilmer.
+#! /bin/sh
+##
+## $Id: rancid-run.in,v 1.28 2004/01/11 06:11:23 hank Exp $
+##
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
-# do diffs for each of the diff groups ($LIST_OF_GROUPS) from <BASEDIR>/bin/env
+## Except where noted otherwise, rancid was written by and is maintained by
+## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
##
+#
+# Run rancid for each of the rancid groups defined by $LIST_OF_GROUPS in
+# @sysconfdir@/rancid.conf or those specified on the command-line.
+#
-ENVFILE="`dirname $0`/env"
+ENVFILE="@sysconfdir@/rancid.conf"
. $ENVFILE
@@ -69,12 +77,12 @@ fi
if [ $# -ge 1 ] ; then
LIST_OF_GROUPS="$*"; export LIST_OF_GROUPS
elif [ "$LIST_OF_GROUPS" = "" ] ; then
- echo "LIST_OF_GROUPS is empty in $ENVFILE"
- exit 1
+ echo "LIST_OF_GROUPS is empty in $ENVFILE"
+ exit 1
fi
-if [ ! -d $BASEDIR/logs ] ; then
- mkdir $BASEDIR/logs
+if [ ! -d $LOGDIR ] ; then
+ mkdir $LOGDIR || (echo "Could not create log directory: $LOGDIR"; exit 1)
fi
for GROUP in $LIST_OF_GROUPS
@@ -99,7 +107,7 @@ do
if [ -s $TMPDIR/.$GROUP.old ]
then
(
- echo "To: @MAILPLUS@admin-$GROUP"
+ echo "To: @ADMINMAILPLUS@$GROUP"
echo "Subject: rancid hung - $GROUP"
echo "Precedence: bulk"
echo ""
@@ -124,5 +132,5 @@ END
echo
echo ending: `date`
- ) >$BASEDIR/logs/$GROUP.`date +%Y%m%d.%H%M%S` 2>&1
+ ) >$LOGDIR/$GROUP.`date +%Y%m%d.%H%M%S` 2>&1
done
diff --git a/bin/rancid.in b/bin/rancid.in
index 4566b58..27a5a48 100755..100644
--- a/bin/rancid.in
+++ b/bin/rancid.in
@@ -1,19 +1,22 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
+## $Id: rancid.in,v 1.168 2004/01/12 00:52:47 asp Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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
@@ -21,7 +24,7 @@
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -135,31 +138,40 @@ sub sortbyipaddr {
# This routine parses "show version"
sub ShowVersion {
print STDERR " In ShowVersion: $_" if ($debug);
+ my($slaveslot);
while (<INPUT>) {
tr/\015//d;
- study;
last if(/^$prompt/);
next if(/^(\s*|\s*$cmd\s*)$/);
return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
if (/^Slave in slot (\d+) is running/) {
$slave = " Slave:";
+ $slaveslot = ", slot $1";
next;
}
+ if (/^Application and Content Networking Software/) { $type="CE"; }
+ /^Application and Content Networking Software Release /i &&
+ ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
/^Cisco Secure PIX /i &&
ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
- /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ &&
+ # PIX fail-over license
+ /^This PIX has an?\s+(.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","C1", "!$_") && next;
+ /^(Cisco )?IOS .* Software,? \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","F1",
- "!Image:$slave Software: $1, $2\n") && next;
+ "!Image:$slave Software: $2, $3\n") && next;
/^([A-Za-z-0-9_]*) Synced to mainline version: (.*)$/ &&
ProcessHistory("COMMENTS","keysort","F2",
"!Image:$slave $1 Synced to mainline version: $2\n") && next;
/^Compiled (.*)$/ &&
ProcessHistory("COMMENTS","keysort","F3",
"!Image:$slave Compiled: $1\n") && next;
- /^ROM: (System )?Bootstrap.*(Version.*)$/ &&
+ /^ROM: (IOS \S+ )?(System )?Bootstrap.*(Version.*)$/ &&
ProcessHistory("COMMENTS","keysort","G1",
- "!ROM Bootstrap: $2\n") && next;
+ "!ROM Bootstrap: $3\n") && next;
if (/^Hardware:\s+(.*), (.* RAM), CPU (.*)$/) {
ProcessHistory("COMMENTS","keysort","A1",
"!Chassis type: $1 - a PIX\n");
@@ -169,6 +181,17 @@ sub ShowVersion {
}
/^Serial Number:\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","C1", "!$_") && next;
+ # CatOS 3500xl stuff
+ /^System serial number(:\s+.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","C1", "!Serial Number$1\n") &&
+ next;
+ /^Model / &&
+ ProcessHistory("COMMENTS","keysort","C2", "!$_") && next;
+ /^Motherboard / &&
+ ProcessHistory("COMMENTS","keysort","C3", "!$_") && next;
+ /^Power supply / &&
+ ProcessHistory("COMMENTS","keysort","C4", "!$_") && next;
+
/^Activation Key:\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","C2", "!$_") && next;
/^ROM: \d+ Bootstrap .*(Version.*)$/ &&
@@ -193,48 +216,80 @@ sub ShowVersion {
my($cpu) = $2;
my($mem) = $3;
my($device) = "router";
- if ( $1 eq "CSC") {
+
+ # the next line ought to be the more specific cpu info, grab it.
+ # yet, some boards/IOS vers have a processor ID line between these
+ # two. grrr. make sure we dont grab the "software" junk that
+ # follows these lines by looking for "CPU at " or the 2600s
+ # "processor: " unique string. there are undoubtedly many other
+ # incantations. for a slave, we dont get this info and its just a
+ # blank line.
+ $_ = <INPUT>;
+ $_ = <INPUT> if (/processor board id/i);
+ $_ = "" if (! /(cpu at |processor: |$cpu processor,)/i);
+ tr/\015//d;
+ s/implementation/impl/i;
+ if ($_ !~ /^\s*$/) {
+ chomp;
+ s/^/, /;
+ }
+
+ if ( $proc eq "CSC") {
$type = "AGS";
- } elsif ( $1 eq "CSC4") {
+ } elsif ( $proc eq "CSC4") {
$type = "AGS+";
- } elsif ( $1 eq "2511" || $1 eq "2524" || $1 eq "AS2511-RJ") {
+ } elsif ( $proc =~ /^(AS)?25[12][12]/) {
$type = "2500";
- } elsif ( $1 =~ /261[01]/ || $1 =~ /262[01]/ ) {
+ } elsif ( $proc =~ /261[01]/ || $proc =~ /262[01]/ ) {
$type = "2600";
- } elsif ( $1 eq "3620" || $1 eq "3640") {
+ } elsif ( $proc =~ /^36[0246][0-9]/) {
$type = "3600";
- } elsif ( $1 eq "RSP7000") {
+ } elsif ( $proc =~ /^37/) {
+ $type = "3700";
+ } elsif ( $proc eq "RSP7000") {
$type = "7500";
- } elsif ( $1 =~ /RSP\d/) {
+ } elsif ( $proc =~ /RSP\d/) {
$type = "7500";
- } elsif ( $1 eq "RP1") {
+ } elsif ( $proc eq "RP1") {
$type = "7000";
- } elsif ( $1 eq "RP") {
+ } elsif ( $proc eq "RP") {
$type = "7000";
- } elsif ( $1 =~ /720[246]/) {
+ } elsif ( $proc =~ /720[246]/) {
$type = "7200";
- } elsif ( $1 =~ /1200[48]\/GRP/ || $1 =~ /1201[26]\/GRP/) {
+ } elsif ( $proc =~ /1200[48]\/GRP/ || $proc =~ /1201[26]\/GRP/) {
$type = "12000";
- } elsif ( $1 =~ /1201[26]-8R\/GRP/) {
+ } elsif ( $proc =~ /1201[26]-8R\/GRP/) {
$type = "12000";
- } elsif ( $1 =~ /WS-C29/) {
+ } elsif ( $proc =~ /WS-C29/) {
$type = "2900XL";
$device = "switch";
- } elsif ( $1 =~ /WS-C35/) {
+ } elsif ( $proc =~ /WS-C355/) {
+ $type = "3550";
+ $device = "switch";
+ } elsif ( $proc =~ /WS-C35/) {
$type = "3500XL";
$device = "switch";
- } elsif ( $1 =~ /6000/) {
+ } elsif ( $proc =~ /WS-C45/) {
+ $type = "4500";
+ $device = "switch";
+ } elsif ( $proc =~ /6000/) {
$type = "6000";
$device = "switch";
+ } elsif ( $proc =~ /CISCO76/) {
+ $type = "7600";
+ $device = "router";
+ } elsif ( $proc =~ /1900/) {
+ $type = "1900";
+ $device = "switch";
} else {
- $type = $1;
+ $type = $proc;
}
print STDERR "TYPE = $type\n" if ($debug);
ProcessHistory("COMMENTS","keysort","A1",
"!Chassis type:$slave $proc - a $type $device\n");
ProcessHistory("COMMENTS","keysort","B1",
"!Memory:$slave main $mem\n");
- ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu\n");
+ ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu$_$slaveslot\n");
next;
}
if (/(\S+) Silicon\s*Switch Processor/) {
@@ -249,7 +304,7 @@ sub ShowVersion {
/^(\d+[kK]) bytes of multibus/ &&
ProcessHistory("COMMENTS","keysort","B2",
"!Memory: multibus $1\n") && next;
- /^(\d+[kK]) bytes of non-volatile/ &&
+ /^(\d+[kK]) bytes of (non-volatile|NVRAM)/ &&
ProcessHistory("COMMENTS","keysort","B3",
"!Memory: nvram $1\n") && next;
/^(\d+[kK]) bytes of flash memory/ &&
@@ -272,9 +327,6 @@ sub ShowVersion {
ProcessHistory("COMMENTS","keysort","I0","!\n");
}
ProcessHistory("COMMENTS","keysort","I1","! $_");
- # The line after the WARNING is what to do about it.
- $_ = <INPUT>; tr/\015//d;
- ProcessHistory("COMMENTS","keysort","I1","! $_");
}
if (/^Configuration register is (.*)$/) {
$config_register=$1;
@@ -284,6 +336,57 @@ sub ShowVersion {
return(0);
}
+# This routine parses "show redundancy"
+sub ShowRedundancy {
+ print STDERR " In ShowRedundancy: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
+
+ /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F1",
+ "!Image:$slave Software: $1, $2\n") && next;
+ /^Compiled (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F3",
+ "!Image:$slave Compiled: $1\n") && next;
+ }
+ 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*)$/);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
+
+ /FRU is .(.*)\'/ && ($tmp = $1);
+ /Product Number = .(.*)\'/ &&
+ ProcessHistory("COMMENTS","keysort","D0","!\n") &&
+ 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);
@@ -295,6 +398,8 @@ sub ShowInstallActive {
return(1) if /^\s*\^\s*$/;
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
+ s/^<-+ More -+>\s*//;
ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next;
}
return(0);
@@ -311,6 +416,8 @@ sub ShowEnv {
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^7/);
return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
if (!defined($E0)) {
$E0=1;
ProcessHistory("COMMENTS","keysort","E0","!\n");
@@ -331,11 +438,42 @@ sub ShowEnv {
ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next;
/^\s*(redundant .*)/i &&
ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next;
+ /^\s*(RPS is .*)/i &&
+ ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next;
}
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 (/command authorization failed/i);
+ # return(1) if ($type !~ /^12[40]/);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
+ /^$/ && next;
+
+ /^\s+Chassis model: (\S+)/ &&
+ ProcessHistory("COMMENTS","keysort","D0","!\n") &&
+ 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 {
@@ -348,6 +486,8 @@ sub ShowGSR {
next if (/^(\s*|\s*$cmd\s*)$/);
return(-1) if (/command authorization failed/i);
# return(1) if ($type !~ /^12[40]/);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
/^$/ && next;
/^\s+Chassis: type (\S+) Fab Ver: (\S+)/ &&
ProcessHistory("COMMENTS","keysort","D0","!\n") &&
@@ -386,15 +526,17 @@ sub ShowBoot {
return(1) if /Ambiguous command/i;
return(1) if /(Invalid input detected|Type help or )/;
return(1) if /(Open device \S+ failed|Error opening \S+:)/;
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
next if /CONFGEN variable/;
if (!defined($H0)) {
$H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n");
}
if ($type !~ /^(12[04]|7)/) {
if ($type !~ /^(29|35)00/) {
- ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_");
+ ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_");
} else {
- ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
+ ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
}
} elsif (/variable/) {
ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
@@ -418,6 +560,8 @@ sub ShowFlash {
return(-1) if (/command authorization failed/i);
return(1) if /^\s*\^\s*$/;
return(1) if /(Invalid input detected|Type help or )/;
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
ProcessHistory("FLASH","","","!Flash: $_");
}
ProcessHistory("","","","!\n");
@@ -438,13 +582,15 @@ sub DirSlotN {
# 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 /No such device/i;
+ 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 /\%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+:)/;
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
ProcessHistory("FLASH","","","!Flash: $dev: $_");
}
ProcessHistory("","","","!\n");
@@ -458,11 +604,12 @@ sub ShowContAll {
while (<INPUT>) {
tr/\015//d;
- study;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
# 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
+ s/^<-+ More -+>\s*//;
if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; }
/^(BRI unit \d)/ &&
ProcessHistory("INT","","","!Interface: $1\n") && next;
@@ -521,6 +668,8 @@ sub ShowContCbus {
next if (/^(\s*|\s*$cmd\s*)$/);
#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
+ s/^<-+ More -+>\s*//;
if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) {
$slot = $1;
$board{$slot} = $2;
@@ -562,11 +711,12 @@ sub ShowDiagbus {
while (<INPUT>) {
tr/\015//d;
- study;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^7[05]/);
return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
if (/^\s*Slot (\d+):/i) {
$slot = $1;
next;
@@ -641,7 +791,7 @@ sub ShowDiagbus {
return(0);
}
-# This routine parses "show diag" for the gsr, 7200, 3600, 2600.
+# 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.
@@ -649,12 +799,14 @@ sub ShowDiag {
while (<INPUT>) {
tr/\015//d;
- study;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type !~ /^(12[40]|720|36|26)/);
return(-1) if (/command authorization failed/i);
/^$/ && next;
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
+
s/Port Packet Over SONET/POS/;
if (/^\s*SLOT\s+(\d+)\s+\((.*)\): (.*)/) {
$slot = $1;
@@ -663,11 +815,22 @@ sub ShowDiag {
next;
}
if (/^\s+MAIN:\s* type \d+,\s+(.*)/) {
- ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $1\n") && next;
+ ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $1\n");
+ 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+PCA:\s+(.*)/) {
local($part) = $1;
$_ = <INPUT>;
@@ -707,35 +870,78 @@ sub ShowDiag {
}
next;
}
- # 7200 and 3600 stuff
- if (/^(Slot)\s+(\d+(\/\d+)?):/ || /^\s+(WIC|VIC) Slot (\d):/) {
+ # 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 "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 format to look more like 7500 output
+ # 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");
+ 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");
+ 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");
+ ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: type $1$2\n") && next;
/\s+(FT1)$/ &&
- ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: type $1\n");
+ ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: 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;
}
+ # 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; }
+ }
+PerlSucks:
+ 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;
@@ -760,6 +966,8 @@ sub ShowModule {
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(-1) if (/command authorization failed/i);
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
# match slot/card info line
if (/^ *(\d+)\s+(\d+)\s+(.*)\s+(\S+)\s+(\S+)\s*$/) {
@@ -781,6 +989,24 @@ sub ShowModule {
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 /(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 {
@@ -794,6 +1020,8 @@ sub ShowC7200 {
#return(1) if ($type !~ /^72/);
return(-1) if (/command authorization failed/i);
/^$/ && next;
+ # the pager can not be disabled per-session on the PIX
+ s/^<-+ More -+>\s*//;
if (/^(C7200 )?Midplane EEPROM:/) {
$_ = <INPUT>;
/revision\s+(\S+).*revision\s+(\S+)/;
@@ -838,6 +1066,8 @@ sub ShowVTP {
#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
+ s/^<-+ More -+>\s*//;
if (/^VTP Operating Mode\s+:\s+(Transparent|Server)/) {
$DO_SHOW_VLAN = 1;
}
@@ -858,8 +1088,13 @@ sub ShowVLAN {
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /(Invalid input detected|Type help or )/;
+ # newer releases (~12.1(9)) place the vlan config in the normal
+ # configuration (write term).
+ return(1) if ($type =~ /^(3550|4500|7600)$/);
#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
+ s/^<-+ More -+>\s*//;
ProcessHistory("COMMENTS","keysort","IO","!VLAN: $_");
}
ProcessHistory("COMMENTS","keysort","IO","!\n");
@@ -869,16 +1104,17 @@ sub ShowVLAN {
# This routine processes a "write term"
sub WriteTerm {
print STDERR " In WriteTerm: $_" if ($debug);
- my($lineauto) = 0;
+ my($lineauto,$comment,$linecnt) = (0,0,0);
while (<INPUT>) {
tr/\015//d;
- study;
last if(/^$prompt/);
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
+ return(0) if ($found_end); # Only do this routine once
+ $linecnt++;
$lineauto = 0 if (/^[^ ]/);
# skip the crap
if (/^(##+$|(Building|Current) configuration)/i) {
@@ -898,6 +1134,16 @@ sub WriteTerm {
# 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
@@ -932,6 +1178,14 @@ sub WriteTerm {
}
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;
@@ -955,7 +1209,7 @@ sub WriteTerm {
}
if (/^\s+(domain-password|area-password) (\S+)( .*)?/
&& $filter_pwds >= 1) {
- ProcessHistory("","","","!$1 <removed>$2\n"); next;
+ 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) {
@@ -964,10 +1218,25 @@ sub WriteTerm {
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)/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); 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+)/) {
@@ -1057,10 +1326,14 @@ sub WriteTerm {
ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
}
}
- # order/prune tacacs/radius server statements
+ # prune tacacs/radius server keys
if (/^(tacacs-server|radius-server) key / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 key <removed>\n"); next;
}
+ if (/^((tacacs-server|radius-server) host \S+ key) / &&
+ $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
# order clns host statements
/^clns host \S+ (\S+)/ &&
ProcessHistory("CLNS","keysort","$1","$_") && next;
@@ -1076,9 +1349,9 @@ sub WriteTerm {
ProcessHistory("NTP","keysort",$sortkey,"$_");
next;
}
- # order ip host line statements
- /^ip host line(\d+)/ &&
- ProcessHistory("IPHOST","numsort","$1","$_") && 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;
@@ -1105,6 +1378,14 @@ sub WriteTerm {
return(1);
}
}
+ # 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) {
+ $found_end = 1;
+ return(1);
+ }
+
return(0);
}
@@ -1114,8 +1395,11 @@ sub DoNothing {print STDOUT;}
# Main
%commands=(
'show version' => "ShowVersion",
+ 'show redundancy secondary' => "ShowRedundancy",
+ 'show idprom backplane', => "ShowIDprom",
'show install active' => "ShowInstallActive",
'show env all' => "ShowEnv",
+ 'show rsp chassis-info',=> "ShowRSP",
'show gsr chassis' => "ShowGSR",
'show boot' => "ShowBoot",
'show bootvar' => "ShowBoot",
@@ -1131,22 +1415,44 @@ sub DoNothing {print STDOUT;}
'dir /all disk2:' => "DirSlotN",
"dir /all sup-bootflash:"=> "DirSlotN", # cat 6500-ios
"dir /all sup-microcode:"=> "DirSlotN", # cat 6500-ios
+ 'dir /all slavenvram:' => "DirSlotN",
+ 'dir /all slavebootflash:' => "DirSlotN",
+ 'dir /all slaveslot0:' => "DirSlotN",
+ 'dir /all slavedisk0:' => "DirSlotN",
+ 'dir /all slaveslot1:' => "DirSlotN",
+ 'dir /all slavedisk1:' => "DirSlotN",
+ 'dir /all slaveslot2:' => "DirSlotN",
+ 'dir /all slavedisk2:' => "DirSlotN",
+ "dir /all slavesup-bootflash:"=> "DirSlotN", # cat 7609
+ 'dir /all sec-nvram:' => "DirSlotN",
+ 'dir /all sec-bootflash:' => "DirSlotN",
+ 'dir /all sec-slot0:' => "DirSlotN",
+ 'dir /all sec-disk0:' => "DirSlotN",
+ 'dir /all sec-slot1:' => "DirSlotN",
+ 'dir /all sec-disk1:' => "DirSlotN",
+ 'dir /all sec-slot2:' => "DirSlotN",
+ 'dir /all sec-disk2:' => "DirSlotN",
'show controllers' => "ShowContAll",
'show controllers cbus' => "ShowContCbus",
'show diagbus' => "ShowDiagbus",
'show diag' => "ShowDiag",
'show module' => "ShowModule", # cat 6500-ios
+ 'show spe version' => "ShowSpeVersion",
'show c7200' => "ShowC7200",
'show vtp status' => "ShowVTP",
'show vlan' => "ShowVLAN",
+ 'show running-config' => "WriteTerm",
'write term' => "WriteTerm"
);
# keys() doesnt return things in the order entered and the order of the
# cmds is important (show version first and write term last). pita
@commands=(
"show version",
+ "show redundancy secondary",
+ "show idprom backplane",
"show install active",
"show env all",
+ "show rsp chassis-info",
"show gsr chassis",
"show boot",
"show bootvar",
@@ -1162,14 +1468,33 @@ sub DoNothing {print STDOUT;}
"dir /all disk2:",
"dir /all sup-bootflash:",
"dir /all sup-microcode:",
+ "dir /all slavenvram:",
+ "dir /all slavebootflash:",
+ "dir /all slaveslot0:",
+ "dir /all slavedisk0:",
+ "dir /all slaveslot1:",
+ "dir /all slavedisk1:",
+ "dir /all slaveslot2:",
+ "dir /all slavedisk2:",
+ "dir /all slavesup-bootflash:",
+ "dir /all sec-nvram:",
+ "dir /all sec-bootflash:",
+ "dir /all sec-slot0:",
+ "dir /all sec-disk0:",
+ "dir /all sec-slot1:",
+ "dir /all sec-disk1:",
+ "dir /all sec-slot2:",
+ "dir /all sec-disk2:",
"show controllers",
"show controllers cbus",
"show diagbus",
"show diag",
"show module",
+ "show spe version",
"show c7200",
"show vtp status",
"show vlan",
+ "show running-config",
"write term"
);
$cisco_cmds=join(";",@commands);
@@ -1196,7 +1521,7 @@ if ($file) {
}
# determine password filtering mode
-if ($ENV{"FILTER_PWDS"} =~ /no/i) {
+if ($ENV{"FILTER_PWDS"} =~ /no/i) {
$filter_pwds = 0;
} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
$filter_pwds = 2;
@@ -1210,7 +1535,7 @@ ProcessHistory("COMMENTS","keysort","F0","!\n");
ProcessHistory("COMMENTS","keysort","G0","!\n");
TOP: while(<INPUT>) {
tr/\015//d;
- if (/\#\s?exit$/) {
+ if (/[>#]\s?exit$/) {
$clean_run=1;
last;
}
@@ -1222,7 +1547,11 @@ TOP: while(<INPUT>) {
}
while (/#\s*($cmds_regexp)\s*$/) {
$cmd = $1;
- if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; }
+ 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";
diff --git a/bin/rename.in b/bin/rename.in
deleted file mode 100755
index 8c3a111..0000000
--- a/bin/rename.in
+++ /dev/null
@@ -1,113 +0,0 @@
-#!@PERLV_PATH@
-'di';
-'ig00';
-#
-# Revision 3.0.1.2 90/08/09 03:17:57 lwall
-# patch19: added man page for relink and rename
-#
-
-if ($ARGV[0] eq '-i') {
- shift;
- if (open(TTYIN, "</dev/tty") && open(TTYOUT,">/dev/tty")) {
- $inspect++;
- select((select(TTYOUT),$|=1)[0]);
- }
-}
-($op = shift) || die "Usage: rename [-i] perlexpr [filenames]\n";
-if (!@ARGV) {
- @ARGV = <STDIN>;
- chop(@ARGV);
-}
-for (@ARGV) {
- unless (-e) {
- print STDERR "$0: $_: $!\n";
- $status = 1;
- next;
- }
- $was = $_;
- eval $op;
- die $@ if $@;
- if ($was ne $_) {
- if ($inspect && -e) {
- print TTYOUT "remove $_? ";
- next unless <TTYIN> =~ /^y/i;
- }
- unless (rename($was, $_)) {
- print STDERR "$0: can't rename $was to $_: $!\n";
- $status = 1;
- }
- }
-}
-exit $status;
-##############################################################################
-__END__
- # These next few lines are legal in both Perl and nroff.
-
-.00; # finish .ig
-
-'di \" finish diversion--previous line must be blank
-.nr nl 0-1 \" fake up transition to first page again
-.nr % 0 \" start at page 1
-';<<'.ex'; #__END__ ############# From here on it's a standard manual page ############
-.TH RENAME 1 "July 30, 1990"
-.AT 3
-.SH NAME
-rename \- renames multiple files
-.SH SYNOPSIS
-.B rename [-i] perlexpr [files]
-.SH DESCRIPTION
-.I Rename
-renames the filenames supplied according to the rule specified as the
-first argument.
-The argument is a Perl expression which is expected to modify the $_
-string in Perl for at least some of the filenames specified.
-If a given filename is not modified by the expression, it will not be
-renamed.
-If no filenames are given on the command line, filenames will be read
-via standard input.
-.PP
-The
-.B \-i
-flag will prompt to remove the old file first if it exists. This
-flag will be ignored if there is no tty.
-.PP
-For example, to rename all files matching *.bak to strip the extension,
-you might say
-.nf
-
- rename 's/\e.bak$//' *.bak
-
-.fi
-To translate uppercase names to lower, you'd use
-.nf
-
- rename 'y/A-Z/a-z/' *
-
-.fi
-To do the same thing but leave Makefiles unharmed:
-.nf
-
- rename 'y/A-Z/a-z/ unless /^Make/' *
-
-.fi
-To rename all the *.f files to *.BAD, you'd use
-.nf
-
- rename 's/\e.f$/.BAD/' *.f
-
-.SH ENVIRONMENT
-.fi
-No environment variables are used.
-.SH FILES
-.SH AUTHOR
-Larry Wall
-.SH "SEE ALSO"
-mv(1)
-.br
-perl(1)
-.SH DIAGNOSTICS
-If you give an invalid Perl expression you'll get a syntax error.
-.SH BUGS
-.I Rename
-does not check for the existence of target filenames, so use with care.
-.ex
diff --git a/bin/rivlogin.in b/bin/rivlogin.in
new file mode 100644
index 0000000..12554d5
--- /dev/null
+++ b/bin/rivlogin.in
@@ -0,0 +1,1005 @@
+#! @EXPECT_PATH@ --
+##
+## $Id: rivlogin.in,v 1.15 2004/01/11 05:39:15 heas Exp $
+##
+## 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.
+##
+#
+# The login expect scripts were based on Erik Sherk's gwtn, by permission.
+#
+# rivlogin - Riverstone (and Enterasys SSR) login
+#
+# Based upon rscmd (see nmops.org)
+# rscmd - Riverstone Networks Automated login
+# by Mike MacFaden, Kiran Addepalli
+# Riverstone Networks, 2000
+#
+# Returned to the RANCID crowd by andrew fort
+
+# Global vars section
+
+# program diagnostics
+set verbose 0
+set success 1
+set config 0
+
+# in seconds to wait for data back from device
+set timeout 10
+set tempfile "/tmp/rivlogin.[exec date]"
+
+# cli command prompt
+set my_prompt ">"
+set enable_prompt "\#"
+
+set default_user ""
+set output_file ""
+set conf_prompt "*\(config\)# "
+set logging 0
+set config_mode 0
+
+# Password file for routers to access
+set password_file $env(HOME)/.cloginrc
+
+# If no -c or -s specified, just automate router login ala rsh
+set do_command 0
+set do_script 0
+set log_user 0
+
+# The default CLI mode to login to is "enable" mode
+set enable 1
+
+# 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
+
+# cmd usage
+set usage "Error: Usage: $argv0 \[-noenable\] \
+\[-f cloginrc-file\] \[-c command\] \[-Evar=x\] \[-s script-file\] \
+\[-x command-file\] \[-t timeout\] \[-o output-file\] \
+router \[router...\]\n"
+
+# Procedures Section
+
+
+#
+# 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 }
+ }
+
+ 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.
+# NOTES: 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 $var
+ lappend $var $args
+}
+
+# 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 { } {
+
+ global env password_file read_password_file
+
+ if { [info exists read_password_file] } {
+ return 1
+ }
+
+ if { [info exists password_file] == 0 } {
+ set password_file $env(HOME)/.cloginrc
+ }
+
+ set read_password_file 1
+ file stat $password_file fileinfo
+
+ if { [expr ($fileinfo(mode) & 007)] != 0000 } {
+ puts "ERROR: $password_file must not be group or world readable and writable\n"
+ return 1
+ }
+
+ source $password_file
+}
+
+# pre: var is x, router is y
+# post: return routerr entry from database else null string
+
+proc find { var router } {
+
+ if {[ source_password_file ] == 0 } {
+ return {}
+ }
+
+ upvar $var list
+ if { [info exists list] } {
+ foreach line $list {
+ if { [string match [lindex $line 0] $router ] } {
+ return [lrange $line 1 end]
+ }
+ }
+ }
+ return {}
+}
+
+
+# pre: login completed ok
+# post: terminate login session by closing tcp connection
+
+proc auto_exit { } {
+
+ global telnet_id
+
+ if { $verbose == 1 } {
+ puts "DEBUG: auto_exit closing connection to pid $telnet_id\n"
+ }
+ close -i telnet_id
+}
+
+# perform login basic to a router
+# pre: args are valid, router is reachable via network
+# post: return 0 on successful login, else 1
+#
+# NOTE: a number of globals are setup: my_prompt, telnet_id are key
+# and paging of cli output is disabled
+
+proc login { router user userpswd passwd enapasswd } {
+
+ global login_array
+ global telnet_id
+ global expect_out
+ global spawn_id
+ global verbose
+ global config verbose my_prompt
+
+ if { $verbose == 1 } {
+ puts "DEBUG: login router = $router"
+ puts "DEBUG: login username = $user"
+ puts "DEBUG: login userpasswd = $userpswd"
+ puts "DEBUG: login passwd = $passwd"
+ puts "DEBUG: login enapasswd = $enapasswd"
+ }
+
+ spawn -noecho telnet $router
+ set telnet_id $spawn_id
+
+ if { $telnet_id == 0 } {
+ puts "ERROR: login: spawn telnet session failed.\n"
+ return 1
+ }
+
+ # wait for initial 'Press RETURN to...' response
+ sleep 0.3
+
+ expect "*"
+ send "\r"
+
+ # If password fails 3 times then expect again
+ set pass_attempt 0
+
+ expect {
+
+ -re ".*> " { }
+
+ "Password:" {
+ incr pass_attempt
+ send "$passwd\r"
+ exp_continue
+ }
+
+ "Username: " {
+
+ set pattempt 0
+
+ send "$user\r"
+ expect {
+
+ "Password: " {
+
+ incr pattempt
+ if {$pattempt == 1} {
+ send "$userpswd\r";
+ } else {
+ send "$enapasswd\r";
+ }
+ exp_continue
+ }
+
+ -re ".*> " { exp_continue;}
+ }
+ }
+
+ "%TELNETD-W-BADPASSWD" {
+ puts "ERROR: bad userid or password to telnet."
+ return 1
+ }
+ "%CONS-W-AUTH_PASSWD" {
+ exp_continue
+ }
+
+ "% Authentication failed." {
+ puts "ERROR: bad userid or password to telnet."
+ return 1
+ }
+
+
+ "Authentication Failed:" {
+ puts "ERROR: bad userid or password to radius/tacacs+"
+ return 1
+ }
+
+ "Connection closed *" {
+ if {$pass_attempt == 3} {
+ puts "ERROR: Maximum attempts for password reached. Check password. Exiting.";
+ puts $expect_out(0,string);
+ return 1
+ }
+ }
+
+ timeout {
+ puts "ERROR: Timeout on login. Exiting.";
+ return 1
+ }
+
+ eof {
+ puts "ERROR: device closed telnet connection during login"
+ return 1
+ }
+ }
+
+ # save my_prompt for later use
+ send "\r"
+ expect -re ".*> "
+ set abc "$expect_out(buffer)"
+ set my_prompt "[lindex $abc 0]"
+ regexp {(.*[^>])} $my_prompt my
+
+ return 0;
+}
+
+
+# pre: login completed ok
+# post: turn off paging of commands
+
+proc disable_cli_paging { } {
+ global my_prompt
+
+ send "cli set terminal rows 0\r"
+
+ expect {
+ "$my_prompt" {return 0 }
+ }
+ return 1
+}
+
+# pre: login returned 0, prompt at top level
+# post: turn off command completion return 0
+# on error, return 1
+
+proc disable_cmd_autocomplete { } {
+ global my_prompt
+
+ send "cli set command completion off\r"
+ expect {
+
+ $my_prompt { }
+
+ timeout {
+ puts "ERROR:disable_cmd_autocomplete(TIMEOUT)";
+ return 0;
+ }
+
+ }
+
+ return 0
+}
+
+# pre: login returned 0, do_enable returned 0, cli is in enable or config mode
+# post: issues logout cli to device, returns 0
+
+proc logout { prompt } {
+ global config_mode enable_prompt
+
+ # in case of not being at root cmd...
+ # verify top level prompt state, move to it if necessary
+
+ if { $config_mode == 1 } {
+
+ send "exit\r"
+
+ expect {
+ "Do you want*" {
+ send "no\r"
+ }
+
+ "$enable_prompt" { }
+
+ timeout { puts "ERROR: logout: timeout from config mode\n" }
+ eof { puts "ERROR: device dropped connection\n" }
+ }
+ set config_mode 0
+ }
+
+ send "logout\r"
+ expect {
+
+ "Are you sure*" {
+ send "yes\r"
+ return 0
+ }
+ }
+}
+
+# pre: current mode allows transition to enable mode
+# post: enable mode entered, my_prompt updated, return 0 else 1
+
+proc do_enable { enauser enapasswd userpswd } {
+ global expect_out verbose
+ global my_prompt enable_prompt
+ set enable_prompt [ string trimright $my_prompt ">" ]
+ set enable_prompt $enable_prompt\#
+
+ if { $verbose == 1 } {
+ puts "DEBUG: do_enable: my_prompt = $my_prompt ena_prompt = $enable_prompt"
+ }
+
+ send "enable\r"
+
+ expect {
+ Username: { send "$enauser\r"; exp_continue }
+ Password: { send "$userpswd\r"; exp_continue }
+
+ "$my_prompt" {
+ puts "ERROR: do_enable failed to gain enable mode."
+ return 1
+ }
+
+ "CONS-W-AUTH_PASSWD" { send "$enapasswd\r"; }
+
+ "$enable_prompt " { }
+ "%SYS-W-NOPASSWD*" { }
+
+ "Authentication Failed: Access Denied" {
+ puts "ERROR: Bad user or password for enable mode."
+ return 1
+ }
+ }
+
+ set my_prompt $enable_prompt
+ return 0
+}
+
+# pre: current mode allows transition to enable mode
+# post: enable mode entered, my_prompt updated, return 0 else 1
+
+proc do_configure { } {
+ global expect_out verbose config_mode
+ global my_prompt
+ set config_prompt [ string trimright $my_prompt "\#" ]
+ set config_prompt $config_prompt\(config\)\#
+
+ if { $verbose == 1 } {
+ puts "DEBUG: do_config: my_prompt = $my_prompt cfg_prompt = $config_prompt"
+ }
+
+ send "configure\r"
+ expect {
+ "$config_prompt " { }
+ "$my_prompt" {
+ }
+
+ eof { return 1}
+ timeout { return 1}
+ }
+
+ set config_mode 1
+ set my_prompt $config_prompt
+ return 0
+}
+
+# track sent/received from device to output_file
+# pre: outut_file is valid filename w/write access
+# post: logfile open, global var logging == 1, return 0 , else 1
+
+proc start_logfile { output_file } {
+ global logging
+
+ if { [ string length $output_file ] != 0 } {
+ set rc [ catch {
+ log_file -noappend $output_file
+ } errMsg ]
+
+ if { $rc != 0 } {
+ puts "ERROR: open file $output_file for write access failed. $errMsg\n"
+ return 1
+ }
+ set logging 1
+ }
+
+ return 0
+}
+
+proc run_commands { prompt cmdstring } {
+ global sendstring
+
+ set commands [split $cmdstring \;]
+ set num_commands [llength $cmdstring]
+
+ for {set i 0} {$i < $num_commands} { incr i} {
+ regsub -- {[ ]*([^\.]*)} [subst -nocommands [lindex $commands $i]] {\1} sendstring
+
+ if {[ run_single_command $prompt $sendstring ] == 1} {
+ puts "ERROR: command '$sendstring' not processed by device. Check previous error messages."
+ return 1
+ }
+ }
+ return 0
+}
+
+
+# Run commands given on the command line
+# pre: prompt is current system cli prompt, cmdstring is command to execute
+# post: return 0 on success else 1
+# NOTE: output from router ends up in output_file if specified
+# expect internal input buffer is reset to "" after each command
+
+proc run_single_command { prompt cmdstring } {
+ global verbose
+ set rc 0
+ set seen_prompt 0
+ set seen_timeout 0
+ set need_ays 0
+ set delay 0
+
+ if {$verbose == 1} {
+ puts "DEBUG: run_commands: prompt=$prompt \"$cmdstring\" "
+ }
+
+ # ays == "are you sure" - must send back yes
+ if { [string compare $cmdstring "save startup" ] == 0 } {
+ set need_ays 1
+ set delay 1
+ if {$verbose == 1} {
+ puts "DEBUG: save startup cmd seen, set need_ays = 1"
+ }
+ }
+
+ # TODO: add case for copy command to startup, also prompts for ok
+
+ # TODO: if we see config command: system set name note it
+ # if we see a save active, then update system prompts as well
+
+ send "$cmdstring\r"
+
+ if { $delay == 1} {
+ sleep 1
+ }
+
+ expect {
+
+ "%CLI-E-IVCMD*" {
+ puts "ERROR: run_commands(command rejected by device)\n"
+ set rc 1
+ }
+
+ "%CLI-E-FACUNKNWN*" {
+ puts "ERROR: run_commands(command rejected by device)\n"
+ set rc 1
+ }
+
+ "%SYS-I-ADDFAILED*" {
+ puts "ERROR: run_commands(command rejected by device)\n"
+ set rc 1
+ }
+ "%TFTP-E-REMOTE,*" {
+ puts "ERROR: run_commands(command rejected by device)\n"
+ set rc 1
+ }
+
+ "%SYS-E-PRIMARY_NO_SUCH_IMAGE*" {
+ puts "ERROR: run_commands(command rejected by device)\n"
+ set rc 1
+ }
+
+ "want to overwrite " {
+ send "yes\r"
+ if {$verbose == 1} {
+ puts "DEBUG: got overwrite question, set need_ays to 0"
+ }
+ set need_ays 0
+ }
+
+
+ "%CONFIG-E-DUPLICATE,*" {
+ }
+
+ "$prompt" {
+ if { $seen_prompt == 0 } {
+ set seen_prompt 1
+ }
+
+ if {$verbose == 1} {
+ puts "DEBUG: saw double prompt, exiting expect loop\n"
+ }
+
+ if { $need_ays == 1 } {
+ exp_continue
+ }
+ }
+
+ -re ".* More: m,<space> --- Quit: q --- One line: <return> ---" {
+ send "q"
+ exp_continue
+ }
+
+
+ timeout {
+ if {$verbose == 1} {
+ puts "DEBUG: timeout occured for the $seen_time time\n"
+ }
+
+ if { $seen_timeout == 0 } {
+ set seen_timeout 1
+ send "\r\r"
+ exp_continue
+ }
+
+ puts "ERROR:run_commands(TIMEOUT)"
+ set rc 1
+ }
+
+ eof {
+ puts "ERROR:run_commands(connection closed by device)\n"
+ set rc 1
+ }
+
+ "\n" { exp_continue }
+ }
+
+ # clear input buffer of any remaining data
+ expect "*"
+ return $rc
+}
+
+
+# pre: RSTONE_USER env var is set
+# post: update global "default_user" to this string
+
+proc init_userid { } {
+ global default_user
+
+ if {[ info exists env(RSTONE_USER) ] } {
+ set default_user $env(RSTONE_USER)
+ } 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.
+ regexp {\(([^)]*)} [exec id] junk default_user
+ }
+}
+
+proc source_script_file { filename } {
+ global my_prompt
+
+ expect -re "$my_prompt" {}
+
+ source $filename
+
+}
+
+
+# pre: login completed ok, filename contains set of cli commands one per line
+# post: each command is extracted from filename and sent to device
+# return 0 on success, return 1 on error
+# NOTE: for scripts that begin with "configure", change the mode to configure
+# before executing the following commands
+
+proc process_script_file { filename } {
+
+ global my_prompt verbose
+ set rc 0
+ set ifile ""
+
+ set rc [ catch {
+ set ifile [ open $filename r]
+ } errMsg ]
+
+ if { $rc != 0 } {
+ puts "ERROR: process_script_file: open script file $filename for read access failed. $errMsg\n"
+ return 1
+ }
+
+ set line_cnt 0
+
+ while { [eof $ifile] != 1 } {
+
+ set bytes [ gets $ifile cmd ]
+ incr line_cnt
+
+ if { $bytes < 0 } {
+ break
+ } elseif { $bytes == 0 } {
+ continue
+ }
+
+ if { $verbose == 1 } {
+ puts "DEBUG: line:$line_cnt cmd = $cmd\n"
+ }
+
+ # skip comments in script files
+ if { [regexp "^\#" $cmd] != 1 } {
+
+ # puts "$cmd rc = [string compare $cmd "configure" ]\n"
+
+ if { [string compare $cmd "configure" ] == 0 } {
+
+ do_configure
+
+ } else {
+ if {[ run_commands $my_prompt $cmd ] == 1} {
+ puts "ERROR: line $line_cnt in $filename not processed by device. Check previous error msgs."
+ set rc 1
+ break
+ }
+ }
+ }
+ }
+
+ close $ifile
+ return $rc
+}
+
+
+
+# pre: filename is valid file
+# post: remove extended ascii sequences and other cruft
+# and prepend a header: rscmd: ip-addr : date
+# TODO: should watch all file commands more closely
+
+proc strip_log { filename router } {
+
+ global tempfile
+
+ set rc [ catch {
+ set ifile [ open $filename r]
+ } errMsg ]
+
+ if { $rc != 0 } {
+ puts "ERROR: strip_log: open script file $filename for read access failed. $errMsg\n"
+ return 1
+ }
+ set rc [ catch {
+ set ofile [ open $tempfile w]
+ } errMsg ]
+
+ if { $rc != 0 } {
+ puts "ERROR: strip_log: open temp file $tempfile for write access failed. $errMsg\n"
+ return 1
+ }
+
+ set nl 0
+
+ puts $ofile "rscmd: $router : [exec date]"
+
+ while { [eof $ifile] != 1 } {
+
+ set bytes [ gets $ifile cmd ]
+ if { $bytes <= 0 } {
+ break
+ }
+ incr nl
+ if { $nl <= 2 } {
+ continue
+ }
+
+ regsub -all -- "\r" $cmd "" newcmd
+ puts $ofile $newcmd
+ }
+
+ close $ifile
+ close $ofile
+ set rc 0
+ file copy -force $tempfile $filename
+ file delete $tempfile
+ return $rc
+}
+
+#
+# main section
+#
+
+
+if { $verbose == 1 } {
+ puts "\n\nrscmd: Version 1.1 started on [exec date]"
+ puts "[exec uname -a]"
+ puts "Expect Version: [exp_version]\n"
+}
+
+# send input like in a fast and consistent human style
+set send_human {.1 .3 1 .05 2}
+
+# initialize default_user variable
+init_userid
+
+# Parse Command Line
+
+for {set idx 0} {$idx < $argc} {incr idx} {
+
+ set arg [lindex $argv $idx]
+
+ switch -glob -- $arg {
+
+ -c* -
+ -C* {
+ if {! [ regexp .\[cC\](.+) $arg ignore command]} {
+ incr idx
+ set command [ lindex $argv $idx ]
+ }
+ set do_command 1
+ # Environment variable to pass to -s scripts
+ } -E*
+ {
+ if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ set E$varname $varvalue
+ } else {
+ send_user "Error: invalid format for -E in $arg\n"
+ exit 1
+ }
+ # Expect script to run
+ } -s* -
+ -S* {
+ if {! [ regexp .\[sS\](.+) $arg ignore sfile]} {
+ incr idx
+ set sfile [ lindex $argv $idx ]
+ }
+
+ if { ! [ file exists $sfile ] } {
+ puts "ERROR: invalid argument script file \"$sfile\" does not exist.\n"
+ exit 1
+ }
+ if { ! [ file readable $sfile ] } {
+ puts "ERROR: invalid argument script file \"$sfile\" permissions disallow read access.\n"
+ exit 1
+ }
+
+ set do_script 1
+ # Command file
+ } -x* -
+ -X {
+ if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} {
+ incr idx
+ set cmd_file [ lindex $argv $idx ]
+ }
+ 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
+ } -f* -
+ -F* {
+ if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
+ incr idx
+ set password_file [ lindex $argv $idx ]
+ }
+
+ } -o* -
+ -O* {
+ if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
+ incr idx
+ set output_file [ lindex $argv $idx ]
+ if { $verbose == 1 } {
+ puts "DEBUG: output file: $output_file"
+ }
+ }
+
+ } -t* -
+ -T* {
+ incr idx
+ set timeout [ lindex $argv $idx ]
+
+ } -noenable {
+ set enable 0
+ } -* {
+ puts "ERROR:unkown argument passed: $arg\n"
+ puts $usage
+ exit 1
+
+ } default {
+ break
+ }
+ }
+}
+
+# Verify at least one router is specified
+#
+if { $idx == $argc } {
+ puts "\n$usage"
+ exit 1
+}
+
+# main loop
+
+foreach router [lrange $argv $idx end] {
+set router [string tolower $router]
+
+# Figure out passwords
+if {$verbose == 1} {
+ puts "DEBUG: do_passwd = $do_passwd\n"
+ puts "DEBUG: do_enablepasswd = $do_enapasswd\n"
+}
+
+if { $do_passwd || $do_enapasswd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ puts "ERROR: - no password for $router in $password_file.\n"
+ exit 1
+ }
+ if { $do_enapasswd && [llength $pswd] < 2 } {
+ puts "ERROR: no enable password found for $router in $password_file."
+ exit 1
+ }
+
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
+}
+
+
+# Figure out user to login with if necessary
+
+if {[info exists username]} {
+ # command line username
+ set user $username
+} else {
+ set user [join [find user $router] ""]
+ if { "$user" == "" } { set user $default_user }
+}
+
+# Figure out username's 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 $user }
+}
+
+# Login to the router, set my_prompt to router's cmd prompt
+
+if {[login $router $user $userpswd $passwd $enapasswd ]} {
+ if { $verbose == 1 } {
+ puts "DEBUG: login to $router failed\n"
+ }
+ exit 1
+}
+
+if {$verbose == 1 } {
+ puts "DEBUG: login completed ok\n"
+}
+
+if { $enable == 1 } {
+
+ if { [do_enable $enauser $enapasswd $userpswd] == 1} {
+ if { $verbose == 1 } {
+ puts "DEBUG: switch to enable mode on $router failed\n"
+ }
+ exit 1
+ }
+}
+
+# run in one of three modes
+
+if { $do_command } {
+
+ disable_cmd_autocomplete
+ disable_cli_paging
+
+ if {[ start_logfile $output_file] != 0 } {
+ exit 1
+ }
+
+ if {[ run_commands $my_prompt $command ]} {
+
+ log_file
+ exit 1
+
+ } else {
+
+ logout $my_prompt
+
+ }
+
+} elseif { $do_script } {
+
+ disable_cmd_autocomplete
+ disable_cli_paging
+
+ if {[ start_logfile $output_file] != 0 } {
+ exit 1
+ }
+
+ #if { [process_script_file $sfile] == 1} {
+# puts "DEBUG: logfile $output_file closed on error\n"
+# logout $my_prompt
+# exit 1
+# }
+
+ source_script_file $sfile
+
+ logout $my_prompt
+
+} else {
+
+ label $router
+ log_user 1
+
+ if {[ start_logfile $output_file] != 0 } {
+ exit 1
+ }
+ interact
+ log_file
+}
+
+if { $verbose == 1 } {
+ puts "DEBUG: exiting normally.\n"
+}
+
+if { $logging == 1} {
+ log_file
+ strip_log $output_file $router
+}
+}
+
+# puts "\n"
+exit 0
diff --git a/bin/rivrancid.in b/bin/rivrancid.in
new file mode 100644
index 0000000..8b9ae03
--- /dev/null
+++ b/bin/rivrancid.in
@@ -0,0 +1,344 @@
+#! @PERLV_PATH@
+##
+## $Id: rivrancid.in,v 1.9 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# Amazingly hacked version of Hank's rancid - this one tries to
+# deal with Cabletron, Riverstone and Enterasys routers/switches
+#
+# 10/23/2002 -- Initial changes for Riverstone/Cabletron support
+# Jim Meehan -- jmeehan@vpizza.org
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rivrancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # flogin timeout in seconds
+
+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 "system show version"
+sub ShowVersion {
+ my($slot);
+
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ next if /^\s*$/;
+ last if(/^$prompt/);
+
+ ProcessHistory("VERSION","","","!SW: $_");
+ }
+ ProcessHistory("VERSION","","","!\n");
+ return(0);
+}
+
+# This routine parses "system show hardware"
+sub ShowHardware {
+ print STDERR " In ShowHardware: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ ProcessHistory("HARDWARE","","","!HW: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return(0);
+}
+
+# This routine parses "system show uptime"
+sub ShowUptime {
+ print STDERR " In ShowUptime: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if /^\s*$/;
+ next if /System up/;
+ ProcessHistory("UPTIME","","","!UPTIME: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return;
+}
+
+# This routine processes a "system show active"
+sub ShowActive {
+ print STDERR " In ShowActive: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+
+ # Remove leading whitespace and/or line numbers
+ s/^\s*(\d+\D: )*//;
+
+ # Riverstone/Cabletron doesn't have an "end" line, so
+ # we need to set $clean_run here
+ if (/^$prompt/) {
+ $clean_run = 1;
+ last;
+ }
+
+ next if (/Running system configuration/);
+
+ # filter out any RCS/CVS tags to avoid confusing local CVS storage
+ s/\$(Revision|Id):/ $1:/;
+
+ if (/^(.*hashed-password \S+)/ && $filter_pwds == 2) {
+ ProcessHistory("","","","! $1 <removed>\n");
+ next;
+ }
+
+ if (/^(snmp set community )\S+/ && defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("","","","! $1<removed>$'");
+ next;
+ }
+
+ ProcessHistory("","","","$_");
+ }
+ return;
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'system show uptime' => "ShowUptime",
+ 'system show version' => "ShowVersion",
+ 'system show hardware' => "ShowHardware",
+ 'system show active-config' => "ShowActive"
+);
+
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important. pita
+
+@commands=(
+ "system show uptime",
+ "system show version",
+ "system show hardware",
+ "system show active-config"
+);
+
+$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 rivlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing rivlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "rivlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "rivlogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "rivlogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"rivlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "rivlogin 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: riverstone\n!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ last if ($clean_run);
+ if (/^Error:/) {
+ print STDOUT ("$host rivlogin error: $_");
+ print STDERR ("$host rivlogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+
+ $kradcount++;
+
+ while (/\033(\[\?25l)/) {
+ s/\033\[\?25l//g;
+ #print STDERR "krad $1\n";
+ #print STDERR $_;
+ #print STDERR $kradcount;
+ next;
+ }
+
+
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]+#)/)[0];
+ $prompt =~ s/([}{)(\\])/\\$1/g;
+ }
+ 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) {
+ 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) {
+ 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/rrancid.in b/bin/rrancid.in
index f242ec4..7674452 100755..100644
--- a/bin/rrancid.in
+++ b/bin/rrancid.in
@@ -1,28 +1,32 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
-## hacked version of Hank's rancid - this one tries to deal with redbacks.
+## $Id: rrancid.in,v 1.18 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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.
##
#
+# hacked version of Hank's rancid - this one tries to deal with redbacks.
+#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -353,7 +357,8 @@ while(<INPUT>) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^#]*#)/)[0];
- $prompt =~ s/([][])/\\$1/g; # quote the damn []'s
+ $prompt =~ s/([][}{)(\\])/\\$1/g; # quote the damn []'s
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
diff --git a/bin/tntlogin.in b/bin/tntlogin.in
new file mode 100644
index 0000000..021f0d2
--- /dev/null
+++ b/bin/tntlogin.in
@@ -0,0 +1,528 @@
+#! @EXPECT_PATH@ --
+##
+## $Id: tntlogin.in,v 1.11 2004/01/11 05:39:15 heas Exp $
+##
+## 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.
+##
+#
+# The login expect scripts were based on Erik Sherk's gwtn, by permission.
+#
+# Modified by P B Matthews.
+
+# Usage line
+set usage "Usage: $argv0 \[-c command\] \
+\[-Evar=x\] \[-f cloginrc-file\] \
+\[-s script-file\] \[-t timeout\] \[-u username\] \
+\[-v vty-password\] \[-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 enable 0
+# The default is that you login non-enabled (tacacs can have you login already
+# enabled)
+set avautoenable 1
+# 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
+
+# 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
+ } -v* -
+ -v* {
+ if {! [ regexp .\[vV\](.+) $arg ignore passwd]} {
+ incr i
+ set passwd [ lindex $argv $i ]
+ }
+ set do_passwd 0
+ # Enable Username
+ } -w* -
+ -W* {
+ # ignore -w
+ # Environment variable to pass to -s scripts
+ } -E*
+ {
+ if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ incr i
+ set E$varname $varvalue
+ } else {
+ send_user "\nError: invalid format for -E in $arg\n"
+ exit 1
+ }
+ # Enable Password
+ } -e*
+ {
+ # ignore -e
+ # 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 {
+ # ignore -noenable
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ # ignore -autoenable
+ } -* {
+ 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 prompt cmethod cyphertype } {
+ global spawn_id in_proc do_command do_script
+ global u_prompt p_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] {
+ 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 compare $prog "ssh"] {
+ if [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: $sshcmd failed: $reason\n"
+ exit 1
+ }
+ } 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
+ }
+ }
+ }
+
+ expect {
+ "Connection refused" {
+ close; wait
+ sleep 0.3
+ expect eof
+ send_user "\nError: Connection Refused\n"; wait; return 1
+ } eof { send_user "\nError: Couldn't login\n"; wait; return 1
+ } "Unknown host\r\n" {
+ expect eof
+ send_user "\nError: Unknown host\n"; wait; return 1
+ } "Host is unreachable" {
+ expect eof
+ send_user "\nError: Host Unreachable!\n"; wait; return 1
+ } "No address associated with name" {
+ expect eof
+ send_user "\nError: Unknown host\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 "$u_prompt" {
+ send "$user\r"
+ set uprompt_seen 1
+ exp_continue
+ }
+ -re "$p_prompt" {
+ sleep 1
+ if {$uprompt_seen == 1} {
+ send "$userpswd\r"
+ } else {
+ send "$passwd\r"
+ }
+ exp_continue
+ }
+ -re "^Confirm seeing above note" {
+ send "y\r"
+ exp_continue
+ }
+ "Password incorrect" { send_user "\nError: Check your password for $router\n";
+ catch {close}; wait; return 1 }
+ -re "$prompt" { break; }
+ denied { send_user "\nError: Check your passwd for $router\n"
+ catch {close}; wait; return 1
+ }
+ "\r\n" { exp_continue; }
+ }
+ }
+ 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 "lines 0\r"
+ 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"
+ expect {
+ -re "^\[^\n\r]*$reprompt" {}
+ -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue }
+ -re "\[\n\r]+" { exp_continue }
+ }
+ }
+
+ send "quit\r"
+# expect {
+# -re "^WARNING: the current user has insufficient rights to view password fields. A configuration saved under this circumstance should not be used to restore profiles containing passwords. Save anyway? [y/n]"
+# {
+# send "y\r"
+ exp_continue
+ }
+ "\n" { exp_continue }
+ "\[^\n\r *]*Session terminated" { return 0 }
+ timeout { 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.
+ set prompt "admin>"
+ # TNT only "enables" based on the password used at login time
+ set autoenable 1
+ set enable 0
+
+ # Figure out passwords
+ if { $do_passwd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ send_user "\nError - no password for $router in $password_file.\n"
+ continue
+ }
+ set passwd [join [lindex $pswd 0] ""]
+ }
+
+ # 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 prompts
+ set u_prompt [find userprompt $router]
+ if { "$u_prompt" == "" } {
+ set u_prompt "(User|Username|login| Login):"
+ } else {
+ set u_prompt [join [lindex $u_prompt 0] ""]
+ }
+
+ set p_prompt [find passprompt $router]
+ if { "$p_prompt" == "" } {
+ set p_prompt "\[Pp]assword:"
+ } else {
+ set p_prompt [join [lindex $p_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 $prompt $cmethod $cyphertype]} {
+ continue
+ }
+
+ if { $do_command } {
+ if {[run_commands $prompt $command]} {
+ continue
+ }
+ } elseif { $do_script } {
+# send "lines 0\r"
+ expect -re $prompt {}
+ source $sfile
+ send "y\r"
+ close
+ } else {
+ label $router
+ log_user 1
+ interact
+ }
+
+ # End of for each router
+ wait
+ sleep 0.3
+}
+exit 0
diff --git a/bin/tntrancid.in b/bin/tntrancid.in
new file mode 100644
index 0000000..88520fd
--- /dev/null
+++ b/bin/tntrancid.in
@@ -0,0 +1,292 @@
+#! @PERLV_PATH@
+##
+## $Id: tntrancid.in,v 1.8 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# Modified by Paul B Matthews & Richard Vander Reyden.
+# I'm suprised it still works....
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: tntrancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # tntlogin timeout in seconds
+$prompt = "admin> ";
+$always_y = "y"; # cause its a pain.
+
+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";
+ print eval "$always_y \%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 processes a "save con"
+sub SaveConf {
+ print STDERR " In SaveConf: $_" if ($debug);
+ my($comment) = 1; # strip extra comments, esp to preserve chassis type
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+# next if(/^\s*$/);
+
+### s/^\s*$/;/;
+
+# Leave software revision, but strip out saved date,
+# which causes rancid to think it changes each poll
+
+ if (/^; saved from /) {
+ ProcessHistory("","","","$_");
+ next;
+ }
+ /^; saved / && next;
+
+ # catch anything that wasnt match above.
+ ProcessHistory("","","","$_");
+ # end of config
+# if (/^# End of configuration file/i) {
+ if (/; profiles saved$/) {
+ printf STDERR " End SaveConf: $_" if ($debug);
+ $found_end = 1;
+ print STDOUT "$found_end = found_end within test\n";
+ return(1);
+ }
+ $found_end = 1;
+#### print STDOUT "$found_end = found_end at test\n";
+ }
+ $found_end = 1;
+ return(0);
+}
+$found_end = 1;
+print STDOUT "$found_end = found_end at end test\n";
+
+
+
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'save con' => "SaveConf"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and write term last). pita
+@commands=(
+ "save con"
+);
+$tnt_cmds=join(";",@commands);
+$cmds_regexp=join("|",@commands);
+$tnt_cmds="save con";
+
+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 tntlogin -t $timeo -c\"$tnt_cmds\" $host\n" if ($debug);
+ print STDOUT "executing tntlogin -t $timeo -c\"$tnt_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "tntlogin -t $timeo -c \"$tnt_cmds\" $host </dev/null > $host.raw 2>&1" || die "tntlogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "tntlogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"tntlogin -t $timeo -c \"$tnt_cmds\" $host </dev/null |") || die "tntlogin 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: tnt\n#\n");
+ProcessHistory("COMMENTS","keysort","X0",";\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+
+ if (/^Error:/) {
+ print STDOUT ("$host tntlogin error: $_");
+ print STDERR ("$host tntlogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/$prompt\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]+#)/)[0];
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
+ $prompt =~ s/:(\d+ ?)#/:\\d+ ?#/;
+ 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) {
+ printf STDERR "rval = -1\n" if ($debug);
+ $clean_run = 0;
+ last TOP;
+ }
+ }
+}
+print STDOUT "Done $logincmd: $_\n" if ($log);
+# Flush History
+ProcessHistory("","","","");
+# Cleanup
+$clean_run = 1;
+print STDOUT "$clean_run - clean\n";
+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 06ff30b..4aeb1d3 100755..100644
--- a/bin/xrancid.in
+++ b/bin/xrancid.in
@@ -1,19 +1,22 @@
-#!@PERLV_PATH@
+#! @PERLV_PATH@
##
+## $Id: xrancid.in,v 1.32 2004/01/11 03:49:13 heas Exp $
##
-## Copyright (C) 1997-2001 by Henry Kilmer.
+## 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 copyright notice is
-## preserved intact on all copies and modified copies.
+## 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
+## 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
@@ -21,7 +24,7 @@
# usage: rancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
-getopts('dflm');
+getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
@@ -272,10 +275,14 @@ sub WriteTerm {
tr/\015//d;
last if(/^$prompt/);
next if(/^\s*$/);
+ return(0) if(/^syntax error at token /i);
# the pager can not be disabled per-session on the PIX
s/^<-+ More -+>\s*//;
+ return(0) if ($found_end);
s/^\s*$/#/;
+ next if (/full detail configuration/i);
+
# filter extra comments and lead comments in config so we can preserve
# the chassis type at the top of muched o/p before the process history
# key changes.
@@ -291,7 +298,7 @@ sub WriteTerm {
# Dog gone Cool matches to process the rest of the config
# some chassis report their chassis type in show diag...oh, but
- # other noooo. grab it here, if available. so, nothing else
+ # others do not. grab it here, if available. so, nothing else
# can change the keysort key until this is grabbed. sigh.
/# (\S+) configuration generated/i &&
ProcessHistory("COMMENTS","keysort","A0","#Chassis type: $1\n") &&
@@ -301,11 +308,11 @@ sub WriteTerm {
/# software version/i && next;
if (/((create|configure) account \S+ \S+) / && $filter_pwds >= 2) {
- ProcessHistory("","","","# $1 <key removed>\n");
+ ProcessHistory("COMMENTS","keysort","H0","# $1 <key removed>\n");
next;
}
if (/configure ssh2 key/ && $filter_pwds >= 1) {
- ProcessHistory("","","","# $_# <key removed>\n");
+ ProcessHistory("COMMENTS","keysort","H0","# $_# <key removed>\n");
while (<INPUT>) {
if (/^(#|enable|conf|disable|unconf)/) {
tr/\015//d;
@@ -317,7 +324,7 @@ sub WriteTerm {
# filter out any RCS/CVS tags to avoid confusing local CVS storage
s/\$(Revision|Id):/ $1:/;
if (/^((config|configure) bgp (neighbor|peer-group) \S+ password encrypted)/i && $filter_pwds >= 1) {
- ProcessHistory("","","","# $1 <removed>\n");
+ ProcessHistory("COMMENTS","keysort","H0","# $1 <removed>\n");
next;
}
@@ -346,17 +353,17 @@ sub WriteTerm {
}
# order/prune tacacs/radius server statements
if (/^(configure radius (primary|secondary) (tacacs-server|radius-server) shared-secret encrypted)/ && $filter_pwds >= 1) {
- ProcessHistory("","","","# $1 <removed>\n");
+ ProcessHistory("COMMENTS","keysort","H0","# $1 <removed>\n");
next;
}
# catch anything that wasnt match above.
- ProcessHistory("","","","$_");
+ ProcessHistory("COMMENTS","keysort","H0","$_");
# end of config
if (/^# End of configuration file/i) {
printf STDERR " End WriteTerm: $_" if ($debug);
$found_end = 1;
- return(1);
+ return(0);
}
}
return(0);
@@ -367,12 +374,13 @@ sub DoNothing {print STDOUT;}
# Main
%commands=(
- 'show version' => "ShowVersion",
- 'show memory' => "ShowMemory",
- 'show diagnostics' => "ShowDiag",
- 'show switch' => "ShowSwitch",
- 'show slot' => "ShowSlot",
- 'show configuration' => "WriteTerm"
+ 'show version' => "ShowVersion",
+ 'show memory' => "ShowMemory",
+ 'show diagnostics' => "ShowDiag",
+ 'show switch' => "ShowSwitch",
+ 'show slot' => "ShowSlot",
+ 'show configuration detail' => "WriteTerm",
+ 'show configuration' => "WriteTerm"
);
# keys() doesnt return things in the order entered and the order of the
# cmds is important (show version first and write term last). pita
@@ -382,6 +390,7 @@ sub DoNothing {print STDOUT;}
"show diagnostics",
"show switch",
"show slot",
+ "show configuration detail",
"show configuration"
);
$cisco_cmds=join(";",@commands);
@@ -397,13 +406,13 @@ if ($file) {
print STDOUT "opening file $host\n" if ($log);
open(INPUT,"<$host") || die "open failed for $host: $!\n";
} else {
- print STDERR "executing clogin -t $timeo -autoenable -c\"$cisco_cmds\" $host\n" if ($debug);
- print STDOUT "executing clogin -t $timeo -autoenable -c\"$cisco_cmds\" $host\n" if ($log);
+ 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 -autoenable -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!\n";
+ 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 -autoenable -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n";
+ open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n";
}
}
@@ -422,13 +431,14 @@ ProcessHistory("COMMENTS","keysort","C0","#\n"); # power supply info
ProcessHistory("COMMENTS","keysort","D0","#\n"); # image name
ProcessHistory("COMMENTS","keysort","E0","#\n"); # h/w info
ProcessHistory("COMMENTS","keysort","F0","#\n"); # slot info
+ProcessHistory("COMMENTS","keysort","H0","#\n"); # config
ProcessHistory("COMMENTS","keysort","X0","#\n");
TOP: while(<INPUT>) {
tr/\015//d;
# note: this match sucks rocks, but currently the extreme bits are
# 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 closed)/ && $found_end) {
+ if (/$prompt\s?(quit|exit|Connection( to \S+)? closed)/ && $found_end) {
$clean_run=1;
last;
}
@@ -442,8 +452,10 @@ TOP: while(<INPUT>) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^#]+#)/)[0];
+ $prompt =~ s/([][}{)(\\])/\\$1/g;
$prompt =~ s/:(\d+ ?)#/:\\d+ ?#/;
- print STDERR ("PROMPT MATCH:$prompt\n") if ($debug);
+ $prompt =~ s/\*/\\\*/;
+ print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
diff --git a/bin/zrancid.in b/bin/zrancid.in
new file mode 100755
index 0000000..a969553
--- /dev/null
+++ b/bin/zrancid.in
@@ -0,0 +1,411 @@
+#! @PERLV_PATH@
+##
+## $Id: zrancid.in,v 1.8 2004/01/11 03:49:13 heas Exp $
+##
+## 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.
+##
+#
+# This version of rancid tries to deal with zebra s/w.
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dfl');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # clogin timeout in seconds
+
+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;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ return(-1) if (/command authorization failed/i);
+
+ ProcessHistory("COMMENTS","keysort","B0", "!$_") && next;
+
+ }
+ return(0);
+}
+
+# This routine processes a "write term"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ return(-1) if (/command authorization failed/i);
+
+ /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ # skip the crap
+ if (/^(##+$|(Building|Current) configuration)/i) {
+ while (<INPUT>) {
+ next if (/^Current configuration\s*:/i);
+ next if (/^([%!].*|\s*)$/);
+ last;
+ }
+ tr/\015//d;
+ }
+ # some versions have other crap mixed in with the bits in the
+ # block above
+ /^! Last Changed:/ && next;
+
+ # 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
+# /^ clockrate / && next; # kill clockrate on serial interfaces
+
+ if (/^(enable password( \d)?) / && $filter_pwds >= 1) {
+ ProcessHistory("ENABLE","","","!$1 <removed>\n");
+ 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;
+ }
+
+ # prune passwords {bgp, ...}
+ if (/^\s*neighbor (\S*) password / && $filter_pwds >= 1) {
+ ProcessHistory("","","","! neighbor $1 password <removed>\n");
+ next;
+ }
+ # 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","ipsort","$3","$_") && 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 (defined($ENV{'NOCOMMSTR'})) {
+ 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)));
+ } 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 (defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 <removed>$'") && next;
+ } else {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
+ }
+ }
+
+ # prune tacacs/radius server keys
+ if (/^(tacacs-server|radius-server) key / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 key <removed>\n"); next;
+ }
+ if (/^(tacacs-server host \S+( .*)? key) (\d )?\S+/
+ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+
+ # order clns host statements
+# /^clns host \S+ (\S+)/ &&
+# ProcessHistory("CLNS","keysort","$1","$_") && next;
+
+ # prune isis password
+ if (/^( isis authentication-key) \d \S+/ && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>$'"); next;
+ }
+ # prune msdp password
+ if (/^(ip msdp password \S+) / && $filter_pwds >= 1) {
+ ProcessHistory("","","","!$1 <removed>\n"); next;
+ }
+
+# # order ip host line statements
+# /^ip host line(\d+)/ &&
+# ProcessHistory("IPHOST","numsort","$1","$_") && next;
+
+ # catch anything that wasnt matched above.
+ ProcessHistory("","","","$_");
+ # end of config.
+ if (/^end$/) {
+ $found_end = 1;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'show version' => "ShowVersion",
+ 'write term' => "WriteTerm"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and write term last). pita
+@commands=(
+ "show version",
+ "write term"
+);
+$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 -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 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: zebra\n!\n");
+ProcessHistory("COMMENTS","keysort","B0","!\n"); # show version
+ProcessHistory("COMMENTS","keysort","C0","!\n"); # show package
+ProcessHistory("COMMENTS","keysort","D0","!\n"); # show hardware
+ProcessHistory("COMMENTS","keysort","Z0","!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if (/\#\s?exit$/) {
+ $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 ("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);
+}