#!/usr/local/bin/perl -w
#
###################################################################################
# Script for changing community-strings on routers and other network-devices
#
# Before you can run the script, check if there exists a file
# /scripts/perl/hilfsdateien/.passauf.pass with the access- and the enablepassword
# (exactly two lines, each containing one password) and a file 
# /scripts/perl/hilfsdateien/.newsnmp.pass with the RO- and RW-community-string 
# (again exactly two lines, each containing one community-string).
#
# The names of the network-devices will be read out of the files "router.extr", 
# "switches.extr", "switchmenu.extr" and "conc.extr". These files are created using
# the script "list_components.pl".
# You could also use manuelly created files including all network-device names.
#
# The first part configures Cisco-routers using the IOS-CLI.
# Second part configures Cisco Workgroup-Concentrators (1400) using the CLI.
# Third part configures Cisco Workgroup-Swtiches (1200) using the CLI.
# Forth part configures Cisco Switches (19xx and 28xx) using the menu.
# Part 2 and 3 using the same syntax on the CLI!
#
# Christian SCHLEGEL - 07.01.2001
# 
###################################################################################

use strict;
use Net::Telnet;
use Net::Ping;

my @passwords;				# all passwords to access enable-mode
my @communities;			# list of the SNMP-communities

					# define all filenames
my $passwordfile  = "/scripts/perl/hilfsdateien/.passauf.pass";
my $snmpfile      = "/scripts/perl/hilfsdateien/.newsnmp.pass";
my $routerfile    = "/scripts/perl/hilfsdateien/router.extr";
my $switchfile    = "/scripts/perl/hilfsdateien/switches.extr";
my $swimefile     = "/scripts/perl/hilfsdateien/switchmenu.extr";
my $concfile      = "/scripts/perl/hilfsdateien/conc.extr";
my $hubfile       = "/scripts/perl/hilfsdateien/hub.extr";
my $logreport     = "/var/log/_changesnmp.log";

					# Read passwords out of the password-file
					# and delete the file afterwards
open (PASS, $passwordfile) || die "Cannot open password-file\n";
while (<PASS>) { push (@passwords, $_); }
chomp (@passwords);
close PASS;

					# Exit script, if there are not exactly
					# two passwords
(@passwords == 2) || die "The count of passwords is not exactly 2\n";

					# Read SNMP-communities out of the snmp-
					# file and delete the file afterwards
open (SNMP, $snmpfile) || die "Cannot open SNMP-file\n";
while (<SNMP>) { push (@communities, $_); }
chomp (@communities);
close SNMP;

					# Exit script, if there are not exactly
					# two SNMP-communities
(@communities == 2) || die "The count of SNMP-communities is not exactly 2\n";

					# If there exists already a logfile make
					# backup with the extension ".old".
if (-e $logreport) {
	open (OLDLOGDATEI, $logreport);
	open (BAKLOGDATEI, ">$logreport.old");
	while (<OLDLOGDATEI>) {
		print BAKLOGDATEI $_;
	}
	close OLDLOGDATEI;
	close BAKLOGDATEI;
}

					# Create a new logfile for changing the
					# SNMP-communities
open (LOGDATEI, ">$logreport") || die "Cannot create a new logfile\n";

					# Define all parameters for a "ping"
my $pinger = Net::Ping -> new ("icmp", 5);

					# Change the SNMP-communities on CISCO-Routers
open (ROUTER, $routerfile) || die "Cannot open the file with the routernames";
while (<ROUTER>) {
	if (/^[^#]/) {
		chomp;
					# Ping the router twice before connecting
					# using telnet
		$pinger -> ping ("$_");
		if ($pinger -> ping ("$_")) {
					# the eval-function controls possible
					# timeouts of the telnet-sesssion
			eval {
				my $date = localtime;
				my $telnet_obj = Net::Telnet -> new (Host => $_, Timeout => 10);
	
					# switch to usermode
				$telnet_obj -> waitfor ("/Password:/");
				$telnet_obj -> print ("");
				$telnet_obj -> waitfor ("/Password:/");
				$telnet_obj -> print   ($passwords [0]);

					# print date and devicename to STDOUT
					# and logfile
				print "$date\t$_   ";
				print LOGDATEI "$date\t$_   ";
				$telnet_obj -> waitfor ("/$_>/i");

					# switch to enable-mode
				$telnet_obj -> print   ("en");
				$telnet_obj -> waitfor ("/Password:/");
				$telnet_obj -> print   ($passwords [1]);
				$telnet_obj -> waitfor ("/$_#/i");

					# switch to config-mode
				$telnet_obj -> print   ("configure terminal");
				$telnet_obj -> waitfor ("/$_.config.#/i");

					# delete old standard communities
				$telnet_obj -> print   ("no snmp community public ro");
				$telnet_obj -> waitfor ("/$_.config.#/i");
				$telnet_obj -> print   ("no snmp community private rw");
				$telnet_obj -> waitfor ("/$_.config.#/i");

					# change the read-community
				$telnet_obj -> print   ("snmp community $communities[0] ro");

					# print the change to STDOUT and the logfile
				print "\tRead-Community changed";
				print LOGDATEI "\tRead-Community changed";

					# Change the write-community
				$telnet_obj -> waitfor ("/$_.config.#/i");
				$telnet_obj -> print   ("snmp community $communities[1] rw ");
				$telnet_obj -> waitfor ("/$_.config.#/i");
					
					# print successful change to the logfile
				print "\tWrite-Community changed\n";
				print LOGDATEI "\tWrite-Community changed\n";
				$telnet_obj -> print   ("no enable password");
				$telnet_obj -> waitfor ("/$_.config.#/i");
				$telnet_obj -> print   ("exit");
				$telnet_obj -> close;
			};
					# print possible errormessages during the
					# telnet-session
			if ($@) {
				print "\terror $@";
				print LOGDATEI "/t/t$_/terror $@";
			}
		}
					# print an errormessage if the device
					# isn't reachable using ping
		else {
			print ("\t$_ is not reachable\n");
			print LOGDATEI "\t$_ is not reachable\n";
		}
	}				# of if
}					# of while
close ROUTER;

					# Change the SNMP-communities on CISCO Workgroup-Concentrators
open (CONC, $concfile) || die "Cannot open the file with the Concentrator-Names";
while (<CONC>) {
	if (/^[^#]/) {
		chomp;
		$pinger -> ping ($_);
		if ($pinger -> ping ($_)) {
			eval {
				my $date = localtime;
				my $telnet_conc = Net::Telnet -> new (Host => $_, Timeout => 10);
				$telnet_conc -> print   ($passwords [0]);
				$telnet_conc -> waitfor ("/$_>/i");
			print "$date\t$_   ";
			print LOGDATEI "$date\t$_   ";
				$telnet_conc -> print   ("en");
				$telnet_conc -> waitfor ("/password/i");
				$telnet_conc -> print   ($passwords [1]);
				$telnet_conc -> waitfor ("/$_> .enable./i");
				$telnet_conc -> print   ("set community read-only $communities[0]");
				$telnet_conc -> waitfor ("/SNMP community string set./");
				$telnet_conc -> waitfor ("/$_> .enable./i");
			print "\tRead-community ch.";
			print LOGDATEI "\tRead-community ch.";
				$telnet_conc -> print   ("set community read-write $communities[1]");
				$telnet_conc -> waitfor ("/SNMP community string set./");
				$telnet_conc -> waitfor ("/$_> .enable./i");
			print "\tWrite-community ch.";
			print LOGDATEI "\tWrite-community ch.";
					
					# Concentrators have a third community-string to allow the change of
					# community-strings via SNMP! This community-string is set to the 
					# same like the RW-community-string
				$telnet_conc -> print   ("set community read-write-all $communities[1]");
				$telnet_conc -> waitfor ("/SNMP community string set./");
				$telnet_conc -> waitfor ("/$_> .enable./i");
			print "\tWrite-all-community ch.\n";
			print LOGDATEI "\tWrite-all-community ch.\n";
				$telnet_conc -> print   ("exit");
				$telnet_conc -> close;
			};	
			if ($@) {
				print "\t\t$_\terror $@";
				print LOGDATEI "/t/t$_/terror $@";
			}
		}
		else {
			print "\t$_ is not reachable\n";
			print LOGDATEI "\t$_ is not reachable\n";
		}
	}				# von if
}					# von while
close CONC;

					# Change the SNMP-communities on CISCO Workgroup Switches
					# These switches are managed by commandline
open (SWITCHES, $switchfile) || die "Cannot open the file with the Switch-Names";
while (<SWITCHES>) {
	if (/^[^#]/) {
		chomp;
		$pinger -> ping ($_);
		if ($pinger -> ping ($_)) {
			eval {
				my $date = localtime;
				my $telnet_switch = Net::Telnet -> new (Host => $_, Timeout => 10);
				$telnet_switch -> print   ($passwords [0]);
				$telnet_switch -> waitfor ("/$_>/i");
			print "$date\t$_   ";
			print LOGDATEI "$date\t$_   ";
				$telnet_switch -> print   ("en");
				$telnet_switch -> waitfor ("/password/i");
				$telnet_switch -> print   ($passwords [1]);
				$telnet_switch -> waitfor ("/$_> .enable./i");
				$telnet_switch -> print   ("set snmp community read-only $communities[0]");
				$telnet_switch -> waitfor ("/SNMP community string set./");
				$telnet_switch -> waitfor ("/$_> .enable./i");
			print "\tRead-community ch.";
			print LOGDATEI "\tRead-community ch.";
				$telnet_switch -> print   ("set community read-write $communities[1]");
				$telnet_switch -> waitfor ("/SNMP community string set./");
				$telnet_switch -> waitfor ("/$_> .enable./i");
			print "\tWrite-community ch.";
			print LOGDATEI "\tWrite-community ch.";
					
					# Switches have a third community-string to allow the change of
					# community-strings via SNMP! This community-string is set to the 
					# same like the RW-community-string
				$telnet_switch -> print   ("set community read-write-all $communities[1]");
				$telnet_switch -> waitfor ("/SNMP community string set./");
				$telnet_switch -> waitfor ("/$_> .enable./i");
			print "\tWrite-all-community ch.\n";
			print LOGDATEI "\tWrite-all-community ch.\n";
				$telnet_switch -> print   ("exit");
				$telnet_switch -> close;
			};
			if ($@) {
				print "\t\t$_\tFehler $@";
				print LOGDATEI "/t/t$_/tFehler $@";
			}
		}
		else {
			print "\t$_ antwortet nicht\n";
			print LOGDATEI "\t$_ antwortet nicht\n";
		}
	}				# von if
}					# von while
close SWITCHES;
					# Change the SNMP-communities on CISCO Workgroup Switches
					# These switches are managed by commandline
open (SWITCHMENU, $swimefile) || die "Cannot open the file with the Switch-Names";
while (<SWITCHMENU>) {
	if (/^[^#]/) {
		chomp;
		$pinger -> ping ($_);
		if ($pinger -> ping ($_)) {
			eval {
				my $date = localtime;
				my $telnet_switch = Net::Telnet -> new (Host => $_, Timeout => 10);
				$telnet_switch -> waitfor ("/password/i");
				$telnet_switch -> print   ($passwords [0]);
				$telnet_switch -> waitfor ("/Enter Selection:/i");
					# Enter the "Network Management" menu
				$telnet_switch -> print   ("n");
				$telnet_switch -> waitfor ("/Enter Selection:/i");
					# Enter the "Network Managemant (SNMP) Configuration" menu
				$telnet_switch -> print   ("s");
				$telnet_switch -> waitfor ("/Enter Selection:/i");
					# Change the READ-community-string
				$telnet_switch -> print   ("r");
				$telnet_switch -> waitfor ("/New setting/i");
			print "$date\t$_   ";
			print LOGDATEI "$date\t$_   ";
				$telnet_switch -> print   ("$communities[0]");
				$telnet_switch -> waitfor ("/Enter selection:/i");
			print "\tRead-community changed";
			print LOGDATEI "\tRead-community changed";
					# Change the WRITE-community-strin
				$telnet_switch -> print   ("w");
				$telnet_switch -> waitfor ("/New setting/i");
				$telnet_switch -> print   ("$communities[1]");
				$telnet_switch -> waitfor ("/Enter Selection/i");
			print "\tWrite-community changed\n";
			print LOGDATEI "\tWrite-community changed\n";
				$telnet_switch -> print   ("X");
				$telnet_switch -> waitfor ("/Enter Selection/i");
				$telnet_switch -> print   ("X");
				$telnet_switch -> waitfor ("/Enter Selection/i");
				$telnet_switch -> print   ("X");
				$telnet_switch -> waitfor ("/Exit Management Console/i");
				$telnet_switch -> print   ("y");
#				$telnet_switch -> close;
			};
			if ($@) {
				print "\t\t$_\tFehler $@";
				print LOGDATEI "\t\t$_\tFehler $@";
			}
		}
		else {
			print "\t$_ antwortet nicht\n";
			print LOGDATEI "\t$_ antwortet nicht\n";
		}
	}				# von if
}					# von while
close SWITCHMENU;
close LOGDATEI;

=head1 NAME

change_snmp.pl

=head1 VERSION

1.0

=head1 SYNOPSIS

change_snmp.pl

=head1 DESCRIPTION

=head1 ARGUMENTS

=head1 EXAMPLE

=head1 AUTHOR

Christian Schlegel
