From 5195074095cac48dd15d857bce69c1aa909ec2b2 Mon Sep 17 00:00:00 2001
From: Matthias Eble <psychotrahe@gmx.de>
Date: Thu, 11 Jun 2009 01:17:58 +0200
Subject: Fixed SNMPv3 behaviour of check_ifoperstatus. Added -x to define
 privprotocol (#2343438 - Robin Schroeder)

check_ifoperstatus didn't function correctly with SNMPv3. This is fixed now.
Created argument-hash for SNMP session creation. This removes redundant code.
Session creation was moved out of process_arguments() and now takes place
after setting the timeout handler.

Additionally the -x argument was added to specify the privprotocol.

diff --git a/NEWS b/NEWS
index ecfd67e..768a1cc 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,7 @@ This file documents the major additions and syntax changes between releases.
 	Fixed check_by_ssh interpretation of quotes in -C parameter (#1985246, #2268675)
 	check_snmp now supports standard threshold ranges and doubles (floating numbers) in thresholds
 	check_fping now supports passing target timeout and interval to fping (#2347686 - Martin Foster)
+	Fixed SNMPv3 behaviour of check_ifoperstatus. Added -x to define privprotocol (#2343438 - Robin Schroeder)
 
 1.4.13 25th Sept 2008
 	Fix Debian bug #460097: check_http --max-age broken (Hilko Bengen)
diff --git a/plugins-scripts/check_ifoperstatus.pl b/plugins-scripts/check_ifoperstatus.pl
index d0a1655..503f1e4 100755
--- a/plugins-scripts/check_ifoperstatus.pl
+++ b/plugins-scripts/check_ifoperstatus.pl
@@ -61,7 +61,7 @@ my $answer = "";
 my $snmpkey = 0;
 my $community = "public";
 my $maxmsgsize = 1472 ; # Net::SNMP default is 1472
-my ($seclevel, $authproto, $secname, $authpass, $privpass, $auth, $priv, $context);
+my ($seclevel, $authproto, $secname, $authpass, $privpass, $privproto, $auth, $priv, $context);
 my $port = 161;
 my @snmpoids;
 my $sysUptime        = '1.3.6.1.2.1.1.3.0';
@@ -89,12 +89,14 @@ my $lastc;
 my $dormantWarn;
 my $adminWarn;
 my $name;
+my %session_opts;
 
 ### Validate Arguments
 
 $status = process_arguments();
 
 
+use Data::Dumper;
 # Just in case of problems, let's not hang Nagios
 $SIG{'ALRM'} = sub {
      print ("ERROR: No snmp response from $hostname (alarm)\n");
@@ -103,6 +105,16 @@ $SIG{'ALRM'} = sub {
 
 alarm($timeout);
 
+print Dumper(\%session_opts);
+($session, $error) = Net::SNMP->session(%session_opts);
+
+		
+if (!defined($session)) {
+			$state='UNKNOWN';
+			$answer=$error;
+			print ("$state: $answer\n");
+			exit $ERRORS{$state};
+}
 
 ## map ifdescr to ifindex - should look at being able to cache this value
 
@@ -293,6 +305,7 @@ sub print_help() {
 	printf "   -X (--privpass)   privacy password (cleartext ascii or localized key\n";
 	printf "                     in hex with 0x prefix generated by using	\"snmpkey\" utility\n"; 
 	printf "                     privacy password and authEngineID\n";
+	printf "   -x (--privproto)  privacy protocol (DES or AES; default: DES)\n";
 	printf "   -k (--key)        SNMP IfIndex value\n";
 	printf "   -d (--descr)      SNMP ifDescr value\n";
 	printf "   -T (--type)       SNMP ifType integer value (see http://www.iana.org/assignments/ianaiftype-mib)\n";
@@ -327,6 +340,7 @@ sub process_arguments() {
 			"U=s" => \$secname,   "secname=s"   => \$secname,
 			"A=s" => \$authpass,  "authpass=s"  => \$authpass,
 			"X=s" => \$privpass,  "privpass=s"  => \$privpass,
+			"x=s" => \$privproto,  "privproto=s"  => \$privproto,
 			"c=s" => \$context,   "context=s"   => \$context,
 			"k=i" => \$snmpkey, "key=i",\$snmpkey,
 			"d=s" => \$ifdescr, "descr=s" => \$ifdescr,
@@ -387,10 +401,27 @@ sub process_arguments() {
 		$timeout = $TIMEOUT;
 	}
 
+		
+	if ($snmp_version !~ /[123]/){
+		$state='UNKNOWN';
+		print ("$state: No support for SNMP v$snmp_version yet\n");
+		exit $ERRORS{$state};
+	}
+
+	%session_opts = (
+		-hostname  => $hostname,
+		-port      => $port,
+		-version	=> $snmp_version,
+		-maxmsgsize => $maxmsgsize
+	);
+
+	$session_opts{'-community'} = $community if (defined $community && $snmp_version =~ /[12]/);
+
 	if ($snmp_version =~ /3/ ) {
 		# Must define a security level even though default is noAuthNoPriv
 		# v3 requires a security username
 		if (defined $seclevel  && defined $secname) {
+			$session_opts{'-username'} = $secname;
 		
 			# Must define a security level even though defualt is noAuthNoPriv
 			unless ( grep /^$seclevel$/, qw(noAuthNoPriv authNoPriv authPriv) ) {
@@ -400,23 +431,22 @@ sub process_arguments() {
 			
 			# Authentication wanted
 			if ( $seclevel eq 'authNoPriv' || $seclevel eq 'authPriv' ) {
-		
 				unless ( $authproto eq 'MD5' || $authproto eq 'SHA1' ) {
 					usage();
 					exit $ERRORS{"UNKNOWN"};
 				}
+				$session_opts{'-authprotocol'} = $authproto if(defined $authproto);
 
 				if ( !defined $authpass) {
 					usage();
 					exit $ERRORS{"UNKNOWN"};
 				}else{
 					if ($authpass =~ /^0x/ ) {
-						$auth = "-authkey => $authpass" ;
+						$session_opts{'-authkey'} = $authpass ;
 					}else{
-						$auth = "-authpassword => $authpass";
+						$session_opts{'-authpassword'} = $authpass ;
 					}
 				}
-					
 			}
 			
 			# Privacy (DES encryption) wanted
@@ -426,21 +456,20 @@ sub process_arguments() {
 					exit $ERRORS{"UNKNOWN"};
 				}else{
 					if ($privpass =~ /^0x/){
-						$priv = "-privkey => $privpass";
+						$session_opts{'-privkey'} = $privpass;
 					}else{
-						$priv = "-privpassword => $privpass";
+						$session_opts{'-privpassword'} = $privpass;
 					}
 				}
+
+				$session_opts{'-privprotocol'} = $privproto if(defined $privproto);
 			}
 
 			# Context name defined or default
-
 			unless ( defined $context) {
 				$context = "";
 			}
 		
-		
-		
 		}else {
 					usage();
 					exit $ERRORS{'UNKNOWN'}; ;
@@ -448,67 +477,6 @@ sub process_arguments() {
 	} # end snmpv3
 
 
-	if ( $snmp_version =~ /[12]/ ) {
-  	($session, $error) = Net::SNMP->session(
-			-hostname  => $hostname,
-			-community => $community,
-			-port      => $port,
-			-version	=> $snmp_version,
-			-maxmsgsize => $maxmsgsize
-		);
-
-		if (!defined($session)) {
-			$state='UNKNOWN';
-			$answer=$error;
-			print ("$state: $answer\n");
-			exit $ERRORS{$state};
-		}
-	
-	}elsif ( $snmp_version =~ /3/ ) {
-
-		if ($seclevel eq 'noAuthNoPriv') {
-			($session, $error) = Net::SNMP->session(
-				-hostname  => $hostname,
-				-port      => $port,
-				-version  => $snmp_version,
-				-username => $secname,
-			);
-
-		}elsif ( $seclevel eq 'authNoPriv' ) {
-			($session, $error) = Net::SNMP->session(
-				-hostname  => $hostname,
-				-port      => $port,
-				-version  => $snmp_version,
-				-username => $secname,
-				$auth,
-				-authprotocol => $authproto,
-			);	
-		}elsif ($seclevel eq 'authPriv' ) {
-			($session, $error) = Net::SNMP->session(
-				-hostname  => $hostname,
-				-port      => $port,
-				-version  => $snmp_version,
-				-username => $secname,
-				$auth,
-				-authprotocol => $authproto,
-				$priv
-			);
-		}
-					
-					
-		if (!defined($session)) {
-					$state='UNKNOWN';
-					$answer=$error;
-					print ("$state: $answer\n");
-					exit $ERRORS{$state};
-		}
-
-	}else{
-		$state='UNKNOWN';
-		print ("$state: No support for SNMP v$snmp_version yet\n");
-		exit $ERRORS{$state};
-	}
-
 }
 ## End validation
 
-- 
cgit v0.10-9-g596f

