#!/usr/local/bin/perl # -*- perl -*- # Copyright (c) 2000 by Jeff Weisberg # Author: Jeff Weisberg # Function: archive router configs use Socket; # where do you want snapshots saved? $SNAPSHOTDIR = "/home/sysadm/conf/snapshot"; # on cisco: # ip rcmd rsh-enable # ip rcmd remote-host ciscouser IP_ADDRESS unixuser enable # an access list might be a good idea as well $luser = "unixuser"; $ruser = "ciscouser"; # substitute your own usernames, of course # substitute your own routers, or pass on cmdline @routers = qw( gw-bm1.example.net gw-bm2.example.net gw-bm3.example.net ); # ASLO NOTE: in order to RCS the snapshots, RCS must be installed ################################################################ @routers = @ARGV if @ARGV; chdir $SNAPSHOTDIR; $TIMEOUT = 120; $proto = 6; # tcp $port = 514; # rsh foreach $r (@routers){ print STDERR "$r\n"; $ip = resolve($r); if( !$ip ){ print STDERR "could not resolve $r\n"; next; } socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; select S; $| = 1; select STDOUT; # get a reserved port for $lp (512 .. 1023){ $sin = sockaddr_in($lp, INADDR_ANY); if( bind(S, $sin) == 0 ){ $! = ''; last; } } if( $! ){ close S; print STDERR "could not bind to local port: $!\n"; next; } $sin = sockaddr_in($port, $ip); if( ! connect(S, $sin) ){ close S; print STDERR "$r - connect failed: $!\n"; next; } # speak the rcmd (rsh) protocol to do "show run" print S "0\0$luser\0$ruser\0show run\0"; rename $r, "$r.bak"; open(FILE, "> $r"); $bad = 1; $itime = time(); $conf = ''; while( 1 ){ if( time() > $itime + $TIMEOUT ){ print STDERR "time out\n"; last; } $rfds = $wfds = "\0\0\0\0"; vec($rfds, fileno(S), 1) = 1; $i = select($rfds, undef, undef, ($itime + $TIMEOUT - time())); if( $i == -1 ){ if( $! != 4 ){ print STDERR "error: $!\n"; close S; last; } next; } $i = sysread S, $line, 8192; if( $i == 0 ){ # eof # print STDERR "unexpected eof\n"; sleep 5; seek S, 0, 1; } $conf .= $line; if( $conf =~ /^end/m ){ $bad = 0; last; } } close S; $_ = $conf; tr/\0//d; tr/\r//d; if( /ntp clock-period/m ){ # ignore minor clock fluctuations s/ntp clock-period .*$/! ntp clock-period /m; } if( /^username /m ){ # ignore pwd s/^(username .*) [^ ]+$/! \1 /mg; } print FILE $_; close FILE; close S; if( ! $bad ){ system( "rcsdiff -q $r" ); system( "echo . | ci -l -mperiodic $r >/dev/null 2>&1" ); unlink "$r.bak"; }else{ print STDERR "\treverting\n"; rename $r, "$r.xxx"; rename "$r.bak", $r; } } sub resolve { my( $a ) = @_; my( $ip, @o ); if( $a =~ /^\d+\.\d+\.\d+\.\d+$/ ){ @o = split( /\./, $a ); $ip = pack ("CCCC", @o); }else{ $ip = gethostbyname($a); if( length($ip) != 4){ sleep(1); $ip = gethostbyname($a); } } $ip; }