Browse Source

Merge branch 'maint' into gcc73-fixes

Mario Trangoni 8 years ago
parent
commit
46d9c59b88

+ 1 - 0
.gitignore

@@ -4,6 +4,7 @@ cscope.out
 nbproject/
 .kdev4/
 plugins.kdev4
+plugins.project
 
 # In all paths
 NP-VERSION-FILE

+ 3 - 0
Makefile.am

@@ -29,6 +29,9 @@ dist-hook:
 install-root:
 	cd plugins-root && $(MAKE) $@
 
+install-packager:
+	cd plugins-root && $(MAKE) $@
+
 test test-debug:
 	cd lib && $(MAKE) $@
 	if test "$(PERLMODS_DIR)" != ""; then cd perlmods && $(MAKE) $@; fi

+ 44 - 0
NEWS

@@ -1,5 +1,48 @@
 This file documents the major additions and syntax changes between releases.
 
+2.3.0 xxxx-xx-xx
+	ENHANCEMENTS
+	Added directory plugins-python containing three Python plugins
+	Add plugin remove_perfdata to remove perfdata from specified plugin's output
+	Added warning_string/critical_string to struct thresholds for storing originally parsed strings
+	check_http: New parameter `--verify-host` will check if -H hostname matches the SSL certificate
+	check_ping: plugin output will now include hostname and IP address
+	check_disk_smb: Add configfile feature
+	check_apt: Add --only-critical switch
+	check_mailq: Add support for opensmtpd
+	check_mailq: Add mailq -C option for config dir or config file
+	check_disk: Add -s option to show status for each path/partition
+	check_mailq.pl: Add option for opensmtpd (brigriffin)
+	check_procs: Add FreeBSD jail support (Mathieu Arnold)
+	check_procs: Allow process to be excluded from check_procs (Marcel Klein)
+	check_ldap: Add support for checking LDAP cert age (Guillaume Rousse)
+	check_icmp: Add Jitter, MOS, Score (Alessandro Ren)
+	check_radius: Add calling-station-id (cejkar)
+	ssl_utils: Added certificate expiry data in OK status (check_http, check_smtp, check_tcp) (Matt Capra)
+
+
+2.2.2 xxxx-xx-xx
+	FIXES
+	check_disk: autofs being mounted despite '-l'. Fixed, and also excluded some system "fake" mountpoints
+	check_ntp_time: Periodically returns "Socket timeout" when one of several ntp server doesn't respond
+	check_ntp_time calls `write` on a UDP socket without a successful call to `connect`
+	check_mysql_query & mysql_query: extra-opts causes crash
+	check_log does not check for "-O oldlog"
+	check_log lost ability to use regexes for query (-q) in 2.1.4
+	fix configure.ac for FreeBSD SWAPFORMAT
+	Fix --no-body
+	check_wave produces lots of errors if required arguments are not provided
+	check_disk_smb.pl added additional smb support
+	check_http Additional header/status checking
+	check_http When checking certificate, don't check content/status
+	Fix ax_with_python not crashing on Python3 (Michael Orlitzky)
+	Fix rpmbuild errors (Josh Coughlan)
+	check_ping: FreeBSD ping working natively
+	check_sensors: Fix fault test with --ignore-fault
+	check_snmp: Fix perfdata not adhering to plugin dev guidelines
+	check_snmp: warning/critical perfdata is returned properly
+
+
 2.2.1 2017-04-19
 	FIXES
 	check_users: not accepting zero as the threshold
@@ -17,6 +60,7 @@ This file documents the major additions and syntax changes between releases.
 	check_mailq: Nullmailer Regex is not working for Ubuntu 16.04
 	check_swap: Downstream Fedora patch: Prevent check_swap from returning OK, if no swap activated
 	Building RPMs on Amazon Linux - Add 'install-root' on line 165 of spec file
+	check_http: Memory allocation error
 
 
 2.2.0 2017-01-19

+ 19 - 0
THANKS.in

@@ -18,6 +18,7 @@ Andreas Ericsson
 Andreas Seemueller
 Andrew Berglund
 Andrew Elwell
+Andrew Penniman
 Andrew Widdersheim
 Andy Brist
 Andy Doran
@@ -42,23 +43,28 @@ Booker C. Bense
 Bradley Baetz
 Brian De Wolf
 Brian Landers
+brigriffin
 Bryan Irvine
 Carlos Canau
 Carole Verdon
+cejkar
 Charles-Henri Larose
 Charlie Cook
 Chester Hosey
 Chris Grim
+Chris Heath
 Chris Pepper
 Chris Wilson
 Christian G Warden
 Christian Mies
+Christian Schmidt
 Christian Schneemann
 Christoph Kron
 Christoph Schell
 Christopher Maser
 Christopher Schultz
 Cire Iriarte
+Claudio Kuenzler
 Cliff Rice
 Collin Fair
 Cove Schneider
@@ -119,6 +125,7 @@ Gianluca Varisco
 Grant Byers
 Greg Bowser
 Guenther Mair
+Guillaume Rousse
 Gunnar Beutner
 Gunnar Hellekson
 Guy Van Den Bergh
@@ -174,6 +181,7 @@ John Rouillard
 John Sivak
 John Warburton
 Jon Hallett
+Jon Stockton
 Jon Vandegrift
 Jonas Genannt
 Jonas Genannt
@@ -181,6 +189,7 @@ Jonathan Milby
 Jonathan Rozes
 Joseph Gooch
 Josip Rodin
+Josh Coughlan
 Juan Carlos Fernandez
 Julien Touche
 Julius Kriukas
@@ -200,6 +209,8 @@ Lars Stavholm
 Lars Vogdt
 Laurent Licour
 Laurent Vaslin
+Lee Clemens
+Leonid Vasiliev
 Lionel Cons
 Lonny Selinger
 Luca Corti
@@ -209,11 +220,13 @@ Lynne Lawrence
 Marc Huffnagle
 Marc Poulin
 Marc Remy
+Marcel Klein
 Marcel Kuiper
 Marco Beck
 Marcos Della
 Mario Trangoni
 Mario Witte
+Mark A. Ziesemer
 Mark Favas
 Mark Jewiss
 Mark Keisler
@@ -221,7 +234,9 @@ Markus Baertschi
 Marlo Bell
 Martin Foster
 Matej Vela
+Mathieu Arnold
 Mathieu Masseboeuf
+Matt Capra
 Matt Garrett
 Matt Perry
 Matt Pounsett
@@ -240,10 +255,12 @@ Michael Bakker
 Michael Haro
 Michael Markstaller
 Michael Musikhin
+Michael Orlitzky
 Michael Tiernan
 Mikael Falkvidd
 Mike Emigh
 Mike McHenry
+mwennrich
 Myke Place
 Nathan Shafer
 Neil Prockter
@@ -344,8 +361,10 @@ StoneISStephan
 Stuart Webster
 Stéphane Bortzmeyer
 Stéphane Urbanovski
+Subito
 Sven Meyer
 Sven Schaffranneck
+Syl Robataille
 Thomas Nilsen
 Thomas Schimpke
 Tilman Koschnick

+ 46 - 3
configure.ac

@@ -786,6 +786,16 @@ then
 	ac_cv_ps_cols=10
 	AC_MSG_RESULT([$ac_cv_ps_command])
 
+dnl jails on FreeBSD:
+elif ps -axwo 'stat comm vsz rss user uid pid ppid jid args' 2>/dev/null | \
+	egrep -i "^ *STAT +COMMAND +VSZ +RSS +USER +UID +PID +PPID +JID +COMMAND" > /dev/null
+then
+	ac_cv_ps_varlist="procstat,&procuid,&procpid,&procppid,&procjid,&procvsz,&procrss,&procpcpu,procprog,&pos"
+	ac_cv_ps_command="$PATH_TO_PS -axwo 'stat uid pid ppid jid vsz rss pcpu comm args'"
+	ac_cv_ps_format="%s %d %d %d %d %d %d %f %s %n"
+	ac_cv_ps_cols=10
+	AC_MSG_RESULT([$ac_cv_ps_command])
+
 dnl Some gnu/linux systems (debian for one) don't like -axwwo and need axwwo.
 dnl so test for this first...
 elif ps axwwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \
@@ -1065,6 +1075,12 @@ AC_ARG_WITH(ping_command,
 		[sets syntax for ICMP ping]),
 	with_ping_command=$withval,)
 
+dnl AS I WAS LOOKING INTO THIS... (Bryan Heden 09/2017)
+dnl Ping packets first was a bit confusing
+dnl it doesn't actually mean "packet count first"
+dnl it means packets come before specifying host
+dnl If a timeout is specified, that comes first
+
 AC_MSG_CHECKING(for ICMP ping syntax)
 ac_cv_ping_packets_first=no
 ac_cv_ping_has_timeout=no
@@ -1114,6 +1130,14 @@ then
 	ac_cv_ping_packets_first=yes
 	AC_MSG_RESULT([$with_ping_command])
 
+elif $PATH_TO_PING -n -t 10 -c 1 127.0.0.1 2>/dev/null | \
+  egrep -i "^round-trip|^rtt" >/dev/null
+then
+  with_ping_command="$PATH_TO_PING -n -t %d -c %d %s"
+  ac_cv_ping_packets_first=yes
+  ac_cv_ping_has_timeout=yes
+  AC_MSG_RESULT([$with_ping_command])
+
 elif $PATH_TO_PING -n -c 1 127.0.0.1 2>/dev/null | \
 	egrep -i "^round-trip|^rtt" >/dev/null
 then
@@ -1230,6 +1254,14 @@ elif test "x$PATH_TO_PING6" != "x"; then
 		ac_cv_ping6_packets_first=yes
 		AC_MSG_RESULT([$with_ping6_command])
 
+  elif $PATH_TO_PING6 -n -X 10 -c 1 ::1 2>/dev/null | \
+    egrep -i "^round-trip|^rtt" >/dev/null
+  then
+    with_ping6_command="$PATH_TO_PING6 -n -X %d -c %d %s"
+    ac_cv_ping6_packets_first=yes
+    ac_cv_ping_has_timeout=yes
+    AC_MSG_RESULT([$with_ping6_command])
+
 	elif $PATH_TO_PING6 -n -c 1 ::1 2>/dev/null | \
 		egrep -i "^round-trip|^rtt" >/dev/null
 	then
@@ -1266,7 +1298,7 @@ elif test "x$PATH_TO_PING6" != "x"; then
 	then
 		with_ping6_command="$PATH_TO_PING6 -n -s 56 -c %d %s"
 		ac_cv_ping6_packets_first=yes
-		AC_MSG_RESULT([$with_ping_command])
+		AC_MSG_RESULT([$with_ping6_command])
 
 	elif $PATH_TO_PING6 -n -c 1 ::1 2>/dev/null | \
 		egrep -i "^round-trip|^rtt" >/dev/null
@@ -1329,7 +1361,7 @@ elif test "x$PATH_TO_PING" != "x"; then
 	then
 		with_ping6_command="$PATH_TO_PING -A inet6 -n -s 56 -c %d %s"
 		ac_cv_ping6_packets_first=yes
-		AC_MSG_RESULT([$with_ping_command])
+		AC_MSG_RESULT([$with_ping6_command])
 
 	elif $PATH_TO_PING -A inet6 -n -c 1 ::1 2>/dev/null | \
 		egrep -i "^round-trip|^rtt" >/dev/null
@@ -1557,6 +1589,17 @@ else
 	AC_MSG_WARN([Could not find qmail-qstat or equivalent])
 fi
 
+AC_PATH_PROG(PATH_TO_SMTPCTL,smtpctl)
+AC_ARG_WITH(smtpctl_command,
+            ACX_HELP_STRING([--with-smtpctl-command=PATH],
+                            [sets path to smtpctl]), PATH_TO_SMTPCTL=$withval)
+if test -n "$PATH_TO_SMTPCTL"
+then
+	AC_DEFINE_UNQUOTED(PATH_TO_SMTPCTL,"$PATH_TO_SMTPCTL",[path to smtpctl])
+else
+	AC_MSG_WARN([Could not find smtpctl or equivalent])
+fi
+
 dnl SWAP info required is amount allocated/available and amount free
 dnl The plugin works through all the swap devices and adds up the total swap
 dnl available.
@@ -1602,7 +1645,7 @@ then
 
 	if [$PATH_TO_SWAPINFO -k 2>/dev/null | egrep -i "^Device +1K-blocks +Used +Avail" >/dev/null]
 	then
-		ac_cv_swap_format=["%*s %f %*d %f"]
+		ac_cv_swap_format=["%*s %lf %*d %lf"]
 		ac_cv_swap_conv=1024
 		AC_MSG_RESULT([using FreeBSD format swapinfo])
 	fi

+ 4 - 1
lib/parse_ini.c

@@ -83,6 +83,7 @@ static char* default_file_in_path(void);
  */
 static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i){
 	size_t locator_len=0, stanza_len=0;
+	char *dflt = NULL;
 
 	/* if locator is NULL we'll use default values */
 	if(locator){
@@ -102,7 +103,9 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in
 	}
 	/* if there is no @file part */
 	if(stanza_len==locator_len){
-		i->file=default_file();
+		dflt=default_file();
+		if (dflt)
+			i->file=strdup(dflt);
 	} else {
 		i->file=strdup(&(locator[stanza_len+1]));
 	}

+ 10 - 0
lib/utils_base.c

@@ -164,18 +164,22 @@ _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_st
 
 	temp_thresholds->warning = NULL;
 	temp_thresholds->critical = NULL;
+	temp_thresholds->warning_string = NULL;
+	temp_thresholds->critical_string = NULL;
 
 	if (warn_string) {
 		if (!(temp_thresholds->warning = parse_range_string(warn_string))) {
 			free(temp_thresholds);
 			return NP_RANGE_UNPARSEABLE;
 		}
+		temp_thresholds->warning_string = strdup(warn_string);
 	}
 	if (critical_string) {
 		if (!(temp_thresholds->critical = parse_range_string(critical_string))) {
 			free(temp_thresholds);
 			return NP_RANGE_UNPARSEABLE;
 		}
+		temp_thresholds->critical_string = strdup(critical_string);
 	}
 
 	*my_thresholds = temp_thresholds;
@@ -204,11 +208,17 @@ void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
 	} else {
 		if (my_threshold->warning) {
 			printf("Warning: start=%g end=%g; ", my_threshold->warning->start, my_threshold->warning->end);
+			if (my_threshold->warning_string) {
+				printf("Warning String: %s; ", my_threshold->warning_string);
+			}
 		} else {
 			printf("Warning not set; ");
 		}
 		if (my_threshold->critical) {
 			printf("Critical: start=%g end=%g", my_threshold->critical->start, my_threshold->critical->end);
+			if (my_threshold->critical_string) {
+				printf("Critical String: %s; ", my_threshold->critical_string);
+			}
 		} else {
 			printf("Critical not set");
 		}

+ 2 - 0
lib/utils_base.h

@@ -28,6 +28,8 @@ typedef struct range_struct {
 typedef struct thresholds_struct {
 	range	*warning;
 	range	*critical;
+	char    *warning_string;
+	char    *critical_string;
 	} thresholds;
 
 #define NP_STATE_FORMAT_VERSION 1

+ 1 - 1
lib/utils_disk.h

@@ -26,7 +26,7 @@ struct parameter_list
   struct parameter_list *name_next;
   uintmax_t total, available, available_to_root, used, inodes_free, inodes_total;
   double dfree_pct, dused_pct;
-  double dused_units, dfree_units, dtotal_units;
+  uintmax_t dused_units, dfree_units, dtotal_units;
   double dused_inodes_percent, dfree_inodes_percent;
 };
 

+ 1 - 1
m4/ax_with_python.m4

@@ -46,7 +46,7 @@ AC_DEFUN([AX_WITH_PYTHON],
     if test "$PYTHON" != "m4_ifval([$2],[$2],[python])"
     then
       AC_MSG_CHECKING($PYTHON version >= $1)
-      if test `$PYTHON -c ["import sys; print sys.version[:3] >= \"$1\" and \"OK\" or \"OLD\""]` = "OK"
+      if test `$PYTHON -c ["import sys; print(sys.version[:3] >= \"$1\" and \"OK\" or \"OLD\")"]` = "OK"
       then
         AC_MSG_RESULT(ok)
       else

+ 3 - 2
nagios-plugins.spec.in

@@ -162,11 +162,12 @@ fi
 
 %install
 rm -rf $RPM_BUILD_ROOT
-make AM_INSTALL_PROGRAM_FLAGS="" DESTDIR=${RPM_BUILD_ROOT} install install-root
+make AM_INSTALL_PROGRAM_FLAGS="" DESTDIR=${RPM_BUILD_ROOT} install
+make AM_INSTALL_PROGRAM_FLAGS="" DESTDIR=${RPM_BUILD_ROOT} install-packager
 %find_lang %{name}
 echo "%defattr(755,%{npusr},%{npgrp})" >> %{name}.lang
 comm -13 %{npdir}/ls-plugins-before %{npdir}/ls-plugins-after | egrep -v "\.o$|^\." | gawk -v libexecdir=%{_libexecdir} '{printf( "%s/%s\n", libexecdir, $0);}' >> %{name}.lang
-echo "%defattr(755,root,root)" >> %{name}.lang
+echo "%defattr(4555,root,%{npgrp})" >> %{name}.lang
 comm -13 %{npdir}/ls-plugins-root-before %{npdir}/ls-plugins-root-after | egrep -v "\.o$|^\." | gawk -v libexecdir=%{_libexecdir} '{printf( "%s/%s\n", libexecdir, $0);}' >> %{name}.lang
 echo "%defattr(755,%{npusr},%{npgrp})" >> %{name}.lang
 comm -13 %{npdir}/ls-plugins-scripts-before %{npdir}/ls-plugins-scripts-after | egrep -v "\.o$|^\." | gawk -v libexecdir=%{_libexecdir} '{printf( "%s/%s\n", libexecdir, $0);}' >> %{name}.lang

+ 47 - 0
plugins-python/Makefile.am

@@ -0,0 +1,47 @@
+## Process this file with automake to produce Makefile.in
+
+if RELEASE_PRESENT
+NP_VERSION = @NP_RELEASE@
+else
+NP-VERSION-FILE: .FORCE-NP-VERSION-FILE
+	@$(SHELL_PATH) $(top_srcdir)/NP-VERSION-GEN
+.FORCE-NP-VERSION-FILE:
+-include NP-VERSION-FILE
+endif
+
+SUFFIXES = .py .in
+
+VPATH=$(top_srcdir) $(top_srcdir)/plugins-python
+
+libexec_SCRIPTS = check_heartbleed.py  check_imap_login.py check_ncpa.py
+
+EXTRA_DIST=check_heartbleed.in  check_imap_login.in  check_ncpa.in
+
+EDIT = sed \
+  -e 's|[@]NP_VERSION[@]|$(NP_VERSION)|g' \
+  -e 's|[@]TRUSTED_PATH[@]|$(with_trusted_path)|g' \
+  -e 's|[@]PYTHON[@]|$(PYTHON)|g' \
+  -e 's|[@]libexecdir[@]|$(libexecdir)|g'
+
+#TESTS_ENVIRONMENT=perl -I $(top_builddir) -I $(top_srcdir)
+
+#TESTS = @SCRIPT_TEST@
+
+#test:
+#	perl -I $(top_builddir) -I $(top_srcdir) ../test.pl
+#	perl -I $(top_builddir) -I $(top_srcdir) ../test.pl t/utils.t	# utils.t is excluded from above, so manually ask to test
+
+#test-debug:
+#	NPTEST_DEBUG=1 HARNESS_VERBOSE=1 perl -I $(top_builddir) -I $(top_srcdir) ../test.pl
+#	NPTEST_DEBUG=1 HARNESS_VERBOSE=1 perl -I $(top_builddir) -I $(top_srcdir) ../test.pl t/utils.t	# utils.t is excluded from above, so manually ask to test
+
+CLEANFILES=$(libexec_SCRIPTS)
+
+.in.py:
+	@if [ ! "$(PYTHON)" = "missing" ]; then \
+	    $(EDIT) $< > $@; \
+	    chmod +x $@; \
+	fi
+
+clean-local:
+	rm -f NP-VERSION-FILE *.pyc

+ 331 - 0
plugins-python/check_heartbleed.in

@@ -0,0 +1,331 @@
+#!/usr/bin/python2
+
+# Check_Heartbleed.py v0.6
+# 18/4/2014
+
+# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)
+# The author disclaims copyright to this source code.
+
+# Modified for simplified checking by Yonathan Klijnsma
+
+# Modified to turn into a Nagios Plugin by Scott Wilkerson (swilkerson@nagios.com)
+# Modified to include TLS v1.2, v1.1, v1.0, and SSLv3.0, defaults to 1.1 (sreinhardt@nagios.com)
+# 	Corrected Hello and Heartbeat packets to match versions
+#	Added optional verbose output
+#	Reimplemented output message and added Rich's idea for looping all supported versions
+# Suggested and implemented in another plugin looping of all versions by default (rich.brown@blueberryhillsoftware.com)
+
+import sys
+import struct
+import socket
+import time
+import select
+import re
+from optparse import OptionParser
+
+options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
+options.add_option('-H', '--host', type='string', default='127.0.0.1', help='Host to connect to (default: 127.0.0.1)')
+options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')
+options.add_option('-v', '--version', type='int', default=-1, help='TLS or SSL version to test [TLSv1.0(0), TLSv1.1(1), TLSv1.2(2), or SSLv3.0(3)] (default: all)')
+options.add_option('-u', '--udp', default=False, action='store_true', help='Use TCP or UDP protocols, no arguments needed. This does not work presently, keep to TCP. (default: TCP)')
+options.add_option('-t', '--timeout', type='int', default=10, help='Plugin timeout length (default: 10)')
+options.add_option('-V', '--verbose', default=False, action='store_true', help='Print verbose output, including hexdumps of packets.')
+
+def h2bin(x):
+    return x.replace(' ', '').replace('\n', '').decode('hex')
+
+# Returns correct versioning for handshake and hb packets
+def tls_ver ():
+    global opts
+    if opts.version == 0:    #TLSv1.0
+        return '''03 01'''
+    elif opts.version == 2:    #TLSv1.2
+        return '''03 03'''
+    elif opts.version == 3:    #SSLv3.0
+        return '''03 00'''
+    else:                    #TLSv1.1
+        return '''03 02'''
+
+# Builds hello packet with correct tls version for rest of connection
+def build_hello():
+
+    hello = h2bin('''
+    16 ''' + tls_ver() + ''' 00  dc 01 00 00 d8 ''' + tls_ver() + ''' 53
+    4e d0 57 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
+    bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
+    00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
+    00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
+    c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
+    c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
+    c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
+    c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
+    00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
+    03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
+    00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
+    00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
+    00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
+    00 0f 00 01 01                                  
+    ''')
+
+##### Hello Packet Layout #####
+#	16													# initiate handshake
+#	+ tls_ver() +  										# version of tls to use
+#	00  dc 												# Length
+#	01 													# Handshake type (hello)
+#	00 00 d8 											# Length
+#	+ tls_ver() +  										# version of tls to use
+#	53 43 5b 90 										# timestamp (change?)
+#	9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf				# random bytes (seriously!)
+#   bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 		# random bytes (seriously!)
+#	00													# Length of session id (start new session)
+#   00 66 												# Length of ciphers supported list
+#	c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88			# 2 byte list of supported ciphers
+#   00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c	# 2 byte list of supported ciphers cont
+#   c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09	# 2 byte list of supported ciphers cont
+#   c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44	# 2 byte list of supported ciphers cont
+#   c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c	# 2 byte list of supported ciphers cont
+#   c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11	# 2 byte list of supported ciphers cont
+#   00 08 00 06 00 03 00 ff  							# 2 byte list of supported ciphers cont
+#	01 													# Length of compression methods
+#	00 													# Null compression (none)
+#	00 49												# Length of TLS extension list
+#	00 0b 00 04 03 00 01 02								# Elliptic curve point formats extension
+#	00 0a 00 34  00 32 00 0e 00 0d 00 19				# Elliptic curve
+#   00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08	# Elliptic curve cont
+#   00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13	# Elliptic curve cont
+#   00 01 00 02 00 03 00 0f  00 10 00 11				# Elliptic curve cont
+#	00 23 00 00											# TLS sessions ticket supported
+#   00 0f 00 01 01										# Heartbeat extension
+##### End Hello Packet #####
+
+    return hello
+
+# Builds and returns heartbleed packet that matches with tls version
+def build_hb():
+
+    hb = h2bin('''
+    18 ''' + tls_ver() + ''' 00 03
+    01 40 00
+    ''')
+
+##### Heartbleed Packet Layout #####
+#   18													# TLS Record Type (heartbeat) 
+#	+ tls_ver() + 										# TLS version
+#	00 03												# Length
+#   01 													# Heartbeat request
+#	40 00												# Length (16384 bytes)
+##### End Heartbleed Packet #####
+    
+    return hb
+
+# Builds and sends hb packet with zero size
+def build_empty_hb():
+
+    hb = h2bin('''
+    18 ''' + tls_ver() + ''' 00 03
+    01 00 00
+    ''')
+
+##### Heartbleed Packet Layout #####
+#   18													# TLS Record Type (heartbeat) 
+#	+ tls_ver() + 										# TLS version
+#	00 03												# Length
+#   01 													# Heartbeat request
+#	40 00												# Length (16384 bytes)
+##### End Heartbleed Packet #####
+    
+    return hb
+
+# Receives data from socket for specified length
+def recvall(s, length):
+    global opts
+    endtime = time.time() + opts.timeout
+    rdata = ''
+    remain = length
+
+    while remain > 0:
+        rtime = endtime - time.time() 
+        if rtime < 0:
+            return None
+        r, w, e = select.select([s], [], [], 5)
+        if s in r:
+            try:
+                data = s.recv(remain)
+            except socket.error:
+                # Should this be OK, as the server has sent a rst most likely and is therefore likely patched?
+                print 'UNKNOWN: Server ' + opts.host + ' closed connection after sending heartbeat. Likely the server has been patched.'
+                sys.exit(3)
+            # EOF?
+            if not data:
+                return None
+            rdata += data
+            remain -= len(data)
+    return rdata
+        
+# Receives messages and handles accordingly
+def recvmsg(s):
+    global opts
+    hdr = recvall(s, 5)
+    if hdr is None:
+        return None, None, None
+    typ, ver, ln = struct.unpack('>BHH', hdr)
+    pay = recvall(s, ln)
+    if pay is None:
+        return None, None, None
+    if opts.verbose == True:
+        print ' ... received message: type = %d, ver = %04x, length = %d, pay = %02x' % (typ, ver, len(pay), ord(pay[0]))
+    return typ, ver, pay
+
+# Sends empty hb packet
+def hit_hb(s, hb):
+    global opts
+
+    if opts.verbose == True:
+       print 'Sending malformed heartbeat packet...'
+
+    try:
+        s.send(hb)
+    except socket.error:
+        print 'UNKNOWN: Error sending heartbeat to ' + opts.host
+        sys.exit(3)
+
+    while True:
+        typ, ver, pay = recvmsg(s)
+        if typ == None:
+            returncode = 0
+            break
+
+        if typ == 24:
+            if pay > 3:
+                returncode = 2    # vulnerable
+                break
+            else:
+                returncode = 0
+                break
+
+        if typ == 21:    # TLS mismatch, hopefully we don't find this
+            returncode = 0
+            break
+
+    #Outside of while
+    if returncode == 0: # Not vulnerable message
+        if opts.version == 3: #respond with ssl instead of tls
+            message = 'SSLv3.0 is not vulnerable. '
+        else:
+            message = 'TLSv1.' + str(opts.version) + ' is not vulnerable. '
+    else: # vulnerable message
+        if opts.version == 3: #respond with ssl instead of tls
+            message = 'SSLv3.0 is vulnerable. '
+        else:
+            message = 'TLSv1.' + str(opts.version) + ' is vulnerable. '
+
+    return returncode, message
+
+# Prints nagios style output and exit codes
+def print_output(exitcode, outputmessage):
+
+    if exitcode == 2:
+        print 'CRITICAL: Server ' + opts.host + ' ' + outputmessage
+    else:
+        print 'OK: Server ' + opts.host + ' ' + outputmessage
+
+    sys.exit(exitcode)
+
+# Outputs packets as hex, used for verbose output
+def hexdump(s):
+
+    for b in xrange(0, len(s), 16):
+        lin = [c for c in s[b : b + 16]]
+        hxdat = ' '.join('%02X' % ord(c) for c in lin)
+        pdat = ''
+        for c in lin:
+            if 32 <= ord(c) <= 126:
+                pdat += c
+            else:
+                pdat += '.'
+        print '  %04x: %-48s %s' % (b, hxdat, pdat)
+    print
+
+# Initiates connection and handles initial hello\hb sending
+def connect(hb):
+    global opts
+ 
+    if opts.udp == True:
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    else:
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    
+    s.settimeout(opts.timeout)
+
+    try: 
+        s.connect((opts.host, opts.port))
+    except socket.error:
+        print 'UNKNOWN: Connecton to server ' + opts.host + ' could not be established.'
+        sys.exit(3)
+
+    hello = build_hello()
+
+    if opts.verbose == True:
+        print 'Sending hello packet...'
+
+    try:
+        s.send(hello)
+    except socket.error:
+        print 'UNKNOWN: Error sending hello to ' + opts.host
+        sys.exit(3)
+
+    while True:
+        typ, ver, pay = recvmsg(s)
+        if typ == None:
+            print 'UNKNOWN: Server ' + opts.host + ' closed connection without sending Server Hello.'
+            sys.exit(3)
+        # Look for server hello done message.
+        if typ == 22 and ord(pay[0]) == 0x0E:
+            if opts.verbose == True:
+                hexdump(pay)
+            break
+        else:
+            if opts.verbose == True:
+                hexdump(pay)
+            continue
+
+    if opts.verbose == True:
+        print 'Sending malformed heartbeat packet...'
+
+    try:
+        s.send(hb)
+    except socket.error:
+        print 'UNKNOWN: Error sending heartbeat to ' + opts.host
+        sys.exit(3)
+
+    return s
+
+def main():
+    global opts
+    opts, args = options.parse_args()
+    exitcode = 0
+    outputmessage = ''
+
+    if opts.version == -1: # no version was specified, loop.
+
+        if opts.verbose == True:
+            print 'Checking all supported TLS and SSL versions.'
+
+        for opts.version in [0, 1, 2, 3]:
+            hb = build_hb()
+            s = connect(hb)
+            returncode, message = hit_hb(s, hb)
+
+            if returncode > exitcode:
+                exitcode = returncode
+            outputmessage += message
+            
+    else: # version was specified
+        hb = build_hb()
+        s = connect(hb)
+        exitcode, outputmessage = hit_hb(s, hb)
+
+    print_output(exitcode, outputmessage)
+
+if __name__ == '__main__':
+    main()

+ 61 - 0
plugins-python/check_imap_login.in

@@ -0,0 +1,61 @@
+#!/usr/bin/python
+# vi:si:et:sw=4:sts=4:ts=4
+# -*- coding: UTF-8 -*-
+# -*- Mode: Python -*-
+#
+# Copyright (C) 2005 Bertera Pietro <pietro@bertera.it>
+
+# This file may be distributed and/or modified under the terms of
+# the GNU General Public License version 2 as published by
+# the Free Software Foundation.
+# This file is distributed without any warranty; without even the implied
+# warranty of merchantability or fitness for a particular purpose.
+# See "LICENSE.GPL" in the source distribution for more information.
+
+import sys, os, imaplib, getopt
+
+def usage():
+    print "-u <user>"
+    print "-p <password>"
+    print "-s use SSL"
+    print "-H <host>"
+
+def main():
+	try:
+	    opts, args = getopt.getopt(sys.argv[1:], "u:p:sH:")	
+    except getopt.GetoptError:
+        usage()
+        return 3
+    
+    user = host = password = use_ssl = None
+    
+    for o, a in opts:
+        if o == "-u":
+            user = a
+        elif o == "-p":
+            password = a
+        elif o == "-s":
+            use_ssl = True
+        elif o == "-H":
+            host = a  
+    if user == None or password == None or host == None:
+        usage()
+        return 1
+    
+    if use_ssl:
+        M = imaplib.IMAP4_SSL(host=host)
+    else:
+    	M = imaplib.IMAP4(host)
+    
+    try:	
+        M.login(user, password)
+	except Exception, e:
+        print "CRITICAL: IMAP Login not Successful: %s" % e
+        sys.exit(2)
+    
+    M.logout()
+    print "OK IMAP Login Successful"
+    return 0
+
+if __name__ == "__main__":
+        sys.exit(main())

+ 300 - 0
plugins-python/check_ncpa.in

@@ -0,0 +1,300 @@
+#!@PYTHON@
+"""
+SYNOPSIS
+
+
+"""
+import sys
+import optparse
+import traceback
+import ssl
+
+# Python 2/3 Compatibility imports
+
+try:
+    import json
+except ImportError:
+    import simplejson as json
+
+try:
+    import urllib.request
+    import urllib.parse
+    import urllib.error
+except ImportError:
+    import urllib2
+    import urllib
+
+try:
+    urlencode = urllib.parse.urlencode
+except AttributeError:
+    urlencode = urllib.urlencode
+
+try:
+    urlopen = urllib.request.urlopen
+except AttributeError:
+    urlopen = urllib2.urlopen
+
+try:
+    urlquote = urllib.parse.quote
+except AttributeError:
+    urlquote = urllib.quote
+
+import shlex
+import re
+import signal
+
+__VERSION__ = '1.1.0'
+
+def pretty(d, indent=0, indenter=' ' * 4):
+    info_str = ''
+    for key, value in list(d.items()):
+        info_str += indenter * indent + str(key)
+        if isinstance(value, dict):
+            info_str += '/\n'
+            info_str += pretty(value, indent + 1, indenter)
+        else:
+            info_str += ': ' + str(value) + '\n'
+    return info_str
+
+
+def parse_args():
+    version = 'check_ncpa.py, Version %s' % __VERSION__
+
+    parser = optparse.OptionParser()
+    parser.add_option("-H", "--hostname", help="The hostname to be connected to.")
+    parser.add_option("-M", "--metric", default='',
+                      help="The metric to check, this is defined on client "
+                           "system. This would also be the plugin name in the "
+                           "plugins directory. Do not attach arguments to it, "
+                           "use the -a directive for that. DO NOT INCLUDE the api/ "
+                           "instruction.")
+    parser.add_option("-P", "--port", default=5693, type="int",
+                      help="Port to use to connect to the client.")
+    parser.add_option("-w", "--warning", default=None, type="str",
+                      help="Warning value to be passed for the check.")
+    parser.add_option("-c", "--critical", default=None, type="str",
+                      help="Critical value to be passed for the check.")
+    parser.add_option("-u", "--units", default=None,
+                      help="The unit prefix (k, Ki, M, Mi, G, Gi, T, Ti) for b and B unit "
+                           "types which calculates the value returned.")
+    parser.add_option("-n", "--unit", default=None,
+                      help="Overrides the unit with whatever unit you define. "
+                           "Does not perform calculations. This changes the unit of measurement only.")
+    parser.add_option("-a", "--arguments", default=None,
+                      help="Arguments for the plugin to be run. Not necessary "
+                           "unless you're running a custom plugin. Given in the same "
+                           "as you would call from the command line. Example: -a '-w 10 -c 20 -f /usr/local'")
+    parser.add_option("-t", "--token", default='',
+                      help="The token for connecting.")
+    parser.add_option("-T", "--timeout", default=60, type="int",
+                      help="Enforced timeout, will terminate plugins after "
+                           "this amount of seconds. [%default]")
+    parser.add_option("-d", "--delta", action='store_true',
+                      help="Signals that this check is a delta check and a "
+                           "local state will kept.")
+    parser.add_option("-l", "--list", action='store_true',
+                      help="List all values under a given node. Do not perform "
+                           "a check.")
+    parser.add_option("-v", "--verbose", action='store_true',
+                      help='Print more verbose error messages.')
+    parser.add_option("-D", "--debug", action='store_true',
+                      help='Print LOTS of error messages. Used mostly for debugging.')
+    parser.add_option("-V", "--version", action='store_true',
+                      help='Print version number of plugin.')
+    parser.add_option("-q", "--queryargs", default=None,
+                      help='Extra query arguments to pass in the NCPA URL.')
+    parser.add_option("-s", "--secure", action='store_true', default=False,
+                      help='Require successful certificate verification. Does not work on Python < 2.7.9.')
+    parser.add_option("-p", "--performance", action='store_true', default=False,
+                      help='Print performance data even when there is none. '
+                           'Will print data matching the return code of this script')
+    options, _ = parser.parse_args()
+
+    if options.version:
+        print(version)
+        sys.exit(0)
+
+    if options.arguments and options.metric and not 'plugin' in options.metric:
+        parser.print_help()
+        parser.error('You cannot specify arguments without running a custom plugin.')
+
+    if not options.hostname:
+        parser.print_help()
+        parser.error("Hostname is required for use.")
+
+    elif not options.metric and not options.list:
+        parser.print_help()
+        parser.error('No metric given, if you want to list all possible items '
+                     'use --list.')
+
+    options.metric = re.sub(r'^/?(api/)?', '', options.metric)
+
+    return options
+
+
+# ~ The following are all helper functions. I would normally split these out into
+# ~ a new module but this needs to be portable.
+
+
+def get_url_from_options(options):
+    host_part = get_host_part_from_options(options)
+    arguments = get_arguments_from_options(options)
+    return '%s?%s' % (host_part, arguments)
+
+
+def get_host_part_from_options(options):
+    """Gets the address that will be queries for the JSON.
+
+    """
+    hostname = options.hostname
+    port = options.port
+
+    if not options.metric is None:
+        metric = urlquote(options.metric)
+    else:
+        metric = ''
+
+    arguments = get_check_arguments_from_options(options)
+    if not metric and not arguments:
+        api_address = 'https://%s:%d/api' % (hostname, port)
+    else:
+        api_address = 'https://%s:%d/api/%s/%s' % (hostname, port, metric, arguments)
+
+    return api_address
+
+
+def get_check_arguments_from_options(options):
+    """Gets the escaped URL for plugin arguments to be added
+    to the end of the host URL. This is different from the get_arguments_from_options
+    in that this is meant for the syntax when the user is calling a check, whereas the below
+    is when GET arguments need to be added.
+
+    """
+    arguments = options.arguments
+    if arguments is None:
+        return ''
+    else:
+        lex = shlex.shlex(arguments)
+        lex.whitespace_split = True
+        arguments = '/'.join([urlquote(x, safe='') for x in lex])
+        return arguments
+
+
+def get_arguments_from_options(options, **kwargs):
+    """Returns the http query arguments. If there is a list variable specified,
+    it will return the arguments necessary to query for a list.
+
+    """
+
+    # Note: Changed back to units due to the units being what is passed via the
+    # API call which can confuse people if they don't match
+    arguments = { 'token': options.token,
+                  'units': options.units }
+    
+    if not options.list:
+        arguments['warning'] = options.warning
+        arguments['critical'] = options.critical
+        arguments['delta'] = options.delta
+        arguments['check'] = 1
+        arguments['unit'] = options.unit
+
+    if options.queryargs:
+        for argument in options.queryargs.split(','):
+            key, value = argument.split('=')
+            arguments[key] = value
+
+    #~ Encode the items in the dictionary that are not None
+    return urlencode(dict((k, v) for k, v in list(arguments.items()) if v is not None))
+
+
+def get_json(options):
+    """Get the page given by the options. This will call down the url and
+    encode its finding into a Python object (from JSON).
+
+    """
+    url = get_url_from_options(options)
+
+    if options.verbose:
+        print('Connecting to: ' + url)
+
+    try:
+        ctx = ssl.create_default_context()
+        if not options.secure:
+            ctx.check_hostname = False
+            ctx.verify_mode = ssl.CERT_NONE
+        ret = urlopen(url, context=ctx)
+    except AttributeError:
+        ret = urlopen(url)
+
+    ret = ''.join(ret)
+
+    if options.verbose:
+        print('File returned contained:\n' + ret)
+
+    arr = json.loads(ret)
+
+    if 'value' in arr:
+        return arr['value']
+
+    return arr
+
+
+def run_check(info_json):
+    """Run a check against the remote host.
+
+    """
+    return info_json['stdout'], info_json['returncode']
+
+
+def show_list(info_json):
+    """Show the list of available options.
+
+    """
+    return pretty(info_json), 0
+
+
+def timeout_handler(threshold):
+    def wrapped(signum, frames):
+        stdout = "UNKNOWN: Execution exceeded timeout threshold of %ds" % threshold
+        print stdout
+        sys.exit(3)
+    return wrapped
+
+
+def main():
+    options = parse_args()
+
+    # We need to ensure that we will only execute for a certain amount of
+    # seconds.
+    signal.signal(signal.SIGALRM, timeout_handler(options.timeout))
+    signal.alarm(options.timeout)
+
+    try:
+
+        if options.version:
+            stdout = 'The version of this plugin is %s' % __VERSION__
+            return stdout, 0
+
+        info_json = get_json(options)
+        if options.list:
+            return show_list(info_json)
+        else:
+            stdout, returncode = run_check(info_json)
+            if options.performance and stdout.find("|") == -1:
+                performance = " | 'status'={};1;2;".format(returncode)
+                return "{}{}".format(stdout, performance), returncode
+            else:
+                return stdout, returncode
+    except Exception, e:
+        if options.debug:
+            return 'The stack trace:' + traceback.format_exc(), 3
+        elif options.verbose:
+            return 'An error occurred:' + str(e), 3
+        else:
+            return 'UNKNOWN: Error occurred while running the plugin. Use the verbose flag for more details.', 3
+
+
+if __name__ == "__main__":
+    stdout, returncode = main()
+    print(stdout)
+    sys.exit(returncode)

+ 11 - 0
plugins-root/Makefile.am

@@ -52,9 +52,20 @@ INSTALL_SUID = \
 	chmod $(setuid_root_mode) $(DESTDIR)$(libexecdir)/$$p; \
 	done
 
+INSTALL_NOSUID = \
+	for f in $(noinst_PROGRAMS) ; do \
+	p=$$f; \
+	echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(libexecdir)/$$p"; \
+	$(INSTALL_PROGRAM) $$p $(DESTDIR)$(libexecdir)/$$p; \
+	echo "NOTE: $(DESTDIR)$(libexecdir)/$$p expected to be chown/chmod by the package installer"; \
+	done
+
 install-root: $(noinst_PROGRAMS)
 	@$(INSTALL_SUID)
 
+install-packager: $(noinst_PROGRAMS)
+	@$(INSTALL_NOSUID)
+
 install-exec-local: $(noinst_PROGRAMS)
 	@TMPFILE=$(DESTDIR)$(libexecdir)/.setuid-$$$$; \
 	rm -f $$TMPFILE; \

+ 348 - 41
plugins-root/check_icmp.c

@@ -5,6 +5,7 @@
 * License: GPL
 * Copyright (c) 2005-2008 Nagios Plugins Development Team
 * Original Author : Andreas Ericsson <ae@op5.se>
+* Jitter, MOS and Score support added by Alessandro Ren <alessandro.ren@opservices.com>
 * 
 * Description:
 * 
@@ -124,18 +125,35 @@ typedef struct rta_host {
 	unsigned char icmp_type, icmp_code; /* type and code from errors */
 	unsigned short flags;        /* control/status flags */
 	double rta;                  /* measured RTA */
+	int			rta_status;
 	double rtmax;                /* max rtt */
 	double rtmin;                /* min rtt */
+	double jitter;                  /* measured jitter */
+	int			jitter_status;
+	double jitter_max;                /* jitter rtt */
+	double jitter_min;                /* jitter rtt */
+	double EffectiveLatency;
+	double mos;									/* Mean opnion score */
+	int			mos_status;
+	double	score;							/* score */
+	int			score_status;
+	u_int last_tdiff;
+	u_int	last_icmp_seq;        /* Last ICMP_SEQ to check out of order pkts */
 	unsigned char pl;            /* measured packet loss */
+	int			pl_status;
 	struct rta_host *next;       /* linked list */
+	int	order_status;
 } rta_host;
 
 #define FLAG_LOST_CAUSE 0x01  /* decidedly dead target. */
 
 /* threshold structure. all values are maximum allowed, exclusive */
 typedef struct threshold {
-	unsigned char pl;    /* max allowed packet loss in percent */
-	unsigned int rta;  /* roundtrip time average, microseconds */
+	unsigned char pl;			/* max allowed packet loss in percent */
+	unsigned int rta;			/* roundtrip time average, microseconds */
+	double jitter;	/* jitter time average, microseconds */
+	double mos;			/* MOS */
+	double score;		/* Score */
 } threshold;
 
 /* the data structure */
@@ -191,6 +209,7 @@ static int wait_for_reply(int, u_int);
 static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*);
 static int send_icmp_ping(int, struct rta_host *);
 static int get_threshold(char *str, threshold *th);
+static int get_threshold2(char *str, threshold *, threshold *, int type);
 static void run_checks(void);
 static void set_source_ip(char *);
 static int add_target(char *);
@@ -227,6 +246,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values
 static int min_hosts_alive = -1;
 float pkt_backoff_factor = 1.5;
 float target_backoff_factor = 1.5;
+int	rta_mode=0;
+int	pl_mode=0;
+int	jitter_mode=0;
+int	score_mode=0;
+int	mos_mode=0;
+int	order_mode=0;
 
 /** code start **/
 static void
@@ -440,10 +465,19 @@ main(int argc, char **argv)
 	table = NULL;
 
 	mode = MODE_RTA;
+	/* Default critical thresholds */
 	crit.rta = 500000;
 	crit.pl = 80;
+	crit.jitter = 50;
+	crit.mos= 3;
+	crit.score=70;
+	/* Default warning thresholds */
 	warn.rta = 200000;
 	warn.pl = 40;
+	warn.jitter = 40;
+	warn.mos= 3.5;
+	warn.score=80;
+	
 	protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP;
 	pkt_interval = 80000;  /* 80 msec packet interval by default */
 	packets = 5;
@@ -479,14 +513,14 @@ main(int argc, char **argv)
 
 	/* parse the arguments */
 	for(i = 1; i < argc; i++) {
-		while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) {
-			unsigned short size;
+		while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O")) != EOF) {
+			long size;
 			switch(arg) {
 			case 'v':
 				debug++;
 				break;
 			case 'b':
-				size = (unsigned short)strtol(optarg,NULL,0);
+				size = strtol(optarg,NULL,0);
 				if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
 				    size < MAX_PING_DATA) {
 					icmp_data_size = size;
@@ -540,7 +574,30 @@ main(int argc, char **argv)
 			case 'h': /* help */
 				print_help ();
 				exit (STATE_OK);
-			}
+			case 'R': /* RTA mode */
+				get_threshold2(optarg, &warn, &crit,1);
+        rta_mode=1;
+        break;
+			case 'P': /* packet loss mode */
+				get_threshold2(optarg, &warn, &crit,2);
+        pl_mode=1;
+        break;
+			case 'J': /* packet loss mode */
+				get_threshold2(optarg, &warn, &crit,3);
+      	jitter_mode=1;
+      	break;
+			case 'M': /* MOS mode */
+				get_threshold2(optarg, &warn, &crit,4);
+        mos_mode=1;
+        break;
+			case 'S': /* score mode */
+				get_threshold2(optarg, &warn, &crit,5);
+        score_mode=1;
+        break;
+			case 'O': /* out of order mode */
+        order_mode=1;
+        break;
+      }
 		}
 	}
 
@@ -589,6 +646,9 @@ main(int argc, char **argv)
 	if(warn.pl > crit.pl) warn.pl = crit.pl;
 	if(warn.rta > crit.rta) warn.rta = crit.rta;
 	if(warn_down > crit_down) crit_down = warn_down;
+	if(warn.jitter > crit.jitter) crit.jitter = warn.jitter;
+	if(warn.mos < crit.mos) warn.mos = crit.mos;
+	if(warn.score < crit.score) warn.score = crit.score;
 
 #ifdef HAVE_SIGACTION
 	sig_action.sa_sigaction = NULL;
@@ -735,6 +795,7 @@ wait_for_reply(int sock, u_int t)
 	struct icmp_ping_data data;
 	struct timeval wait_start, now;
 	u_int tdiff, i, per_pkt_wait;
+	double jitter_tmp;
 
 	/* if we can't listen or don't have anything to listen to, just return */
 	if(!t || !icmp_pkts_en_route) return 0;
@@ -813,12 +874,43 @@ wait_for_reply(int sock, u_int t)
 		host = table[ntohs(icp.icmp_seq)/packets];
 		tdiff = get_timevaldiff(&data.stime, &now);
 
+		if (host->last_tdiff>0) {
+			/* Calculate jitter */
+			if (host->last_tdiff > tdiff) {
+				jitter_tmp = host->last_tdiff - tdiff;
+			}
+			else {
+				jitter_tmp = tdiff - host->last_tdiff;
+			}
+			if (host->jitter==0) {
+				host->jitter=jitter_tmp;
+				host->jitter_max=jitter_tmp;
+				host->jitter_min=jitter_tmp;
+			}
+			else {
+				host->jitter+=jitter_tmp;
+				if (jitter_tmp < host->jitter_min)
+					host->jitter_min=jitter_tmp;
+				if (jitter_tmp > host->jitter_max)
+					host->jitter_max=jitter_tmp;
+			}
+			
+			/* Check if packets in order */
+			if (host->last_icmp_seq >= icp.icmp_seq)
+				host->order_status=STATE_CRITICAL;
+		}
+		host->last_tdiff=tdiff;
+		
+		host->last_icmp_seq=icp.icmp_seq;
+		
+		//printf("%d tdiff %d host->jitter %u  host->last_tdiff %u\n", icp.icmp_seq, tdiff, host->jitter, host->last_tdiff);
+		
 		host->time_waited += tdiff;
 		host->icmp_recv++;
 		icmp_recv++;
-		if (tdiff > host->rtmax)
+		if (tdiff > (int)host->rtmax)
 			host->rtmax = tdiff;
-		if (tdiff < host->rtmin)
+		if (tdiff < (int)host->rtmin)
 			host->rtmin = tdiff;
 
 		if(debug) {
@@ -997,6 +1089,7 @@ finish(int sig)
 	{"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
 	int hosts_ok = 0;
 	int hosts_warn = 0;
+	double R;
 
 	alarm(0);
 	if(debug > 1) printf("finish(%d) called\n", sig);
@@ -1012,6 +1105,7 @@ finish(int sig)
 	}
 
 	/* iterate thrice to calculate values, give output, and print perfparse */
+	status=STATE_OK;
 	host = list;
 	while(host) {
 		if(!host->icmp_recv) {
@@ -1027,19 +1121,104 @@ finish(int sig)
 			pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
 			rta = (double)host->time_waited / host->icmp_recv;
 		}
+		if (host->icmp_recv>1) {
+			host->jitter=(host->jitter / (host->icmp_recv - 1)/1000);
+			host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10;
+			if (host->EffectiveLatency < 160)
+			   R = 93.2 - (host->EffectiveLatency / 40);
+			else
+			   R = 93.2 - ((host->EffectiveLatency - 120) / 10);
+			R = R - (pl * 2.5);
+			if (R<0) R=0;
+			host->score = R;
+			host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R));
+		}
+		else {
+			host->jitter=0;
+			host->jitter_min=0;
+			host->jitter_max=0;
+			host->mos=0;
+		}
 		host->pl = pl;
 		host->rta = rta;
-		if(pl >= crit.pl || rta >= crit.rta) {
-			status = STATE_CRITICAL;
+
+		/* if no new mode selected, use old schema */
+		if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) {
+			rta_mode=1;
+			pl_mode=1;
 		}
-		else if(!status && (pl >= warn.pl || rta >= warn.rta)) {
-			status = STATE_WARNING;
-			hosts_warn++;
+
+		/* Check which mode is on and do the warn / Crit stuff */
+		if (rta_mode) {
+			if(rta >= crit.rta) {
+				status = STATE_CRITICAL;
+				host->rta_status=STATE_CRITICAL;
+			}
+			else if(status!=STATE_CRITICAL && (rta >= warn.rta)) {
+				status = STATE_WARNING;
+				hosts_warn++;
+				host->rta_status=STATE_WARNING;
+			}
+			else {
+				hosts_ok++;
+			}
 		}
-		else {
-			hosts_ok++;
+		if (pl_mode) {
+			if(pl >= crit.pl) {
+				status = STATE_CRITICAL;
+				host->pl_status=STATE_CRITICAL;
+			}
+			else if(status!=STATE_CRITICAL && (pl >= warn.pl)) {
+				status = STATE_WARNING;
+				hosts_warn++;
+				host->pl_status=STATE_WARNING;
+			}
+			else {
+				hosts_ok++;
+			}
+		}
+		if (jitter_mode) {
+			if(host->jitter >= crit.jitter) {
+				status = STATE_CRITICAL;
+				host->jitter_status=STATE_CRITICAL;
+			}
+			else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) {
+				status = STATE_WARNING;
+				hosts_warn++;
+				host->jitter_status=STATE_WARNING;
+			}
+			else {
+				hosts_ok++;
+			}
+		}
+		if (mos_mode) {
+			if(host->mos <= crit.mos) {
+				status = STATE_CRITICAL;
+				host->mos_status=STATE_CRITICAL;
+			}
+			else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) {
+				status = STATE_WARNING;
+				hosts_warn++;
+				host->mos_status=STATE_WARNING;
+			}
+			else {
+				hosts_ok++;
+			}
+		}
+		if (score_mode) {
+			if(host->score <= crit.score) {
+				status = STATE_CRITICAL;
+				host->score_status=STATE_CRITICAL;
+			}
+			else if(status!=STATE_CRITICAL && (host->score <= warn.score)) {
+				status = STATE_WARNING;
+				score_mode++;
+				host->score_status=STATE_WARNING;
+			}
+			else {
+				hosts_ok++;
+			}
 		}
-
 		host = host->next;
 	}
 	/* this is inevitable */
@@ -1049,17 +1228,20 @@ finish(int sig)
 		else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING;
 	}
 	printf("%s - ", status_string[status]);
-
+	
 	host = list;
 	while(host) {
-		if(debug) write(STDOUT_FILENO, "\n", 1);
+		
+		if(debug) puts("");
 		if(i) {
-			if(i < targets) write(STDOUT_FILENO, " :: ", 4);
-			else write(STDOUT_FILENO, "\n", 1);
+			if(i < targets) printf(" :: ");
+			else printf("\n");
 		}
 		i++;
 		if(!host->icmp_recv) {
 			status = STATE_CRITICAL;
+			host->rtmin=0;
+			host->jitter_min=0;
 			if(host->flags & FLAG_LOST_CAUSE) {
 				printf("%s: %s @ %s. rta nan, lost %d%%",
 					   host->name,
@@ -1072,25 +1254,86 @@ finish(int sig)
 			}
 		}
 		else {	/* !icmp_recv */
-			printf("%s: rta %0.3fms, lost %u%%",
-				   host->name, host->rta / 1000, host->pl);
+			printf("%s ", host->name);
+			/* rta text output */
+			if (rta_mode) {
+				if (status == STATE_OK)
+					printf("rta %0.3fms", host->rta / 1000);
+				else if (status==STATE_WARNING && host->rta_status==status)
+					printf("rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000);
+				else if (status==STATE_CRITICAL && host->rta_status==status)
+					printf("rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000);
+			}
+			/* pl text output */
+			if (pl_mode) {
+				if (status == STATE_OK)
+					printf("lost %u%%", host->pl);
+				else if (status==STATE_WARNING && host->pl_status==status)
+					printf("lost %u%% > %u%%", host->pl, warn.pl);
+				else if (status==STATE_CRITICAL && host->pl_status==status)
+					printf("lost %u%% > %u%%", host->pl, crit.pl);
+			}
+			/* jitter text output */
+			if (jitter_mode) {
+				if (status == STATE_OK)
+					printf("jitter %0.3fms", (float)host->jitter);
+				else if (status==STATE_WARNING && host->jitter_status==status)
+					printf("jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter);
+				else if (status==STATE_CRITICAL && host->jitter_status==status)
+					printf("jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter);
+			}
+			/* mos text output */
+			if (mos_mode) {
+				if (status == STATE_OK)
+					printf("MOS %0.1f", (float)host->mos);
+				else if (status==STATE_WARNING && host->mos_status==status)
+					printf("MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos);
+				else if (status==STATE_CRITICAL && host->mos_status==status)
+					printf("MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos);
+			}
+			/* score text output */
+			if (score_mode) {
+				if (status == STATE_OK)
+					printf("Score %u", (int)host->score);
+				else if (status==STATE_WARNING && host->score_status==status )
+					printf("Score %u < %u", (int)host->score, (int)warn.score);
+				else if (status==STATE_CRITICAL && host->score_status==status )
+					printf("Score %u < %u", (int)host->score, (int)crit.score);
+			}
+			/* order statis text output */
+			if (order_mode) {
+				if (status == STATE_OK)
+					printf("Packets in order");
+				else if (status==STATE_CRITICAL && host->order_status==status)
+					printf("Packets out of order");
+			}
 		}
-
 		host = host->next;
 	}
 
 	/* iterate once more for pretty perfparse output */
-	printf("|");
+	if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
+			printf("|");
+	}
+	i = 0;
 	host = list;
 	while(host) {
-		if(debug) write(STDOUT_FILENO, "\n", 1);
-		printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ",
-			   (targets > 1) ? host->name : "",
-			   host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000,
-			   (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl,
-			   (targets > 1) ? host->name : "", (float)host->rtmax / 1000,
-			   (targets > 1) ? host->name : "", (host->rtmin < DBL_MAX) ? (float)host->rtmin / 1000 : (float)0);
-
+		if(debug) puts("");
+		if (rta_mode && host->pl<100) {
+			printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ",(targets > 1) ? host->name : "", (float)host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, (targets > 1) ? host->name : "", (float)host->rtmax / 1000, (targets > 1) ? host->name : "", (float)host->rtmin / 1000);
+		}
+		if (pl_mode) {
+			printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl);
+		}
+		if (jitter_mode && host->pl<100) {
+			printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ", (targets > 1) ? host->name : "", (float)host->jitter, (float)warn.jitter, (float)crit.jitter, (targets > 1) ? host->name : "", (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",(float)host->jitter_min / 1000);
+		}
+		if (mos_mode && host->pl<100) {
+			printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (targets > 1) ? host->name : "", (float)host->mos, (float)warn.mos, (float)crit.mos);
+		}
+		if (score_mode && host->pl<100) {
+			printf("%sscore=%u;%u;%u;0;100 ", (targets > 1) ? host->name : "", (int)host->score, (int)warn.score, (int)crit.score);
+		}
 		host = host->next;
 	}
 
@@ -1165,8 +1408,20 @@ add_target_ip(char *arg, struct in_addr *in)
 	/* fill out the sockaddr_in struct */
 	host->saddr_in.sin_family = AF_INET;
 	host->saddr_in.sin_addr.s_addr = in->s_addr;
-
 	host->rtmin = DBL_MAX;
+	host->rtmax = 0;
+	host->jitter=0;
+	host->jitter_max=0;
+	host->jitter_min=DBL_MAX;
+	host->last_tdiff=0;
+	host->order_status=STATE_OK;
+	host->last_icmp_seq=0;
+	host->rta_status=0;
+	host->pl_status=0;
+	host->jitter_status=0;
+	host->mos_status=0;
+	host->score_status=0;
+	host->pl_status=0;
 
 	if(!list) list = cursor = host;
 	else cursor->next = host;
@@ -1283,7 +1538,7 @@ get_timevar(const char *str)
 	else if(u == 's') factor = 1000000;	/* seconds */
 	if(debug > 2) printf("factor is %u\n", factor);
 
-	i = strtoul(str, &ptr, 0);
+	i =  strtoul(str, &ptr, 0);
 	if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1)
 		return i * factor;
 
@@ -1329,6 +1584,46 @@ get_threshold(char *str, threshold *th)
 	return 0;
 }
 
+/* not too good at checking errors, but it'll do (main() should barfe on -1) */
+static int
+get_threshold2(char *str, threshold *warn, threshold *crit, int type)
+{
+	char *p = NULL, i = 0;
+
+	if(!str || !strlen(str) || !warn || !crit) return -1;
+	/* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */
+	p = &str[strlen(str) - 1];
+	while(p != &str[0]) {
+		if( (*p == 'm') || (*p == '%') ) *p = '\0';
+		else if(*p == ',' && i) {
+			*p = '\0';	/* reset it so get_timevar(str) works nicely later */
+			if (type==1)
+				crit->rta = atof(p+1)*1000;
+			else if  (type==2)
+				crit->pl = (unsigned char)strtoul(p+1, NULL, 0);
+			else if  (type==3)
+				crit->jitter = atof(p+1);
+			else if (type==4)
+				crit->mos = atof(p+1);
+			else if (type==5)
+				crit->score = atof(p+1);
+		}
+		i = 1;
+		p--;
+	}
+	if (type==1)
+		warn->rta = atof(p)*1000;
+	else if (type==2)
+		warn->pl = (unsigned char)strtoul(p, NULL, 0);
+	if (type==3)
+		warn->jitter = atof(p);
+	else if (type==4)
+		warn->mos = atof(p);
+	else if (type==5)
+		warn->score = atof(p);
+	return 0;
+}
+
 unsigned short
 icmp_checksum(unsigned short *p, int n)
 {
@@ -1353,10 +1648,10 @@ icmp_checksum(unsigned short *p, int n)
 void
 print_help(void)
 {
-
   /*print_revision (progname);*/ /* FIXME: Why? */
-
   printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
+  
+  printf ("Jiiter, MOS and Score support added by Alesssandro Ren <alessandro.ren@opservices.com.br>\n");
   printf (COPYRIGHT, copyright, email);
 
   printf ("\n\n");
@@ -1365,15 +1660,27 @@ print_help(void)
 
   printf (UT_HELP_VRSN);
   printf (UT_EXTRA_OPTS);
-
-  printf (" %s\n", "-H");
-  printf ("    %s\n", _("specify a target"));
-  printf (" %s\n", "-w");
+	printf (" %s\n", "-w");
   printf ("    %s", _("warning threshold (currently "));
   printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
   printf (" %s\n", "-c");
   printf ("    %s", _("critical threshold (currently "));
   printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl);
+
+  printf (" %s\n", "-R");
+  printf ("    %s\n", _("RTA, round trip average,  mode  warning,critical, ex. 100ms,200ms unit in ms"));
+  printf (" %s\n", "-P");
+  printf ("    %s\n", _("packet loss mode, ex. 40%,50% , unit in %"));
+  printf (" %s\n", "-J");
+  printf ("    %s\n", _("jitter mode  warning,critical, ex. 40.000ms,50.000ms , unit in ms "));
+  printf (" %s\n", "-M");
+  printf ("    %s\n", _("MOS mode, between 0 and 4.4  warning,critical, ex. 3.5,3.0"));
+  printf (" %s\n", "-S");
+  printf ("    %s\n", _("score  mode, max value 100  warning,critical, ex. 80,70 "));
+  printf (" %s\n", "-O");
+  printf ("    %s\n", _("detect out of order ICMP packts "));
+  printf (" %s\n", "-H");
+  printf ("    %s\n", _("specify a target"));
   printf (" %s\n", "-s");
   printf ("    %s\n", _("specify a source IP address or device name"));
   printf (" %s\n", "-n");
@@ -1402,9 +1709,9 @@ print_help(void)
   printf ("    %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN);
   printf (" %s\n", "-v");
   printf ("    %s\n", _("verbose"));
-
   printf ("\n");
   printf ("%s\n", _("Notes:"));
+  printf ("%s\n", _("If not mode R,P,J,M,S or O is informed, default icmp behavior, RTA and packet loss"));
   printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
   printf ("\n");
   printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));

+ 19 - 6
plugins-scripts/check_disk_smb.pl

@@ -22,7 +22,7 @@ require 5.004;
 use POSIX;
 use strict;
 use Getopt::Long;
-use vars qw($opt_P $opt_V $opt_h $opt_H $opt_k $opt_s $opt_W $opt_u $opt_p $opt_w $opt_c $opt_a $verbose);
+use vars qw($opt_P $opt_V $opt_m $opt_h $opt_H $opt_k $opt_s $opt_W $opt_u $opt_p $opt_w $opt_c $opt_a $opt_C $verbose);
 use vars qw($PROGNAME);
 use FindBin;
 use lib "$FindBin::Bin";
@@ -45,6 +45,7 @@ GetOptions
 	 "V"   => \$opt_V, "version"    => \$opt_V,
 	 "h"   => \$opt_h, "help"       => \$opt_h,
 	 "k"   => \$opt_k, "kerberos"   => \$opt_k,
+	 "m=s" => \$opt_m, "maxprotocol=s" => \$opt_m,
 	 "w=s" => \$opt_w, "warning=s"  => \$opt_w,
 	 "c=s" => \$opt_c, "critical=s" => \$opt_c,
 	 "p=s" => \$opt_p, "password=s" => \$opt_p,
@@ -52,7 +53,8 @@ GetOptions
 	 "s=s" => \$opt_s, "share=s"    => \$opt_s,
 	 "W=s" => \$opt_W, "workgroup=s" => \$opt_W,
 	 "H=s" => \$opt_H, "hostname=s" => \$opt_H,
-	 "a=s" => \$opt_a, "address=s" => \$opt_a);
+	 "a=s" => \$opt_a, "address=s" => \$opt_a,
+	 "C=s" => \$opt_C, "configfile=s" => \$opt_C);
 
 if ($opt_V) {
 	print_revision($PROGNAME,'@NP_VERSION@'); #'
@@ -82,6 +84,9 @@ defined($user) || usage("Invalid user: $opt_u\n");
 defined($opt_p) || ($opt_p = shift @ARGV) || ($opt_p = "");
 my $pass = $1 if ($opt_p =~ /(.*)/);
 
+defined($opt_m) || ($opt_m = shift @ARGV) || ($opt_m = "");
+my $maxprotocol = $1 if ($opt_m =~ /(.*)/);
+
 ($opt_w) || ($opt_w = shift @ARGV) || ($opt_w = 85);
 my $warn = $1 if ($opt_w =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
 ($warn) || usage("Invalid warning threshold: $opt_w\n");
@@ -90,6 +95,10 @@ my $warn = $1 if ($opt_w =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
 my $crit = $1 if ($opt_c =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
 ($crit) || usage("Invalid critical threshold: $opt_c\n");
 
+($opt_C) || ($opt_C = shift @ARGV) || ($opt_C = "");
+my $configfile = $opt_C if ($opt_C);
+usage("Unable to read config file $configfile\n") if ($configfile) && (! -r $configfile);
+
 # Execute the given command line and return anything it writes to STDOUT and/or
 # STDERR.  (This might be useful for other plugins, too, so it should possibly
 # be moved to utils.pm.)
@@ -187,10 +196,12 @@ my @cmd = (
 	$smbclient,
 	"//$host/$share",
 	"-U", "$user%$pass",
+	defined($maxprotocol) ? ("-m", $maxprotocol) : (),
 	defined($workgroup) ? ("-W", $workgroup) : (),
 	defined($address) ? ("-I", $address) : (),
 	defined($opt_P) ? ("-p", $opt_P) : (),
 	defined($opt_k) ? ("-k") : (),
+	defined($configfile) ? ("-s, $configfile") : (),
 	"-c", "du"
 );
 
@@ -289,8 +300,9 @@ print "$state\n" if ($verbose);
 exit $ERRORS{$state};
 
 sub print_usage () {
-	print "Usage: $PROGNAME -H <host> -s <share> -u <user> -p <password> 
-      -w <warn> -c <crit> [-W <workgroup>] [-P <port>] [-a <IP>]\n";
+	print "Usage: $PROGNAME -H <host> -s <share> -u <user> 
+      -p <password> -w <warn> -c <crit> [-W <workgroup>] [-P <port>] 
+      [-a <IP>] [-C <configfile>]\n";
 }
 
 sub print_help () {
@@ -316,12 +328,13 @@ Perl Check SMB Disk plugin for Nagios
    Password to log in to server. (Defaults to an empty password)
 -w, --warning=INTEGER or INTEGER[kMG]
    Percent of used space at which a warning will be generated (Default: 85%)
-      
 -c, --critical=INTEGER or INTEGER[kMG]
    Percent of used space at which a critical will be generated (Defaults: 95%)
 -P, --port=INTEGER
    Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default)
-   
+-C, --configfile=STRING
+   Path to configfile which should be used by smbclient (Defaults to smb.conf of your smb installation)
+
    If thresholds are followed by either a k, M, or G then check to see if that
    much disk space is available (kilobytes, Megabytes, Gigabytes)
 

+ 12 - 2
plugins-scripts/check_log.sh

@@ -169,6 +169,16 @@ while test -n "$1"; do
     shift
 done
 
+if [ "$oldlog" = "" ]; then
+	echo "Log check error: You must supply an Old Log File name using '-O'!"
+	exit "$STATE_UNKNOWN"
+fi
+rc=`echo "$oldlog" | grep -q -- "^-"; echo $?`
+if [ $rc -eq 0 ]; then
+	echo "Log check error: You must supply an Old Log File name using '-O'!"
+	exit "$STATE_UNKNOWN"
+fi
+
 # If the source log file doesn't exist, exit
 
 if [ ! -e "$logfile" ]; then
@@ -205,10 +215,10 @@ fi
 diff "$logfile" "$oldlog" | grep -v "^>" > "$tempdiff"
 
 # Count the number of matching log entries we have
-count=$(grep -c "$query" "$tempdiff")
+count=$(egrep -c "$query" "$tempdiff")
 
 # Get the last matching entry in the diff file
-lastentry=$(grep "$query" "$tempdiff" | tail -1)
+lastentry=$(egrep "$query" "$tempdiff" | tail -1)
 
 rm -f "$tempdiff"
 cat "$logfile" > "$oldlog"

+ 98 - 14
plugins-scripts/check_mailq.pl

@@ -28,9 +28,9 @@
 use POSIX;
 use strict;
 use Getopt::Long;
-use vars qw($opt_V $opt_h $opt_v $verbose $PROGNAME $opt_w $opt_c $opt_t $opt_s
-					$opt_M $mailq $status $state $msg $msg_q $msg_p $opt_W $opt_C $mailq @lines
-					%srcdomains %dstdomains);
+use vars qw($opt_V $opt_h $opt_v $verbose $PROGNAME $opt_w $opt_c $opt_t $opt_s $opt_d
+					$opt_M $mailq $status $state $msg $msg_q $msg_p $opt_W $opt_C $mailq $mailq_args
+					@lines %srcdomains %dstdomains);
 use FindBin;
 use lib "$FindBin::Bin";
 use lib '@libexecdir@';
@@ -49,6 +49,8 @@ $PROGNAME = "check_mailq";
 $mailq = 'sendmail';	# default
 $msg_q = 0 ;
 $msg_p = 0 ;
+# If appended, must start with a space
+$mailq_args = '' ;
 $state = $ERRORS{'UNKNOWN'};
 
 Getopt::Long::Configure('bundling');
@@ -58,6 +60,10 @@ if ($status){
 	exit $ERRORS{"UNKNOWN"};
 }
 
+if ($opt_d) {
+	$mailq_args = $mailq_args . ' -C ' . $opt_d;
+}
+
 if ($opt_s) {
 	if ($utils::PATH_TO_SUDO ne "") {
 		if (-x $utils::PATH_TO_SUDO) {
@@ -313,19 +319,19 @@ elsif ( $mailq eq "postfix" ) {
      ## open mailq
 	if ( defined $utils::PATH_TO_MAILQ ) {
 		if (-x $utils::PATH_TO_MAILQ) {
-			if (! open (MAILQ, "$utils::PATH_TO_MAILQ | ")) {
-				print "ERROR: $utils::PATH_TO_MAILQ returned an error\n";
+			if (! open (MAILQ, "$utils::PATH_TO_MAILQ$mailq_args | ")) {
+				print "ERROR: $utils::PATH_TO_MAILQ$mailq_args returned an error\n";
 				exit $ERRORS{'UNKNOWN'};
 			}
 		}
 		else {
 			if ( $sudo ne "" ) {
-				if (! open (MAILQ, "$sudo $utils::PATH_TO_MAILQ | " ) ) {
-					print "ERROR: $utils::PATH_TO_MAILQ is not executable with sudo by (uid $>:gid($)))\n";
+				if (! open (MAILQ, "$sudo $utils::PATH_TO_MAILQ$mailq_args | " ) ) {
+					print "ERROR: $utils::PATH_TO_MAILQ$mailq_args is not executable with sudo by (uid $>:gid($)))\n";
 					exit $ERRORS{'UNKNOWN'};
 				}
 			} else {
-				print "ERROR: $utils::PATH_TO_MAILQ is not executable by (uid $>:gid($))) and sudo is not set in utils.pm\n";
+				print "ERROR: $utils::PATH_TO_MAILQ$mailq_args is not executable by (uid $>:gid($))) and sudo is not set in utils.pm\n";
 				exit $ERRORS{'UNKNOWN'};
 			}
 		}
@@ -338,7 +344,7 @@ elsif ( $mailq eq "postfix" ) {
 	@lines = reverse <MAILQ>;
 
         if ( $? ) {
-		print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ",$/;
+		print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_MAILQ$mailq_args",$/;
 		exit $ERRORS{CRITICAL};
         }
 
@@ -351,7 +357,7 @@ elsif ( $mailq eq "postfix" ) {
 	}elsif ($lines[0]=~/Mail queue is empty/) {
 		$msg_q = 0;
         }else{
-                print "Couldn't match $utils::PATH_TO_MAILQ output\n";
+                print "Couldn't match $utils::PATH_TO_MAILQ$mailq_args output\n";
                 exit   $ERRORS{'UNKNOWN'};
         }
 
@@ -520,7 +526,47 @@ elsif ( $mailq eq "exim" ) {
 		$state = $ERRORS{'CRITICAL'};
 	}
 } # end of ($mailq eq "exim")
+elsif ( $mailq eq "opensmtpd" ) {
+	## open smtpctl
+	if ( defined $utils::PATH_TO_SMTPCTL && -x $utils::PATH_TO_SMTPCTL ) {
+		if (! open (MAILQ, "$sudo $utils::PATH_TO_SMTPCTL show queue | " ) ) {
+			print "ERROR: could not open $utils::PATH_TO_SMTPCTL \n";
+			exit $ERRORS{'UNKNOWN'};
+		}
+	}elsif( defined $utils::PATH_TO_SMTPCTL){
+		unless (-x $utils::PATH_TO_SMTPCTL) {
+			print "ERROR: $utils::PATH_TO_SMTPCTL is not executable by (uid $>:gid($)))\n";
+			exit $ERRORS{'UNKNOWN'};
+		}
+	} else {
+		print "ERROR: \$utils::PATH_TO_SMTPCTL is not defined\n";
+		exit $ERRORS{'UNKNOWN'};
+	}
+
+	while (<MAILQ>) {
+
+		# 34357f5b3f589feb|inet4|mta||f.someone@domaina.org|no-reply@domainb.com|no-reply@domainb.com|1498235412|1498581012|0|25|pending|17168|Network error on destination MXs
+		if (/^.*|.*|.*|.*|.*|.*|.*|.*|.*|.*|.*|.*|.*|.*$/) {
+			$msg_q++ ;
+		}
+	}
+	close(MAILQ);
 
+	if ( $? ) {
+		print "CRITICAL: Error code ".($?>>8)." returned from $utils::PATH_TO_SMTPCTL",$/;
+		exit $ERRORS{CRITICAL};
+	}
+	if ($msg_q < $opt_w) {
+		$msg = "OK: $mailq mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
+		$state = $ERRORS{'OK'};
+	}elsif ($msg_q >= $opt_w  && $msg_q < $opt_c) {
+		$msg = "WARNING: $mailq mailq is $msg_q (threshold w = $opt_w)";
+		$state = $ERRORS{'WARNING'};
+	}else {
+		$msg = "CRITICAL: $mailq mailq is $msg_q (threshold c = $opt_c)";
+		$state = $ERRORS{'CRITICAL'};
+	}
+} # end of ($mailq eq "opensmtpd")
 elsif ( $mailq eq "nullmailer" ) {
 	## open mailq
 	if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) {
@@ -558,6 +604,39 @@ elsif ( $mailq eq "nullmailer" ) {
 	}
 } # end of ($mailq eq "nullmailer")
 
+elsif ( $mailq eq "opensmtp" ) {
+	## open mailq
+	if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) {
+		if (! open (MAILQ, "$sudo $utils::PATH_TO_MAILQ | " ) ) {
+			print "ERROR: could not open $utils::PATH_TO_MAILQ \n";
+			exit $ERRORS{'UNKNOWN'};
+		}
+	}elsif( defined $utils::PATH_TO_MAILQ){
+		unless (-x $utils::PATH_TO_MAILQ) {
+			print "ERROR: $utils::PATH_TO_MAILQ is not executable by (uid $>:gid($)))\n";
+			exit $ERRORS{'UNKNOWN'};
+		}
+	} else {
+		print "ERROR: \$utils::PATH_TO_MAILQ is not defined\n";
+		exit $ERRORS{'UNKNOWN'};
+	}
+
+	$msg_q++ while (<MAILQ>);
+
+	close(MAILQ) ;
+	if ($msg_q < $opt_w) {
+		$msg = "OK: $mailq mailq ($msg_q) is below threshold ($opt_w/$opt_c)";
+		$state = $ERRORS{'OK'};
+	}elsif ($msg_q >= $opt_w  && $msg_q < $opt_c) {
+		$msg = "WARNING: $mailq mailq is $msg_q (threshold w = $opt_w)";
+		$state = $ERRORS{'WARNING'};
+	}else {
+		$msg = "CRITICAL: $mailq mailq is $msg_q (threshold c = $opt_c)";
+		$state = $ERRORS{'CRITICAL'};
+	}
+} # end of ($mailq eq "opensmtp")
+
+
 # Perfdata support
 print "$msg|unsent=$msg_q;$opt_w;$opt_c;0\n";
 exit $state;
@@ -576,7 +655,8 @@ sub process_arguments(){
 		 "w=i" => \$opt_w, "warning=i"  => \$opt_w,   # warning if above this number
 		 "c=i" => \$opt_c, "critical=i" => \$opt_c,	  # critical if above this number
 		 "t=i" => \$opt_t, "timeout=i"  => \$opt_t,
-		 "s"   => \$opt_s, "sudo"       => \$opt_s
+		 "s"   => \$opt_s, "sudo"       => \$opt_s,
+		 "d:s" => \$opt_d, "configdir:s" => \$opt_d
 		 );
 
 	if ($opt_V) {
@@ -618,7 +698,7 @@ sub process_arguments(){
 	}
 
 	if (defined $opt_M) {
-		if ($opt_M =~ /^(sendmail|qmail|postfix|exim|nullmailer)$/) {
+		if ($opt_M =~ /^(sendmail|qmail|postfix|exim|nullmailer|opensmtpd)$/) {
 			$mailq = $opt_M ;
 		}elsif( $opt_M eq ''){
 			$mailq = 'sendmail';
@@ -648,6 +728,10 @@ sub process_arguments(){
 		{
 			$mailq = 'nullmailer';
 		}
+		elsif (defined $utils::PATH_TO_SMTPCTL && -x $utils::PATH_TO_SMTPCTL)
+		{
+			$mailq = 'opensmtpd';
+		}
 		else {
 			$mailq = 'sendmail';
 		}
@@ -657,7 +741,7 @@ sub process_arguments(){
 }
 
 sub print_usage () {
-	print "Usage: $PROGNAME -w <warn> -c <crit> [-W <warn>] [-C <crit>] [-M <MTA>] [-t <timeout>] [-s] [-v]\n";
+	print "Usage: $PROGNAME -w <warn> -c <crit> [-W <warn>] [-C <crit>] [-M <MTA>] [-t <timeout>] [-s] [-d <CONFIGDIR>] [-v]\n";
 }
 
 sub print_help () {
@@ -673,7 +757,7 @@ sub print_help () {
 	print "-W (--Warning)   = Min. number of messages for same domain in queue to generate warning\n";
 	print "-C (--Critical)  = Min. number of messages for same domain in queue to generate critical alert ( W < C )\n";
 	print "-t (--timeout)   = Plugin timeout in seconds (default = $utils::TIMEOUT)\n";
-	print "-M (--mailserver) = [ sendmail | qmail | postfix | exim | nullmailer ] (default = autodetect)\n";
+	print "-M (--mailserver) = [ sendmail | qmail | postfix | exim | nullmailer | opensmtpd ] (default = autodetect)\n";
 	print "-h (--help)\n";
 	print "-V (--version)\n";
 	print "-v (--verbose)   = debugging output\n";

+ 15 - 8
plugins-scripts/check_sensors.sh

@@ -42,23 +42,30 @@ case "$1" in
 		exit "$STATE_OK"
 		;;
 	*)
+		ignorefault=0
+		if test "$1" = "-i" -o "$1" = "--ignore-fault"; then
+			ignorefault=1
+		fi
+
 		sensordata=$(sensors 2>&1)
 		status=$?
+
+		# Set a default
+		text="SENSOR UNKNOWN"
+		exit=$STATE_UNKNOWN
+
 		if [ $status -eq 127 ] ; then
 			text="SENSORS UNKNOWN - command not found (did you install lmsensors?)"
 			exit=$STATE_UNKNOWN
 		elif [ "$status" != 0 ] ; then
 			text="WARNING - sensors returned state $status"
 			exit=$STATE_WARNING
-		elif echo "${sensordata}" | egrep -q ALARM > /dev/null ; then
+		elif echo "${sensordata}" | egrep -q ALARM >/dev/null ; then
 			text="SENSOR CRITICAL - Sensor alarm detected!"
 			exit=$STATE_CRITICAL
-		elif echo "${sensordata}" | egrep -q FAULT  > /dev/null -a; then
-			if [ "$(test "$1")" != "-i" -a \
-				"$1" != "--ignore-fault" ] ; then
-				text="SENSOR UNKNOWN - Sensor reported fault"
-				exit=$STATE_UNKNOWN
-			fi
+		elif [ $ignorefault -eq 0 ] && echo "${sensordata}" | egrep -q FAULT  >/dev/null; then
+			text="SENSOR UNKNOWN - Sensor reported fault"
+			exit=$STATE_UNKNOWN
 		else
 			text="SENSORS OK"
 			exit=$STATE_OK
@@ -68,6 +75,6 @@ case "$1" in
 		if test "$1" = "-v" -o "$1" = "--verbose"; then
 			echo "${sensordata}"
 		fi
-		exit "$exit"
+		exit $exit
 		;;
 esac

+ 11 - 5
plugins-scripts/check_wave.pl

@@ -13,7 +13,8 @@ use vars qw($opt_V $opt_h $verbose $opt_w $opt_c $opt_H);
 my (@test, $low1, $med1, $high1, $snr, $low2, $med2, $high2);
 my ($low, $med, $high, $lowavg, $medavg, $highavg, $tot, $ss);
 
-$PROGNAME = "check_wave";
+$PROGNAME = $0;
+chomp $PROGNAME;
 sub print_help ();
 sub print_usage ();
 
@@ -41,9 +42,9 @@ if ($opt_h) {
 }
 
 $opt_H = shift unless ($opt_H);
-print_usage() unless ($opt_H);
+unless ($opt_H) { print_usage(); exit -1; }
 my $host = $1 if ($opt_H =~ m/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z][-a-zA-Z0]+(\.[a-zA-Z][-a-zA-Z0]+)*)$/);
-print_usage() unless ($host);
+unless ($host) { print_usage(); exit -1; }
 
 ($opt_c) || ($opt_c = shift) || ($opt_c = 120);
 my $critical = $1 if ($opt_c =~ /([0-9]+)/);
@@ -51,7 +52,12 @@ my $critical = $1 if ($opt_c =~ /([0-9]+)/);
 ($opt_w) || ($opt_w = shift) || ($opt_w = 60);
 my $warning = $1 if ($opt_w =~ /([0-9]+)/);
 
-$low1 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.8.1`;
+$low1 = `snmpget $host public .1.3.6.1.4.1.74.2.21.1.2.1.8.1 2>/dev/null`;
+unless ($low1) {
+	print "UNKNOWN - Could not find the 'snmpget' command Please install\n";
+	print "the snmp commands (usually net-snmp) before using $PROGNAME\n";
+	exit $ERRORS{'UNKNOWN'};
+}
 @test = split(/ /,$low1);
 $low1 = $test[2];
 
@@ -97,7 +103,7 @@ if ($tot==0) {
 	$ss = ($medavg*50) + ($highavg*100);
 }
 
-printf("Signal Strength at: %3.0f%,  SNR at $snr%",$ss);
+printf("Signal Strength at: %3.0f%,  SNR at $snr%\n",$ss);
 
 if ($ss<$critical) {
 	exit(2);

+ 3 - 2
plugins/Makefile.am

@@ -29,7 +29,7 @@ MATHLIBS = @MATHLIBS@
 libexec_PROGRAMS = check_apt check_cluster check_disk check_dummy check_http check_load \
 	check_mrtg check_mrtgtraf check_ntp check_ntp_peer check_nwstat check_overcr check_ping \
 	check_real check_smtp check_ssh check_tcp check_time check_ntp_time \
-	check_ups check_users negate \
+	check_ups check_users negate remove_perfdata \
 	urlize @EXTRAS@
 
 check_tcp_programs = check_ftp check_imap check_nntp check_pop \
@@ -78,7 +78,7 @@ check_fping_LDADD = $(NETLIBS)
 check_game_LDADD = $(BASEOBJS)
 check_http_LDADD = $(SSLOBJS)
 check_hpjd_LDADD = $(NETLIBS)
-check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS)
+check_ldap_LDADD = $(SSLOBJS) $(NETLIBS) $(LDAPLIBS) $(SSLLIBS)
 check_load_LDADD = $(BASEOBJS)
 check_mrtg_LDADD = $(BASEOBJS)
 check_mrtgtraf_LDADD = $(BASEOBJS)
@@ -113,6 +113,7 @@ check_by_ssh_LDADD = $(NETLIBS)
 check_ide_smart_LDADD = $(BASEOBJS)
 negate_LDADD = $(BASEOBJS)
 urlize_LDADD = $(BASEOBJS)
+remove_perfdata_LDADD = $(BASEOBJS)
 
 if !HAVE_UTMPX
 check_users_LDADD += popen.o

+ 12 - 3
plugins/check_apt.c

@@ -73,6 +73,7 @@ char* add_to_regexp(char *expr, const char *next);
 /* configuration variables */
 static int verbose = 0;      /* -v */
 static int do_update = 0;    /* whether to call apt-get update */
+static int only_critical = 0;    /* whether to warn about non-critical updates */
 static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */
 static char *upgrade_opts = NULL; /* options to override defaults for upgrade */
 static char *update_opts = NULL; /* options to override defaults for update */
@@ -110,7 +111,7 @@ int main (int argc, char **argv) {
 
 	if(sec_count > 0){
 		result = max_state(result, STATE_CRITICAL);
-	} else if(packages_available > 0){
+	} else if(packages_available > 0 && only_critical == 0){
 		result = max_state(result, STATE_WARNING);
 	} else if(result > STATE_UNKNOWN){
 		result = STATE_UNKNOWN;
@@ -148,12 +149,13 @@ int process_arguments (int argc, char **argv) {
 		{"include", required_argument, 0, 'i'},
 		{"exclude", required_argument, 0, 'e'},
 		{"critical", required_argument, 0, 'c'},
+		{"only-critical", no_argument, 0, 'o'},
 		{"input-file", required_argument, 0, INPUT_FILE_OPT},
 		{0, 0, 0, 0}
 	};
 
 	while(1) {
-		c = getopt_long(argc, argv, "hVvt:u::U::d::ni:e:c:", longopts, NULL);
+		c = getopt_long(argc, argv, "hVvt:u::U::d::ni:e:c:o", longopts, NULL);
 
 		if(c == -1 || c == EOF || c == 1) break;
 
@@ -203,6 +205,9 @@ int process_arguments (int argc, char **argv) {
 		case 'c':
 			do_critical=add_to_regexp(do_critical, optarg);
 			break;
+		case 'o':
+			only_critical=1;
+			break;
 		case INPUT_FILE_OPT:
 			input_filename = optarg;
 			break;
@@ -463,7 +468,11 @@ print_help (void)
   printf ("    %s\n", _("upgrades for Debian and Ubuntu:"));
   printf ("    \t\%s\n", SECURITY_RE);
   printf ("    %s\n", _("Note that the package must first match the include list before its"));
-  printf ("    %s\n\n", _("information is compared against the critical list."));
+  printf ("    %s\n", _("information is compared against the critical list."));
+  printf (" %s\n", "-o, --only-critical");
+  printf ("    %s\n", _("Only warn about upgrades matching the critical list.  The total number"));
+  printf ("    %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause"));
+  printf ("    %s\n\n", _("the plugin to return WARNING status."));
 
   printf ("%s\n\n", _("The following options require root privileges and should be used with care:"));
   printf (" %s\n", "-u, --update=OPTS");

+ 50 - 64
plugins/check_disk.c

@@ -127,7 +127,6 @@ enum
 int process_arguments (int, char **);
 void print_path (const char *mypath);
 void set_all_thresholds (struct parameter_list *path);
-int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *);
 void print_help (void);
 void print_usage (void);
 double calculate_percent(uintmax_t, uintmax_t);
@@ -147,6 +146,7 @@ int erronly = FALSE;
 int display_mntp = FALSE;
 int exact_match = FALSE;
 int freespace_ignore_reserved = FALSE;
+int show_status = FALSE;
 char *warn_freespace_units = NULL;
 char *crit_freespace_units = NULL;
 char *warn_freespace_percent = NULL;
@@ -171,7 +171,7 @@ main (int argc, char **argv)
   int result = STATE_UNKNOWN;
   int disk_result = STATE_UNKNOWN;
   char *output;
-  char *details;
+  char status_lit[4];
   char *perf;
   char *preamble;
   char *flag_header;
@@ -190,7 +190,6 @@ main (int argc, char **argv)
 
   preamble = strdup (" - free space:");
   output = strdup ("");
-  details = strdup ("");
   perf = strdup ("");
   stat_buf = malloc(sizeof *stat_buf);
 
@@ -206,11 +205,37 @@ main (int argc, char **argv)
   if (process_arguments (argc, argv) == ERROR)
     usage4 (_("Could not parse arguments"));
 
+  if (show_status)
+    sprintf(status_lit, "x:");
+  else
+    status_lit[0] = '\0';
+
   /* If a list of paths has not been selected, find entire
      mount list and create list of paths
    */
   if (path_selected == FALSE) {
     for (me = mount_list; me; me = me->me_next) {
+			if (strcmp(me->me_type, "autofs") == 0 && show_local_fs) {
+				if (last_me == NULL)
+					mount_list = me;
+				else
+					last_me->me_next = me->me_next;
+				free_mount_entry (me);
+				continue;
+			}
+			if (strcmp(me->me_type, "sysfs") == 0 || strcmp(me->me_type, "proc") == 0
+			|| strcmp(me->me_type, "debugfs") == 0 || strcmp(me->me_type, "tracefs") == 0
+			|| strcmp(me->me_type, "fusectl") == 0 || strcmp(me->me_type, "fuse.gvfsd-fuse") == 0
+			|| strcmp(me->me_type, "cgroup") == 0 || strstr(me->me_type, "tmpfs") != NULL)
+			{
+				if (last_me == NULL)
+					mount_list = me->me_next;
+				else
+					last_me->me_next = me->me_next;
+				free_mount_entry (me);
+				continue;
+			}
+
       if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) {
         path = np_add_parameter(&path_select_list, me->me_mountdir);
       }
@@ -321,6 +346,9 @@ main (int argc, char **argv)
       if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result);
       disk_result = max_state( disk_result, temp_result );
 
+      if (show_status)
+        status_lit[0] = state_text(disk_result)[0];
+
       result = max_state(result, disk_result);
 
       /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
@@ -357,14 +385,10 @@ main (int argc, char **argv)
       if (disk_result==STATE_OK && erronly && !verbose)
         continue;
 
-      if (disk_result && verbose) {
-	      xasprintf(&flag_header, " %s [", state_text (disk_result));
-      }
-      else {
-	      xasprintf(&flag_header, "");
-      }
-      xasprintf (&output, "%s %s %.0f %s (%.2f%%",
+      xasprintf (&output, "%s%s%s%s %.0f %s (%.2f%%",
                 output,
+                newlines ? "" : " ",
+                status_lit,
                 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
                 path->dfree_units,
                 units,
@@ -384,8 +408,6 @@ main (int argc, char **argv)
         }
       }
 
-      free(flag_header);
-
       /* TODO: Need to do a similar debug line
       xasprintf (&details, _("%s\n\
 %.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"),
@@ -398,9 +420,6 @@ main (int argc, char **argv)
 
   }
 
-  if (verbose >= 2)
-    xasprintf (&output, "%s%s", output, details);
-
   if (newlines) {
     printf ("DISK %s%s\n%s|%s\n", state_text (result), (erronly && result==STATE_OK) ? "" : preamble, output, perf);
   } else {
@@ -483,6 +502,7 @@ process_arguments (int argc, char **argv)
     {"errors-only", no_argument, 0, 'e'},
     {"exact-match", no_argument, 0, 'E'},
     {"all", no_argument, 0, 'A'},
+    {"show-status", no_argument, 0, 's'},
     {"verbose", no_argument, 0, 'v'},
     {"quiet", no_argument, 0, 'q'},
     {"clear", no_argument, 0, 'C'},
@@ -502,7 +522,7 @@ process_arguments (int argc, char **argv)
       strcpy (argv[c], "-t");
 
   while (1) {
-    c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLg:R:r:i:I:MEAn", longopts, &option);
+    c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLg:R:r:i:I:MEAns", longopts, &option);
 
     if (c == -1 || c == EOF)
       break;
@@ -703,6 +723,10 @@ process_arguments (int argc, char **argv)
       cflags = default_cflags;
       break;
 
+    case 's':
+      show_status = TRUE;
+			break;
+
     case 'A':
       optarg = strdup(".*");
     case 'R':
@@ -839,50 +863,6 @@ set_all_thresholds (struct parameter_list *path)
     set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
 }
 
-/* TODO: Remove?
-
-int
-validate_arguments (uintmax_t w, uintmax_t c, double wp, double cp, double iwp, double icp, char *mypath)
-{
-  if (w < 0 && c < 0 && wp < 0.0 && cp < 0.0) {
-    printf (_("INPUT ERROR: No thresholds specified"));
-    print_path (mypath);
-    return ERROR;
-  }
-  else if ((wp >= 0.0 || cp >= 0.0) &&
-           (wp < 0.0 || cp < 0.0 || wp > 100.0 || cp > 100.0 || cp > wp)) {
-    printf (_("\
-INPUT ERROR: C_DFP (%f) should be less than W_DFP (%.1f) and both should be between zero and 100 percent, inclusive"),
-            cp, wp);
-    print_path (mypath);
-    return ERROR;
-  }
-  else if ((iwp >= 0.0 || icp >= 0.0) &&
-           (iwp < 0.0 || icp < 0.0 || iwp > 100.0 || icp > 100.0 || icp > iwp)) {
-    printf (_("\
-INPUT ERROR: C_IDFP (%f) should be less than W_IDFP (%.1f) and both should be between zero and 100 percent, inclusive"),
-            icp, iwp);
-    print_path (mypath);
-    return ERROR;
-  }
-  else if ((w > 0 || c > 0) && (w == 0 || c == 0 || c > w)) {
-    printf (_("\
-INPUT ERROR: C_DF (%lu) should be less than W_DF (%lu) and both should be greater than zero"),
-            (unsigned long)c, (unsigned long)w);
-    print_path (mypath);
-    return ERROR;
-  }
-
-  return OK;
-}
-
-*/
-
-
-
-
-
-
 
 void
 print_help (void)
@@ -949,6 +929,8 @@ print_help (void)
   printf ("    %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
   printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
   printf ("    %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
+  printf (" %s\n", "-s, --show-status");
+  printf ("    %s\n", _("Show status for each path/partition"));
   printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
   printf (" %s\n", "-u, --units=STRING");
   printf ("    %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
@@ -980,16 +962,20 @@ print_usage (void)
 {
   printf ("%s\n", _("Usage:"));
   printf (" %s -w limit -c limit [-W limit] [-K limit] {-p path | -x device}\n", progname);
-  printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
-  printf ("[-t timeout] [-u unit] [-v] [-X type] [-N type] [-n]\n");
+  printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] {-A | [-R path] [-r path]}\n");
+  printf ("[-s] [-t timeout] [-u unit] [-v] [-X type] [-N type] [-n]\n");
 }
 
 void
 stat_path (struct parameter_list *p)
 {
   /* Stat entry to check that dir exists and is accessible */
-  if (verbose >= 3)
-    printf("calling stat on %s\n", p->name);
+  if (verbose >= 3) {
+    if (p->best_match)
+      printf("calling stat on %s (%s %s)\n", p->name, p->best_match->me_devname, p->best_match->me_type);
+    else
+      printf("calling stat on %s\n", p->name);
+  }
   if (stat (p->name, &stat_buf[0])) {
     if (verbose >= 3)
       printf("stat failed on %s\n", p->name);

File diff suppressed because it is too large
+ 1119 - 1084
plugins/check_http.c


+ 65 - 12
plugins/check_ldap.c

@@ -76,6 +76,9 @@ int starttls = FALSE;
 int ssl_on_connect = FALSE;
 int verbose = 0;
 
+int check_cert = FALSE;
+int days_till_exp_warn, days_till_exp_crit;
+
 /* for ldap tls */
 
 char *SERVICE = "LDAP";
@@ -183,6 +186,9 @@ main (int argc, char *argv[])
 			printf (_("Could not init TLS at port %i!\n"), ld_port);
 			return STATE_CRITICAL;
 		}
+
+		if (check_cert == TRUE)
+			return ldap_check_cert(ld);
 #else
 		printf (_("TLS not supported by the libraries!\n"));
 		return STATE_CRITICAL;
@@ -207,6 +213,9 @@ main (int argc, char *argv[])
 			printf (_("Could not init startTLS at port %i!\n"), ld_port);
 			return STATE_CRITICAL;
 		}
+
+		if (check_cert == TRUE)
+			return ldap_check_cert(ld);
 #else
 		printf (_("startTLS not supported by the library, needs LDAPv3!\n"));
 		return STATE_CRITICAL;
@@ -296,6 +305,7 @@ int
 process_arguments (int argc, char **argv)
 {
 	int c;
+	char *temp;
 
 	int option = 0;
 	/* initialize the long option struct */
@@ -315,6 +325,7 @@ process_arguments (int argc, char **argv)
 #endif
 		{"starttls", no_argument, 0, 'T'},
 		{"ssl", no_argument, 0, 'S'},
+		{"age", required_argument, 0, 'A'},
 		{"use-ipv4", no_argument, 0, '4'},
 		{"use-ipv6", no_argument, 0, '6'},
 		{"port", required_argument, 0, 'p'},
@@ -335,7 +346,7 @@ process_arguments (int argc, char **argv)
 	}
 
 	while (1) {
-		c = getopt_long (argc, argv, "hvV234TS6t:c:w:H:b:p:a:D:P:U:C:W:", longopts, &option);
+		c = getopt_long (argc, argv, "hvV234TS6t:c:w:H:b:p:a:D:P:U:C:W:A:", longopts, &option);
 
 		if (c == -1 || c == EOF)
 			break;
@@ -403,6 +414,33 @@ process_arguments (int argc, char **argv)
 			else
 				usage_va(_("%s cannot be combined with %s"), "-T/--starttls", "-S/--ssl");
 			break;
+		case 'A': /* Check SSL cert validity */
+#ifndef HAVE_SSL
+			usage4 (_("Invalid option - SSL is not available"));
+#else
+			if (starttls || ssl_on_connect || strstr(argv[0],"check_ldaps")) {
+				if ((temp=strchr(optarg,','))!=NULL) {
+					*temp = '\0';
+					if (!is_intnonneg (temp))
+						usage2 (_("Invalid certificate expiration period"), optarg);
+					days_till_exp_warn = atoi(optarg);
+					*temp = ',';
+					temp++;
+					if (!is_intnonneg (temp))
+						usage2 (_("Invalid certificate expiration period"), temp);
+						days_till_exp_crit = atoi (temp);
+				} else {
+					days_till_exp_crit = 0;
+					if (!is_intnonneg (optarg))
+						usage2 (_("Invalid certificate expiration period"), optarg);
+					days_till_exp_warn = atoi (optarg);
+				}
+				check_cert = TRUE;
+			} else {
+				usage_va(_("%s requires either %s or %s"), "-A/--age", "-S/--ssl", "-T/--starttls");
+			}
+			break;
+#endif
 		case 'S':
 			if (! starttls) {
 				ssl_on_connect = TRUE;
@@ -477,32 +515,34 @@ print_help (void)
 
 	printf (UT_IPv46);
 
-	printf (" %s\n", "-a [--attr]");
+	printf (" %s\n", "-a, --attr=ATTRIBUTE");
   printf ("    %s\n", _("ldap attribute to search (default: \"(objectclass=*)\""));
-  printf (" %s\n", "-b [--base]");
+  printf (" %s\n", "-b, --base=BASE");
   printf ("    %s\n", _("ldap base (eg. ou=my unit, o=my org, c=at"));
-  printf (" %s\n", "-D [--bind]");
+  printf (" %s\n", "-D, --bind=DN");
   printf ("    %s\n", _("ldap bind DN (if required)"));
-  printf (" %s\n", "-P [--pass]");
+  printf (" %s\n", "-P, --pass=PASSWORD");
   printf ("    %s\n", _("ldap password (if required)"));
-  printf (" %s\n", "-T [--starttls]");
+  printf (" %s\n", "-T, --starttls");
   printf ("    %s\n", _("use starttls mechanism introduced in protocol version 3"));
-  printf (" %s\n", "-S [--ssl]");
+  printf (" %s\n", "-S, --ssl");
   printf ("    %s %i\n", _("use ldaps (ldap v2 ssl method). this also sets the default port to"), LDAPS_PORT);
+  printf (" %s\n", "-A, --age=INTEGER[,INTEGER]");
+  printf ("    %s\n", _("Minimum number of days a certificate has to be valid"));
 
 #ifdef HAVE_LDAP_SET_OPTION
-	printf (" %s\n", "-2 [--ver2]");
+	printf (" %s\n", "-2, --ver2");
   printf ("    %s\n", _("use ldap protocol version 2"));
-  printf (" %s\n", "-3 [--ver3]");
+  printf (" %s\n", "-3, --ver3");
   printf ("    %s\n", _("use ldap protocol version 3"));
   printf ("    (%s %d)\n", _("default protocol version:"), DEFAULT_PROTOCOL);
 #endif
 
 	printf (UT_WARN_CRIT);
 
-  printf (" %s\n", "-W [--warn-entries]");
+  printf (" %s\n", "-W, --warn-entries=INTEGER");
   printf ("    %s\n", _("Number of found entries to result in warning status"));
-  printf (" %s\n", "-C [--crit-entries]");
+  printf (" %s\n", "-C, --crit-entries=INTEGER");
   printf ("    %s\n", _("Number of found entries to result in critical status"));
 
 	printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
@@ -526,7 +566,7 @@ print_usage (void)
 {
   printf ("%s\n", _("Usage:"));
   printf (" %s (-H <host>|-U <uri>) -b <base_dn> [-p <port>] [-a <attr>] [-D <binddn>]\n", progname);
-  printf ("       [-P <password>] [-w <warn_time>] [-c <crit_time>] [-t timeout]%s\n",
+  printf ("       [-P <password>] [-w <warn_time>] [-c <crit_time>] [-t timeout] [-A <age>]%s\n",
 #ifdef HAVE_LDAP_SET_OPTION
 			"\n       [-2|-3] [-4|-6]"
 #else
@@ -534,3 +574,16 @@ print_usage (void)
 #endif
 			);
 }
+
+int ldap_check_cert (LDAP *ld)
+{
+	SSL *ssl;
+	int rc;
+
+	rc = ldap_get_option(ld, LDAP_OPT_X_TLS_SSL_CTX, &ssl);
+	if (rc == LDAP_OPT_ERROR || ssl == NULL) {
+		printf ("%s\n",_("CRITICAL - Cannot retrieve ssl session from connection."));
+		return STATE_CRITICAL;
+	}
+	return np_net_ssl_check_cert_real(ssl, days_till_exp_warn, days_till_exp_crit);
+}

+ 1 - 0
plugins/check_nagios.c

@@ -64,6 +64,7 @@ main (int argc, char **argv)
 	int procuid = 0;
 	int procpid = 0;
 	int procppid = 0;
+	int procjid = 0;
 	int procvsz = 0;
 	int procrss = 0;
 	char proc_cgroup_hierarchy[MAX_INPUT_BUFFER];

+ 7 - 0
plugins/check_ntp_time.c

@@ -80,6 +80,7 @@ typedef struct {
 /* this structure holds data about results from querying offset from a peer */
 typedef struct {
 	time_t waiting;         /* ts set when we started waiting for a response */
+	int connected;          /* don't try to "write()" if "connect()" fails */
 	int num_responses;      /* number of successfully recieved responses */
 	uint8_t stratum;        /* copied verbatim from the ntp_message */
 	double rtdelay;         /* converted from the ntp_message */
@@ -355,6 +356,7 @@ double offset_request(const char *host, int *status){
 			ufds[i].fd=socklist[i];
 			ufds[i].events=POLLIN;
 			ufds[i].revents=0;
+			servers[i].connected=1;
 		}
 		ai_tmp = ai_tmp->ai_next;
 	}
@@ -370,6 +372,8 @@ double offset_request(const char *host, int *status){
 		now_time=time(NULL);
 
 		for(i=0; i<num_hosts; i++){
+			if(servers[i].connected == 0)
+				continue;
 			if(servers[i].waiting<now_time && servers[i].num_responses<AVG_NUM){
 				if(verbose && servers[i].waiting != 0) printf("re-");
 				if(verbose) printf("sending request to peer %d\n", i);
@@ -413,6 +417,9 @@ double offset_request(const char *host, int *status){
 			}
 		}
 		/* lather, rinse, repeat. */
+		/* break if we have one response but other ntp servers doesn't response */
+		/* greater than timeout_interval/2 */
+		if (servers_completed && now_time-start_ts > timeout_interval/2) break;
 	}
 
 	if (one_read == 0) {

+ 19 - 1
plugins/check_ping.c

@@ -54,6 +54,7 @@ void print_usage (void);
 void print_help (void);
 
 int display_html = FALSE;
+int show_resolution = FALSE;
 int wpl = UNKNOWN_PACKET_LOSS;
 int cpl = UNKNOWN_PACKET_LOSS;
 float wrta = UNKNOWN_TRIP_TIME;
@@ -67,6 +68,8 @@ int verbose = 0;
 float rta = UNKNOWN_TRIP_TIME;
 int pl = UNKNOWN_PACKET_LOSS;
 
+char ping_name[256];
+char ping_ip_addr[64];
 char *warn_text;
 
 
@@ -159,6 +162,12 @@ main (int argc, char **argv)
 		else
 			printf (_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"),
 							state_text (this_result), warn_text, pl, rta);
+		if (show_resolution) {
+			if (strcmp(ping_name, ping_ip_addr) == 0)
+				printf(" - %s", ping_name);
+			else
+				printf(" - %s (%s)", ping_name, ping_ip_addr);
+		}
 		if (display_html == TRUE)
 			printf ("</A>");
 
@@ -196,6 +205,7 @@ process_arguments (int argc, char **argv)
 	static struct option longopts[] = {
 		STD_LONG_OPTS,
 		{"packets", required_argument, 0, 'p'},
+		{"show-resolution", no_argument, 0, 's'},
 		{"nohtml", no_argument, 0, 'n'},
 		{"link", no_argument, 0, 'L'},
 		{"use-ipv4", no_argument, 0, '4'},
@@ -214,7 +224,7 @@ process_arguments (int argc, char **argv)
 	}
 
 	while (1) {
-		c = getopt_long (argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option);
+		c = getopt_long (argc, argv, "VvhsnL46t:c:w:H:p:", longopts, &option);
 
 		if (c == -1 || c == EOF)
 			break;
@@ -271,6 +281,9 @@ process_arguments (int argc, char **argv)
 			else
 				usage2 (_("<max_packets> (%s) must be a non-negative number\n"), optarg);
 			break;
+		case 's':
+			show_resolution = TRUE;
+			break;
 		case 'n':	/* no HTML */
 			display_html = FALSE;
 			break;
@@ -448,6 +461,9 @@ run_ping (const char *cmd, const char *addr)
 
 		result = max_state (result, error_scan (buf, addr));
 
+		if(sscanf(buf, "PING %255s (%63[^)]", &ping_name, &ping_ip_addr))
+			continue;
+
 		/* get the percent loss statistics */
 		match = 0;
 		if((sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) ||
@@ -585,6 +601,8 @@ print_help (void)
   printf (" %s\n", "-p, --packets=INTEGER");
   printf ("    %s ", _("number of ICMP ECHO packets to send"));
   printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS);
+	printf (" %s\n", "-s, --show-resolution");
+	printf ("    %s\n", _("show name resolution in the plugin output (DNS & IP)"));
   printf (" %s\n", "-L, --link");
   printf ("    %s\n", _("show HTML in the plugin output (obsoleted by urlize)"));
 

+ 65 - 7
plugins/check_procs.c

@@ -71,6 +71,8 @@ int options = 0; /* bitmask of filter criteria to test against */
 #define ELAPSED 512
 #define EREG_ARGS 1024
 #define CGROUP_HIERARCHY 2048
+#define EXCLUDE_PROGS 4096
+#define JID 8192
 
 #define KTHREAD_PARENT "kthreadd" /* the parent process of kernel threads:
 							ppid of procs are compared to pid of this proc*/
@@ -94,6 +96,9 @@ int rss;
 float pcpu;
 char *statopts;
 char *prog;
+char *exclude_progs;
+char ** exclude_progs_arr = NULL;
+char exclude_progs_counter = 0; 
 char *cgroup_hierarchy;
 char *args;
 char *input_filename = NULL;
@@ -103,6 +108,7 @@ char *fails;
 char tmp[MAX_INPUT_BUFFER];
 int kthread_filter = 0;
 int usepid = 0; /* whether to test for pid or /proc/pid/exe */
+int jid;
 
 FILE *ps_input = NULL;
 
@@ -133,6 +139,7 @@ main (int argc, char **argv)
 	int procuid = 0;
 	pid_t procpid = 0;
 	pid_t procppid = 0;
+	int procjid = 0;
 	pid_t kthread_ppid = 0;
 	int procvsz = 0;
 	int procrss = 0;
@@ -236,9 +243,9 @@ main (int argc, char **argv)
 			procseconds = convert_to_seconds(procetime);
 
 			if (verbose >= 3) {
-				printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s",
++				printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d jid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
 					procs, procuid, procvsz, procrss,
-					procpid, procppid, procpcpu, procstat,
+					procpid, procppid, procjid, procpcpu, procstat,
 					procetime, procprog, procargs);
 				if (strstr(PS_COMMAND, "cgroup") != NULL) {
 					printf(" proc_cgroup_hierarchy=%s\n", proc_cgroup_hierarchy);
@@ -262,6 +269,26 @@ main (int argc, char **argv)
 				continue;
 			}
 
+			/* Ignore excluded processes by name */
+			if(options & EXCLUDE_PROGS) {
+			  int found = 0;
+			  int i = 0;
+			 
+			  
+			  for(i=0; i < (exclude_progs_counter); i++) {
+			    if(!strcmp(procprog, exclude_progs_arr[i])) {
+			      found = 1;
+			    }
+			  }
+			  if(found == 0) {
+			    resultsum |= EXCLUDE_PROGS;
+			  }else
+			  {
+                            if(verbose >= 3)
+			      printf("excluding - by ignorelist\n");
+                          }
+			}
+
 			/* filter kernel threads (childs of KTHREAD_PARENT)*/
 			/* TODO adapt for other OSes than GNU/Linux
 					sorry for not doing that, but I've no other OSes to test :-( */
@@ -287,6 +314,8 @@ main (int argc, char **argv)
 				resultsum |= PROG;
 			if ((options & PPID) && (procppid == ppid))
 				resultsum |= PPID;
+			if ((options & JID) && (procjid == jid))
+				resultsum |= JID;
 			if ((options & USER) && (procuid == uid))
 				resultsum |= USER;
 			if ((options & VSZ)  && (procvsz >= vsz))
@@ -315,9 +344,9 @@ main (int argc, char **argv)
 
 			procs++;
 			if (verbose >= 2) {
-				printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s",
++				printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d jid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
 					procuid, procvsz, procrss,
-					procpid, procppid, procpcpu, procstat, 
+					procpid, procppid, procjid, procpcpu, procstat,
 					procetime, procprog, procargs);
 				if (strstr(PS_COMMAND, "cgroup") != NULL) {
 					printf(" cgroup_hierarchy=%s\n", cgroup_hierarchy);
@@ -438,6 +467,8 @@ process_arguments (int argc, char **argv)
 		{"no-kthreads", required_argument, 0, 'k'},
 		{"traditional-filter", no_argument, 0, 'T'},
 		{"cgroup-hierarchy", required_argument, 0, 'g'},
+		{"exclude-process", required_argument, 0, 'X'},
+		{"jid", required_argument, 0, 'j'},
 		{0, 0, 0, 0}
 	};
 
@@ -446,7 +477,7 @@ process_arguments (int argc, char **argv)
 			strcpy (argv[c], "-t");
 
 	while (1) {
-		c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:Tg:",
+		c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:Tg:X:j:",
 			longopts, &option);
 
 		if (c == -1 || c == EOF)
@@ -477,6 +508,12 @@ process_arguments (int argc, char **argv)
 				break;
 			}
 			usage4 (_("Parent Process ID must be an integer!"));
+		case 'j':                                   /* jail id */
+			if (sscanf (optarg, "%d%[^0-9]", &jid, tmp) == 1) {
+				xasprintf (&fmt, "%s%sJID = %d", (fmt ? fmt : "") , (options ? ", " : ""), jid);
+				options |= JID;
+				break;
+			}
 		case 's':									/* status */
 			if (statopts)
 				break;
@@ -516,6 +553,23 @@ process_arguments (int argc, char **argv)
 			          prog);
 			options |= PROG;
 			break;
+		case 'X':
+		        if(exclude_progs)
+			  break;
+			else
+			  exclude_progs = optarg;
+			xasprintf (&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
+				   exclude_progs);
+			char *p = strtok(exclude_progs, ",");
+
+			while(p){
+			  exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char*) * ++exclude_progs_counter);
+			  exclude_progs_arr[exclude_progs_counter-1] = p;
+			  p = strtok(NULL, ",");
+			}
+
+			options |= EXCLUDE_PROGS;
+			break;
 		case 'g':									/* cgroup hierarchy */
 			if (cgroup_hierarchy)
 				break;
@@ -766,6 +820,8 @@ print_help (void)
   printf ("   %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
   printf (" %s\n", "-p, --ppid=PPID");
   printf ("   %s\n", _("Only scan for children of the parent process ID indicated."));
+  printf (" %s\n", "-j, --jid=JID");
+  printf ("   %s\n", _("Only scan for process running in jail which ID is JID."));
   printf (" %s\n", "-z, --vsz=VSZ");
   printf ("   %s\n", _("Only scan for processes with VSZ higher than indicated."));
   printf (" %s\n", "-r, --rss=RSS");
@@ -780,6 +836,8 @@ print_help (void)
   printf ("   %s\n", _("Only scan for processes with args that contain the regex STRING."));
   printf (" %s\n", "-C, --command=COMMAND");
   printf ("   %s\n", _("Only scan for exact matches of COMMAND (without path)."));
+  printf (" %s\n", "-C, --exclude-process");
+  printf ("   %s\n", _("Exclude processes which match this comma seperated list"));
   printf (" %s\n", "-k, --no-kthreads");
   printf ("   %s\n", _("Only scan for non kernel threads (works on Linux only)."));
   printf (" %s\n", "-g, --cgroup-hierarchy");
@@ -818,7 +876,7 @@ void
 print_usage (void)
 {
   printf ("%s\n", _("Usage:"));
-	printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
+	printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid] [-j jid]\n", progname);
   printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
-  printf (" [-C command] [-k] [-t timeout] [-v]\n");
+  printf (" [-C command] [-X process_to_exclude] [-k] [-t timeout] [-v]\n");
 }

+ 68 - 2
plugins/check_radius.c

@@ -36,6 +36,17 @@ const char *email = "devel@nagios-plugins.org";
 #include "utils.h"
 #include "netutils.h"
 
+#include <ifaddrs.h>
+
+#ifdef __FreeBSD__
+#include <net/if_dl.h>
+#else
+#include <linux/if_packet.h>
+#define AF_LINK AF_PACKET
+#define LLADDR(l) ((l)->sll_addr)
+#define sockaddr_dl sockaddr_ll
+#endif
+
 #if defined(HAVE_LIBFREERADIUS_CLIENT)
 #include <freeradius-client.h>
 #elif defined(HAVE_LIBRADIUSCLIENT_NG)
@@ -47,6 +58,7 @@ const char *email = "devel@nagios-plugins.org";
 int process_arguments (int, char **);
 void print_help (void);
 void print_usage (void);
+char *get_ether_addr(uint32_t client_id);
 
 #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG)
 #define my_rc_conf_str(a) rc_conf_str(rch,a)
@@ -85,6 +97,7 @@ char *username = NULL;
 char *password = NULL;
 char *nasid = NULL;
 char *nasipaddress = NULL;
+char *castid = NULL;
 char *expect = NULL;
 char *config_file = NULL;
 unsigned short port = PW_AUTH_UDP_PORT;
@@ -154,6 +167,7 @@ main (int argc, char **argv)
 	SEND_DATA data;
 	int result = STATE_UNKNOWN;
 	uint32_t client_id, service;
+	char *ether;
 	char *str;
 
 	setlocale (LC_ALL, "");
@@ -197,6 +211,14 @@ main (int argc, char **argv)
 	if (my_rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) == NULL)
 		die (STATE_UNKNOWN, _("Invalid NAS-IP-Address\n"));
 
+	if (castid != NULL) {
+		if (!(my_rc_avpair_add (&data.send_pairs, PW_CALLING_STATION_ID, castid, 0)))
+			die (STATE_UNKNOWN, _("Invalid Calling-Station-Id\n"));
+	} else if ((ether = get_ether_addr(client_id)) != NULL) {
+		if (!(my_rc_avpair_add (&data.send_pairs, PW_CALLING_STATION_ID, ether, 0)))
+			die (STATE_UNKNOWN, _("Invalid Calling-Station-Id\n"));
+	}
+
 	my_rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, (int)timeout_interval,
 	             retries);
 
@@ -237,6 +259,7 @@ process_arguments (int argc, char **argv)
 		{"password", required_argument, 0, 'p'},
 		{"nas-id", required_argument, 0, 'n'},
 		{"nas-ip-address", required_argument, 0, 'N'},
+		{"calling-station-id", required_argument, 0, 'c'},
 		{"filename", required_argument, 0, 'F'},
 		{"expect", required_argument, 0, 'e'},
 		{"retries", required_argument, 0, 'r'},
@@ -248,8 +271,8 @@ process_arguments (int argc, char **argv)
 	};
 
 	while (1) {
-		c = getopt_long (argc, argv, "+hVvH:P:F:u:p:n:N:t:r:e:", longopts,
-									 &option);
+		c = getopt_long (argc, argv, "+hVvH:P:F:u:p:n:N:c:t:r:e:", longopts,
+									   &option);
 
 		if (c == -1 || c == EOF || c == 1)
 			break;
@@ -296,6 +319,9 @@ process_arguments (int argc, char **argv)
 		case 'N':									/* nas ip address */
 			nasipaddress = optarg;
 			break;
+		case 'c':									/* calling station id */
+			castid = optarg;
+			break;
 		case 'F':									/* configuration file */
 			config_file = optarg;
 			break;
@@ -358,6 +384,8 @@ print_help (void)
   printf ("    %s\n", _("NAS identifier"));
   printf (" %s\n", "-N, --nas-ip-address=STRING");
   printf ("    %s\n", _("NAS IP Address"));
+  printf (" %s\n", "-c, --calling-station-id=STRING");
+  printf ("    %s\n", _("Calling Station identifier"));
   printf (" %s\n", "-F, --filename=STRING");
   printf ("    %s\n", _("Configuration file"));
   printf (" %s\n", "-e, --expect=STRING");
@@ -403,3 +431,41 @@ int my_rc_read_config(char * a)
 	return rc_read_config(a);
 #endif
 }
+
+char *get_ether_addr(uint32_t client_id)
+{
+	static char ether_addr[18];
+	struct ifaddrs *ifap, *ifa, *ifb;
+	struct sockaddr_in *sain;
+	unsigned char *lladdr;
+
+	getifaddrs(&ifap);
+
+	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
+		if (ifa->ifa_addr->sa_family == AF_INET) {
+			sain = (struct sockaddr_in *)ifa->ifa_addr;
+			if (client_id == ntohl(sain->sin_addr.s_addr))
+				break;
+		}
+	if (ifa == NULL) {
+		freeifaddrs(ifap);
+		return NULL;
+	}
+
+	ifb = ifa;
+	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
+		if (ifa->ifa_addr->sa_family == AF_LINK
+		    && strcmp(ifa->ifa_name, ifb->ifa_name) == 0)
+			break;
+	if (ifa == NULL) {
+		freeifaddrs(ifap);
+		return NULL;
+	}
+
+	lladdr = (unsigned char *)LLADDR((struct sockaddr_dl *)ifa->ifa_addr);
+	sprintf(ether_addr, "%02X-%02X-%02X-%02X-%02X-%02X",
+	    lladdr[0], lladdr[1], lladdr[2], lladdr[3], lladdr[4], lladdr[5]);
+
+	freeifaddrs(ifap);
+	return ether_addr;
+}

+ 78 - 30
plugins/check_snmp.c

@@ -288,6 +288,7 @@ main (int argc, char **argv)
 		set_thresholds(&thlds[i],
 		               w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
 		               c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
+
 		if (w) {
 			th_warn=strchr(th_warn, ',');
 			if (th_warn) th_warn++;
@@ -332,7 +333,7 @@ main (int argc, char **argv)
 
 	/* This is just for display purposes, so it can remain a string */
 	xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s %s %s %s:%s",
-		snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto, "[context]", "[authpriv]",
+		snmpcmd, command_interval, retries, strlen(miblist) ? miblist : "''", proto, "[context]", "[authpriv]",
 		server_address, port);
 
 	for (i = 0; i < numoids; i++) {
@@ -486,6 +487,7 @@ main (int argc, char **argv)
 		/* Process this block for numeric comparisons */
 		/* Make some special values,like Timeticks numeric only if a threshold is defined */
 		if (thlds[i]->warning || thlds[i]->critical || calculate_rate || is_ticks || offset != 0.0) {
+
 			ptr = strpbrk (show, "-0123456789");
 			if (ptr == NULL)
 				die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show);
@@ -574,50 +576,96 @@ main (int argc, char **argv)
 		ptr = NULL;
 		strtod(show, &ptr);
 		if (ptr > show) {
-			if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
-				temp_string=labels[i];
-			else
-				temp_string=oidname;
-			if (strpbrk (temp_string, " ='\"") == NULL) {
-				strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
+
+			/* use either specified label or oid as label */
+			if (perf_labels 
+				&& (nlabels >= (size_t)1) 
+				&& ((size_t)i < nlabels) 
+				&& labels[i] != NULL) {
+
+					temp_string=labels[i];
+			}
+			else {
+				temp_string = oidname;
+			}
+
+			/* check the label for space, equal, singlequote or doublequote */
+			if (strpbrk(temp_string, " ='\"") == NULL) {
+
+				/* if it doesn't have any - we can just use it as the label */
+				strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
+
 			} else {
-				if (strpbrk (temp_string, "'") == NULL) {
+
+				/* if it does have one of those characters, we need
+				   to find a way to adequately quote it */
+				if (strpbrk(temp_string, "'") == NULL) {
 					quote_string="'";
 				} else {
 					quote_string="\"";
 				}
-				strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1);
-				strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
-				strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1);
+
+				strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
+				strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
+				strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
 			}
-			strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1);
-			len = sizeof(perfstr)-strlen(perfstr)-1;
-			strncat(perfstr, show, len>ptr-show ? ptr-show : len);
 
-			if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL) {
-				xasprintf (&temp_string, "%s", unitv[i]);
-				strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
-				}
+			/* append the equal */
+			strncat(perfstr, "=", sizeof(perfstr) - strlen(perfstr) - 1);
+			len = sizeof(perfstr) - strlen(perfstr) - 1;
+
+			/* and then the data itself from the response */
+			strncat(perfstr, show, (len > ptr - show) ? ptr - show : len);
 
-			if (type)
-				strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
+			/* now append the unit of measurement */
+			if ((nunits > (size_t)0) 
+				&& ((size_t)i < nunits) 
+				&& (unitv[i] != NULL)) {
+
+					xasprintf(&temp_string, "%s", unitv[i]);
+					strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
+			}
 
+			/* and the type, if any */
+			if (type) {
+				strncat(perfstr, type, sizeof(perfstr) - strlen(perfstr) - 1);
+			}
+
+			/* add warn/crit to perfdata */
 			if (thlds[i]->warning || thlds[i]->critical) {
-				strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
-				if (thlds[i]->warning) {
-					xasprintf (&temp_string, "%.0f", thlds[i]->warning->end);
-					strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
+
+				strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
+
+				/* print the warning string if it exists */
+				if (thlds[i]->warning_string) {
+
+					xasprintf(&temp_string, "%s", thlds[i]->warning_string);
+					strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
 				}
 				strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
-				if (thlds[i]->critical) {
-					xasprintf (&temp_string, "%.0f", thlds[i]->critical->end);
-					strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1);
+
+				/* print the critical string if it exists */
+				if (thlds[i]->critical_string) {
+
+					xasprintf(&temp_string, "%s", thlds[i]->critical_string);
+					strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
 				}
-				strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
+				strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
+			}
+
+			/* remove trailing semi-colons for guideline adherence */
+			len = strlen(perfstr) - 1;
+			if (perfstr[len] == ';') {
+				perfstr[len] = '\0';
 			}
-			strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
+
+			/* we do not add any min/max value */
+
+			strncat(perfstr, " ", sizeof(perfstr) - strlen(perfstr) - 1);
 		}
-	}
+
+	} /* for (line=0, i=0; line < chld_out.lines; line++, i++) */
+	
 	total_oids=i;
 
 	/* Save state data, as all data collected now */

+ 6 - 0
plugins/common.h

@@ -146,6 +146,9 @@
 #    include <rsa.h>
 #    include <crypto.h>
 #    include <x509.h>
+#    if OPENSSL_VERSION_NUMBER >= 0x10002000L
+#      include <x509v3.h>
+#    endif
 #    include <pem.h>
 #    include <ssl.h>
 #    include <err.h>
@@ -154,6 +157,9 @@
 #      include <openssl/rsa.h>
 #      include <openssl/crypto.h>
 #      include <openssl/x509.h>
+#      if OPENSSL_VERSION_NUMBER >= 0x10002000L
+#        include <openssl/x509v3.h>
+#      endif
 #      include <openssl/pem.h>
 #      include <openssl/ssl.h>
 #      include <openssl/err.h>

+ 1 - 0
plugins/netutils.h

@@ -108,6 +108,7 @@ void np_net_ssl_cleanup();
 int np_net_ssl_write(const void *buf, int num);
 int np_net_ssl_read(void *buf, int num);
 int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit);
+int np_net_ssl_check_cert_real(SSL *ssl, int days_till_exp_warn, int days_till_exp_crit);
 #endif /* HAVE_SSL */
 
 #endif /* NAGIOS_NETUGILS_H_INCLUDED_ */

+ 257 - 0
plugins/remove_perfdata.c

@@ -0,0 +1,257 @@
+/*****************************************************************************
+* 
+* Nagios remove perfdata plugin
+* 
+* License: GPL
+* Copyright (c) 2002-2017 Nagios Plugins Development Team
+* 
+* Description:
+* 
+* This file contains the remove_perfdata plugin
+* 
+* Removes perfdata from a specified plugin's output. Optionally,
+* you can choose to remove any long output as well
+* 
+* 
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+* 
+* 
+*****************************************************************************/
+
+const char *progname = "remove_perfdata";
+const char *copyright = "2002-2017";
+const char *email = "devel@nagios-plugins.org";
+
+/* timeout should be handled in the plugin being called */
+#define DEFAULT_TIMEOUT 300
+
+#include "common.h"
+#include "utils.h"
+#include "utils_cmd.h"
+
+#include <ctype.h>
+
+static const char **process_arguments(int, char **);
+void validate_arguments(char **);
+void print_help(void);
+void print_usage(void);
+int remove_perfdata = 1;
+int remove_long_output = 0;
+
+
+int
+main(int argc, char **argv)
+{
+    int result = STATE_UNKNOWN;
+    int c = 0;
+    int i = 0;
+    int j = 0;
+    char *buf;
+    char *sub;
+    char **command_line;
+    output chld_out;
+    output chld_err;
+
+    setlocale(LC_ALL, "");
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+
+    command_line = (char **) process_arguments(argc, argv);
+
+    /* Set signal handling and alarm */
+    if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
+        die(STATE_UNKNOWN, _("Cannot catch SIGALRM"));
+    }
+
+    (void) alarm((unsigned) DEFAULT_TIMEOUT);
+
+    /* catch when the command is quoted */
+    if (command_line[1] == NULL) {
+        result = cmd_run(command_line[0], &chld_out, &chld_err, 0);
+    } else {
+        result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
+    }
+
+    if (chld_err.lines > 0) {
+        printf("%s:\n", _("Error output from command"));
+        for (i = 0; i < chld_err.lines; i++) {
+            printf("%s\n", chld_err.line[i]);
+        }
+        exit(STATE_WARNING);
+    }
+
+    /* Return UNKNOWN or worse if no output is returned */
+    if (chld_out.lines == 0) {
+        die(max_state_alt(result, STATE_UNKNOWN), _("No data returned from command\n"));
+    }
+
+    for (i = 0; i < chld_out.lines; i++) {
+
+        /* if we're on the first line, remove the perfdata */
+        if (remove_perfdata && i == 0) {
+
+            int in_quotes = 0;
+
+            for (j = 0; j < (int) strlen(chld_out.line[i]); j++) {
+
+                c = chld_out.line[i][j];
+
+                if (c == '"') {
+                    if (in_quotes) {
+                        in_quotes = 0;
+                    }
+                    else {
+                        in_quotes = 1;
+                    }
+                }
+
+                /* when we reach an unqouted |, stop printing */
+                if (!in_quotes && c == '|')
+                    break;
+
+                printf("%c", c);
+            }
+
+            /* and print a newline if we skipped past it */
+            if (c != '\n') {
+                printf("\n");
+            }
+        }
+
+        /* if we don't want long output, don't print it */
+        else if (remove_long_output && i > 0) {
+            break;
+        }
+
+        /* for everything else, theres mastercard - or printing the full line to the screen */
+        else {
+            printf("%s\n", chld_out.line[i]);
+        }
+    }
+
+    exit(result);
+}
+
+
+/* process command-line arguments */
+static const char **
+process_arguments(int argc, char **argv)
+{
+    int c = 0;
+    int option = 0;
+    static struct option longopts[] = {
+        {"help", no_argument, 0, 'h'},
+        {"version", no_argument, 0, 'V'},
+        {"remove-long-output", no_argument, 0, 'l'},
+        {"dont-remove-perfdata", required_argument, 0, 'd'},
+        {0, 0, 0, 0}
+    };
+
+    while (1) {
+        c = getopt_long(argc, argv, "+hVld", longopts, &option);
+
+        if (c == -1 || c == EOF)
+            break;
+
+        switch (c) {
+
+        /* help */
+        case '?':
+            usage5();
+            break;
+
+        /* help */
+        case 'h':
+            print_help();
+            exit(EXIT_SUCCESS);
+            break;
+
+        /* version */
+        case 'V':
+            print_revision(progname, NP_VERSION);
+            exit(EXIT_SUCCESS);
+
+        /* remove long output */
+        case 'l':
+            remove_long_output = 1;
+            break;
+
+        /* don't remove perfdata */
+        case 'd':
+            remove_perfdata = 0;
+            break;
+        }
+    }
+
+    validate_arguments(&argv[optind]);
+
+    return (const char **) &argv[optind];
+}
+
+
+void
+validate_arguments(char **command_line)
+{
+    if (command_line[0] == NULL)
+        usage4(_("Could not parse arguments"));
+
+    if (   strncmp(command_line[0], "/", 1) != 0 
+        && strncmp(command_line[0], "./", 2) != 0)
+        usage4(_("Require path to command"));
+}
+
+
+void
+print_help(void)
+{
+    print_revision(progname, NP_VERSION);
+
+    printf(COPYRIGHT, copyright, email);
+
+    printf("%s\n", _("Removes perfdata from plugin output."));
+    printf("%s\n", _("Additional switches can be used to remove long output as well."));
+
+    printf("\n\n");
+    print_usage();
+
+    printf(UT_HELP_VRSN);
+
+    printf(" -l, --remove-long-output\n");
+    printf("    %s\n", _("Remove long output from specified plugin's output."));
+    printf(" -d, --dont-remove-perfdata\n");
+    printf("    %s\n", _("Don't remove perfdata from the specified plugin's output.\n"));
+
+    printf("\n");
+
+    printf("%s\n", _("Examples:"));
+    printf("\n");
+    printf("%s\n", "remove_perfdata /usr/local/nagios/libexec/check_ping -H host");
+    printf("    %s\n", _("Run check_ping and remove performance data. (Must use full path to plugin.)"));
+    printf("\n");
+    printf("%s\n", _("Notes:"));
+    printf("    %s\n", _("This plugin is a wrapper to take the output of another plugin and alter it."));
+    printf("    %s\n", _("The full path of the plugin must be provided."));
+    printf("\n");
+
+    printf(UT_SUPPORT);
+}
+
+
+
+void
+print_usage(void)
+{
+    printf("%s\n", _("Usage:"));
+    printf("%s [-hV] [-l] [-d] <definition of wrapped plugin>\n", progname);
+}

+ 23 - 2
plugins/sslutils.c

@@ -35,6 +35,8 @@ static SSL_CTX *c=NULL;
 static SSL *s=NULL;
 static int initialized=0;
 
+int check_hostname = 0;
+
 int np_net_ssl_init(int sd) {
 	return np_net_ssl_init_with_hostname(sd, NULL);
 }
@@ -157,6 +159,16 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
 #endif
 		SSL_set_fd(s, sd);
 		if (SSL_connect(s) == 1) {
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+			if (check_hostname && host_name && *host_name) {
+				X509 *certificate=SSL_get_peer_certificate(s);
+				int rc = X509_check_host(certificate, host_name, 0, 0, NULL);
+				if (rc != 1) {
+					printf("%s\n", _("CRITICAL - Hostname mismatch."));
+					return STATE_CRITICAL;
+				}
+			}
+#endif
 			return OK;
 		} else {
 			printf("%s\n", _("CRITICAL - Cannot make SSL connection."));
@@ -194,6 +206,15 @@ int np_net_ssl_read(void *buf, int num) {
 }
 
 int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
+#  ifdef USE_OPENSSL
+	return np_net_ssl_check_cert_real(s, days_till_exp_warn, days_till_exp_crit);
+#  else /* ifndef USE_OPENSSL */
+	printf ("%s\n", _("WARNING - Plugin does not support checking certificates."));
+	return STATE_WARNING;
+#  endif /* USE_OPENSSL */
+}
+
+int np_net_ssl_check_cert_real(SSL *ssl, int days_till_exp_warn, int days_till_exp_crit){
 #  ifdef USE_OPENSSL
 	X509 *certificate=NULL;
 	X509_NAME *subj=NULL;
@@ -214,7 +235,7 @@ int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
 	// Prefix whatever we're about to print with SSL
 	printf("SSL ");
 
-	certificate=SSL_get_peer_certificate(s);
+	certificate=SSL_get_peer_certificate(ssl);
 	if (!certificate) {
 		printf("%s\n",_("CRITICAL - Cannot retrieve server certificate."));
 		return STATE_CRITICAL;
@@ -304,7 +325,7 @@ int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
 		else
 			status = STATE_CRITICAL;
 	} else {
-		printf(_("OK - Certificate '%s' will expire on %s. "), cn, timestamp);
+		printf(_("OK - Certificate '%s' will expire in %u days on %s.\n"), cn, days_left, timestamp);
 		status = STATE_OK;
 	}
 	X509_free(certificate);

+ 17 - 1
plugins/t/check_apt.t

@@ -23,7 +23,7 @@ sub make_result_regexp {
 }
 
 if (-x "./check_apt") {
-	plan tests => 28;
+	plan tests => 36;
 } else {
 	plan skip_all => "No check_apt compiled";
 }
@@ -40,10 +40,18 @@ $result = NPTest->testCmd( sprintf($testfile_command, "", "debian2") );
 is( $result->return_code, 1, "Debian apt output, warning" );
 like( $result->output, make_result_regexp(13, 0), "Output correct" );
 
+$result = NPTest->testCmd( sprintf($testfile_command, "-o", "debian2") );
+is( $result->return_code, 0, "Debian apt output, no critical" );
+like( $result->output, make_result_regexp(13, 0), "Output correct" );
+
 $result = NPTest->testCmd( sprintf($testfile_command, "", "debian3") );
 is( $result->return_code, 2, "Debian apt output, some critical" );
 like( $result->output, make_result_regexp(19, 4), "Output correct" );
 
+$result = NPTest->testCmd( sprintf($testfile_command, "-o", "debian3") );
+is( $result->return_code, 2, "Debian apt output, some critical" );
+like( $result->output, make_result_regexp(19, 4), "Output correct" );
+
 $result = NPTest->testCmd( sprintf($testfile_command, "-c '^[^\\(]*\\(.* (Debian-Security:|Ubuntu:[^/]*/[^-]*-security)'", "debian3") );
 is( $result->return_code, 2, "Debian apt output - should have same result when default security regexp specified via -c" );
 like( $result->output, make_result_regexp(19, 4), "Output correct" );
@@ -52,6 +60,10 @@ $result = NPTest->testCmd( sprintf($testfile_command, "-i libc6", "debian3") );
 is( $result->return_code, 1, "Debian apt output, filter for libc6" );
 like( $result->output, make_result_regexp(3, 0), "Output correct" );
 
+$result = NPTest->testCmd( sprintf($testfile_command, "-i libc6", "debian3") );
+is( $result->return_code, 1, "Debian apt output, filter for libc6, not critical" );
+like( $result->output, make_result_regexp(3, 0), "Output correct" );
+
 $result = NPTest->testCmd( sprintf($testfile_command, "-i libc6 -i xen", "debian3") );
 is( $result->return_code, 2, "Debian apt output, filter for libc6 and xen" );
 like( $result->output, make_result_regexp(9, 4), "Output correct" );
@@ -64,6 +76,10 @@ $result = NPTest->testCmd( sprintf($testfile_command, "-e libc6", "debian3") );
 is( $result->return_code, 2, "Debian apt output, filter out libc6" );
 like( $result->output, make_result_regexp(16, 4), "Output correct" );
 
+$result = NPTest->testCmd( sprintf($testfile_command, "-e libc6 -o", "debian3") );
+is( $result->return_code, 2, "Debian apt output, filter out libc6, critical" );
+like( $result->output, make_result_regexp(16, 4), "Output correct" );
+
 $result = NPTest->testCmd( sprintf($testfile_command, "-e libc6 -e xen", "debian3") );
 is( $result->return_code, 1, "Debian apt output, filter out libc6 and xen" );
 like( $result->output, make_result_regexp(10, 0), "Output correct" );

+ 25 - 16
plugins/utils.c

@@ -204,31 +204,40 @@ int
 parse_timeout_string (char *timeout_str)
 {
 	char *seperated_str;
-        char *timeout_val = "";
+    char *timeout_val = "";
 	char *timeout_sta = NULL;
-        if ( strstr(timeout_str, ":" ) == NULL) {
+
+	if (strstr(timeout_str, ":") == NULL) {
 		timeout_val = timeout_str;
-        } else if ( strncmp(timeout_str, ":", 1 ) == 0) {
+	} 
+	else if (strncmp(timeout_str, ":", 1) == 0) {
 		seperated_str = strtok(timeout_str, ":");
-                if ( seperated_str != NULL ) {
-                	timeout_sta = seperated_str;
+
+		if (seperated_str != NULL) {
+			timeout_sta = seperated_str;
 		}
-        } else {
+	}
+	else {
 		seperated_str = strtok(timeout_str, ":");
-                timeout_val = seperated_str;
-                seperated_str = strtok(NULL, ":");
-                if (seperated_str != NULL) {
-                        timeout_sta = seperated_str;
-                }
-        }
-        if ( timeout_sta != NULL ) {
+		timeout_val = seperated_str;
+		seperated_str = strtok(NULL, ":");
+
+		if (seperated_str != NULL) {
+			timeout_sta = seperated_str;
+		}
+	}
+
+	if (timeout_sta != NULL) {
 		set_timeout_state(timeout_sta);
 	}
-	if (( timeout_val == NULL ) || ( timeout_val[0] == '\0' )) {
+
+	if ((timeout_val == NULL) || (timeout_val[0] == '\0')) {
 		return timeout_interval;
-	} else if (is_intpos(timeout_val)) {
+	} 
+	else if (is_intpos(timeout_val)) {
 		return atoi(timeout_val);
-	} else {
+	}
+	else {
 		usage4 (_("Timeout value must be a positive integer"));
 		exit (STATE_UNKNOWN);
 	}

Some files were not shown because too many files changed in this diff