Explorar el Código

Merge branch '2.1.0-beta-RC1' into timeout_state

Conflicts:
	plugins/check_snmp.c
Spenser Reinhardt hace 11 años
padre
commit
d57816ec0c
Se han modificado 53 ficheros con 1010 adiciones y 514 borrados
  1. 7 0
      .gitignore
  2. 22 1
      THANKS.in
  3. 51 1
      configure.ac
  4. 85 89
      lib/parse_ini.c
  5. 0 40
      lib/parse_ini.h
  6. 6 3
      lib/tests/test_utils.c
  7. 86 87
      lib/utils_base.c
  8. 34 9
      lib/utils_cmd.c
  9. 1 1
      nagios-plugins.spec.in
  10. 13 4
      plugins-root/check_dhcp.c
  11. 3 2
      plugins-scripts/check_file_age.pl
  12. 38 19
      plugins-scripts/check_ifstatus.pl
  13. 21 4
      plugins-scripts/check_log.sh
  14. 22 8
      plugins-scripts/check_mailq.pl
  15. 2 0
      plugins-scripts/check_oracle.sh
  16. 2 2
      plugins-scripts/check_sensors.sh
  17. 1 1
      plugins-scripts/t/check_disk_smb.t
  18. 7 1
      plugins-scripts/t/check_file_age.t
  19. 1 0
      plugins-scripts/utils.pm.in
  20. 1 1
      plugins/Makefile.am
  21. 1 1
      plugins/check_apt.c
  22. 2 1
      plugins/check_by_ssh.c
  23. 3 3
      plugins/check_dbi.c
  24. 6 3
      plugins/check_dig.c
  25. 56 4
      plugins/check_disk.c
  26. 109 132
      plugins/check_dns.c
  27. 148 14
      plugins/check_http.c
  28. 30 8
      plugins/check_ldap.c
  29. 29 9
      plugins/check_mrtgtraf.c
  30. 1 0
      plugins/check_nagios.c
  31. 1 1
      plugins/check_ntp.c
  32. 6 3
      plugins/check_ntp_peer.c
  33. 48 6
      plugins/check_procs.c
  34. 5 5
      plugins/check_real.c
  35. 44 12
      plugins/check_snmp.c
  36. 6 6
      plugins/check_ssh.c
  37. 4 4
      plugins/check_tcp.c
  38. 3 3
      plugins/check_ups.c
  39. 1 1
      plugins/negate.c
  40. 6 7
      plugins/netutils.c
  41. 1 1
      plugins/netutils.h
  42. 9 3
      plugins/sslutils.c
  43. 1 0
      plugins/t/check_dns.t
  44. 1 1
      plugins/t/check_procs.t
  45. 1 1
      plugins/t/negate.t
  46. 27 5
      plugins/tests/check_http.t
  47. 10 1
      plugins/tests/check_snmp.t
  48. 2 2
      po/de.po
  49. 2 2
      po/fr.po
  50. 2 2
      po/nagios-plugins.pot
  51. 2 0
      test.pl.in
  52. 38 0
      tools/find_authors
  53. 2 0
      tools/generate-change-log

+ 7 - 0
.gitignore

@@ -1,6 +1,12 @@
+#Tooling:
+tags
+cscope.out
+
 # In all paths
 NP-VERSION-FILE
 *.o
+*.swp
+*.rej
 
 # /
 /aclocal.m4
@@ -35,6 +41,7 @@ NP-VERSION-FILE
 /build-aux/install-sh
 /build-aux/missing
 /build-aux/mkinstalldirs
+/build-aux/test-driver
 
 # /doc/
 /doc/developer-guidelines.html

+ 22 - 1
THANKS.in

@@ -321,4 +321,25 @@ Evgeni Golov
 Davide Madrisan
 Dawid Golunski
 Gunnar Beutner
-Eric Mislivec
+Eric J. Mislivec
+Pawel Rozlach
+Laurent Licour
+Koen Wilde
+Chris Wilson
+Jason Erdmann
+Sebastian Herbszt
+Yannick Charton
+Andrew Berglund
+Johannes Engel
+Andreas Seemueller
+Adrian Murphy
+Jonas Genannt
+Nick Peelman
+Mikael Falkvidd
+Alexander Wittig
+Stephane Lapie
+Trevor McDonald
+Joseph Gooch
+Damian Myerscough
+nafets
+arvanus

+ 51 - 1
configure.ac

@@ -161,6 +161,12 @@ AC_CHECK_LIB(socket,socket,SOCKETLIBS="$SOCKETLIBS -lsocket")
 AC_CHECK_LIB(resolv,main,SOCKETLIBS="$SOCKETLIBS -lresolv")
 AC_SUBST(SOCKETLIBS)
 
+dnl Check for POSIX thread libraries
+AC_CHECK_HEADERS(pthread.h)
+AC_CHECK_LIB(pthread,pthread_create,THREADLIBS="-lpthread",
+             AC_CHECK_LIB(pthread,pthread_create,THREADLIBS="-lpthread -lrt",-lrt))
+AC_SUBST(THREADLIBS)
+
 dnl
 dnl check for math-related functions needing -lm
 AC_CHECK_HEADERS(math.h)
@@ -310,7 +316,7 @@ AS_IF([test "x$with_ldap" != "xno"], [
     AC_SUBST(LDAPINCLUDE)
     AC_CHECK_FUNCS(ldap_set_option)
     EXTRAS="$EXTRAS check_ldap\$(EXEEXT)"
-  	AC_CHECK_FUNCS(ldap_init ldap_set_option ldap_get_option ldap_start_tls_s)
+  	AC_CHECK_FUNCS(ldap_initialize ldap_init ldap_set_option ldap_get_option ldap_start_tls_s)
   else
     AC_MSG_WARN([Skipping LDAP plugin])
     AC_MSG_WARN([install LDAP libs to compile this plugin (see REQUIREMENTS).])
@@ -626,6 +632,7 @@ AC_DEFINE_UNQUOTED(SOCKET_SIZE_TYPE, $ac_cv_socket_size_type ,
 dnl #### Process table test
 
 AC_PATH_PROG(PATH_TO_PS,ps)
+AC_PATH_PROG(PATH_TO_ENV,env)
 
 AC_MSG_CHECKING(for ps syntax)
 AC_ARG_WITH(ps_command,
@@ -755,6 +762,26 @@ dnl 	ac_cv_ps_format=["%*s %d %d %d %d %*d %*d %d %d%*[ 0123456789abcdef]%[OSRZT
 dnl 	ac_cv_ps_cols=8
 dnl 	AC_MSG_RESULT([$ac_cv_ps_command])
 
+dnl Lets test if cgroups are supported, on systems with ps axwo command:
+elif ps axwo 'stat comm vsz rss user uid pid ppid args cgroup:256' 2>/dev/null | \
+	egrep -i ["^ *STAT +[UCOMAND]+ +VSZ +RSS +USER +UID +PID +PPID +COMMAND +CGROUP"] > /dev/null
+then
+	ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procrss,&procpcpu,proc_cgroup_hierarchy,procprog,&pos]"
+	ac_cv_ps_command="$PATH_TO_PS axwo 'stat uid pid ppid vsz rss pcpu cgroup:256 comm args'"
+	ac_cv_ps_format="%s %d %d %d %d %d %f %s %s %n"
+	ac_cv_ps_cols=10
+	AC_MSG_RESULT([$ac_cv_ps_command])
+
+dnl cgroups with ps -axwo command:
+elif ps -axwo 'stat comm vsz rss user uid pid ppid args cgroup:256' 2>/dev/null | \
+	egrep -i ["^ *STAT +[UCOMAND]+ +VSZ +RSS +USER +UID +PID +PPID +COMMAND +CGROUP"] > /dev/null
+then
+	ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procrss,&procpcpu,proc_cgroup_hierarchy,procprog,&pos]"
+	ac_cv_ps_command="$PATH_TO_PS -axwo 'stat uid pid ppid vsz rss pcpu cgroup:256 comm args'"
+	ac_cv_ps_format="%s %d %d %d %d %d %f %s %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 -axwo and need axwo.
 dnl so test for this first...
 elif ps axwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \
@@ -947,6 +974,19 @@ then
 	ac_cv_ps_cols=6
 	AC_MSG_RESULT([$ac_cv_ps_command])
 
+dnl HP-UX:
+dnl S        UID       RUID USER     RUSER      PID  PPID     VSZ  %CPU COMMAND         COMMAND
+dnl S          0        400 root     oracle    2805     1   12904  0.00 ora_dism_SEA1X  ora_dism_SEA1X
+dnl S        400        400 oracle   oracle   19261     1  126488  0.00 tnslsnr         /u01/app/oracle/product/db/11.2.0.3/bin/tnslsnr LISTENER -inherit
+elif env UNIX95=1 ps -eo 'state uid ruid user ruser pid ppid vsz pcpu comm args' 2>/dev/null | head -n 1 | \
+    egrep -i ["^ *S +UID +RUID +USER +RUSER +PID +PPID +VSZ +%CPU +COMMAND +COMMAND"] >/dev/null
+then
+    ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procpcpu,procprog,&pos]"
+    ac_cv_ps_command="$PATH_TO_ENV UNIX95=1 $PATH_TO_PS -eo 'state uid pid ppid vsz pcpu comm args'"
+    ac_cv_ps_format="%s %d %d %d %d %f %s %n"
+    ac_cv_ps_cols=8
+    AC_MSG_RESULT([$ac_cv_ps_command])
+
 dnl AIX 4.1:
 dnl     F S      UID   PID  PPID   C PRI NI ADDR  SZ  RSS   WCHAN    TTY  TIME CMD
 dnl    303 A        0     0     0 120  16 -- 1c07  20   24              -  0:45 swapper
@@ -1480,6 +1520,16 @@ else
 	AC_MSG_WARN([Get ssh in order to make check_by_ssh plugin])
 fi
 
+AC_PATH_PROG(PATH_TO_SUDO,sudo)
+AC_ARG_WITH(sudo_command,
+            ACX_HELP_STRING([--with-sudo-command=PATH],
+                            [sets path to sudo]), PATH_TO_SUDO=$withval)
+if test -n "$PATH_TO_SUDO"
+then
+	AC_DEFINE_UNQUOTED(PATH_TO_SUDO,"$PATH_TO_SUDO",[path to sudo])
+else
+	AC_MSG_WARN([Could not find sudo or eqivalent])
+fi
 
 AC_PATH_PROG(PATH_TO_MAILQ,mailq)
 AC_ARG_WITH(mailq_command,

+ 85 - 89
lib/parse_ini.c

@@ -30,8 +30,6 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-/* TODO: die like N::P if config file is not found */
-
 /* np_ini_info contains the result of parsing a "locator" in the format
  * [stanza_name][@config_filename] (check_foo@/etc/foo.ini, for example)
  */
@@ -40,6 +38,33 @@ typedef struct {
 	char *stanza;
 } np_ini_info;
 
+static char *default_ini_file_names[] = {
+	"plugins.ini",
+	"nagios-plugins.ini",
+	NULL
+};
+
+static char *default_ini_path_names[] = {
+	"/usr/local/nagios/etc/plugins.ini",
+	"/usr/local/nagios/etc/nagios-plugins.ini",
+	"/usr/local/etc/nagios/plugins.ini",
+	"/usr/local/etc/nagios/nagios-plugins.ini",
+	"/usr/local/etc/nagios-plugins.ini",
+	"/usr/local/etc/nagios-plugins/nagios-plugins.ini",
+	"/usr/local/etc/nagios-plugins/plugins.ini",
+	"/usr/local/etc/nagios/plugins.ini",
+	"/usr/local/etc/nagios/nagios-plugins.ini",
+	"/etc/nagios-plugins.ini",
+	"/etc/nagios/plugins.ini",
+	"/etc/nagios/nagios-plugins.ini",
+	"/etc/nagios-plugins/nagios-plugins.ini",
+	"/etc/nagios-plugins/plugins.ini",
+	"/etc/opt/nagios-plugins.ini",
+	"/etc/opt/nagios/plugins.ini",
+	"/etc/opt/nagios/nagios-plugins.ini",
+	NULL
+};
+
 /* eat all characters from a FILE pointer until n is encountered */
 #define GOBBLE_TO(f, c, n) do { (c)=fgetc((f)); } while((c)!=EOF && (c)!=(n))
 
@@ -47,10 +72,9 @@ typedef struct {
 static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts);
 /* internal function that converts a single line into options format */
 static int add_option(FILE *f, np_arg_list **optlst);
-/* internal function to find default file */
+/* internal functions to find default file */
 static char* default_file(void);
-/* internal function to test files access */
-static int test_file(const char* env, int len, const char* file, char* temp_file);
+static char* default_file_in_path(void);
 
 /* parse_locator decomposes a string of the form
  * 	[stanza][@filename]
@@ -66,24 +90,23 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in
 	}
 	/* if a non-default stanza is provided */
 	if(stanza_len>0){
-		i->stanza=(char*)malloc(sizeof(char)*(stanza_len+1));
+		i->stanza=malloc(sizeof(char)*(stanza_len+1));
 		strncpy(i->stanza, locator, stanza_len);
 		i->stanza[stanza_len]='\0';
 	} else { /* otherwise we use the default stanza */
 		i->stanza=strdup(def_stanza);
 	}
+	if(i->stanza==NULL){
+		die(STATE_UNKNOWN, "%s\n", _("malloc() failed!"));
+	}
 	/* if there is no @file part */
 	if(stanza_len==locator_len){
 		i->file=default_file();
-		if(strcmp(i->file, "") == 0){
-			die(STATE_UNKNOWN, _("Cannot find '%s' or '%s' in any standard location.\n"), NP_DEFAULT_INI_FILENAME1, NP_DEFAULT_INI_FILENAME2);
-		}
 	} else {
 		i->file=strdup(&(locator[stanza_len+1]));
 	}
-
-	if(i->file==NULL || i->stanza==NULL){
-		die(STATE_UNKNOWN, _("malloc() failed!\n"));
+	if(i->file==NULL || i->file[0]=='\0'){
+		die(STATE_UNKNOWN, "%s\n", _("Cannot find config file in any standard location."));
 	}
 }
 
@@ -118,15 +141,24 @@ np_arg_list* np_get_defaults(const char *locator, const char *default_section){
                                 die(STATE_UNKNOWN, "%s %s\n", _("Can't read config file."), strerror(errno));
                 }
 
+		/* before attempting access, let's make sure inifile is not null, this should never be the case though */
+		if (inifile == NULL)
+			die(STATE_UNKNOWN, "%s %s\n", _("Can't read config file:"), strerror(errno));
                 /* inifile points to an open FILE our ruid/rgid can access, parse its contents. */
                 if (read_defaults(inifile, i.stanza, &defaults) == FALSE)
-                        die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file);
+                        die(STATE_UNKNOWN,"%s%s%s%s'\n", _("Invalid section '"), i.stanza, _("' in config file '"), i.file);
 
                 if (inifile != stdin) fclose(inifile);
-        }
+        } 
 
-	if (i.file != NULL) free(i.file);
-	free(i.stanza);
+	if (i.file != NULL) {
+		free(i.file);
+		i.file = NULL;
+	}
+	if (i.stanza != NULL) {
+		free(i.stanza);
+		i.stanza = NULL;
+	}
 
 	if (is_suid_set && idpriv_temp_restore() == -1) 
 		die(STATE_UNKNOWN, "%s %s\n", _("Can't restore user permissions."), strerror(errno));
@@ -163,7 +195,7 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){
 				for(i=0; i<stanza_len; i++){
 					c=fgetc(f);
 					/* Strip leading whitespace */
-					if(i==0) for(c; isspace(c); c=fgetc(f));
+					if(i==0) for(; isspace(c); c=fgetc(f));
 					/* nope, read to the end of the line */
 					if(c!=stanza[i]) {
 						GOBBLE_TO(f, c, '\n');
@@ -174,7 +206,7 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){
 				if(i==stanza_len){
 					c=fgetc(f);
 					/* Strip trailing whitespace */
-					for(c; isspace(c); c=fgetc(f));
+					for(; isspace(c); c=fgetc(f));
 					if(c==']') stanzastate=RIGHTSTANZA;
 				}
 				break;
@@ -186,7 +218,6 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){
 					 */
 					case NOSTANZA:
 						die(STATE_UNKNOWN, "%s\n", _("Config file error"));
-						break;
 					/* we're in a stanza, but for a different plugin */
 					case WRONGSTANZA:
 						GOBBLE_TO(f, c, '\n');
@@ -216,7 +247,7 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts){
 static int add_option(FILE *f, np_arg_list **optlst){
 	np_arg_list *opttmp=*optlst, *optnew;
 	char *linebuf=NULL, *lineend=NULL, *optptr=NULL, *optend=NULL;
-	char *eqptr=NULL, *valptr=NULL, *spaceptr=NULL, *valend=NULL;
+	char *eqptr=NULL, *valptr=NULL, *valend=NULL;
 	short done_reading=0, equals=0, value=0;
 	size_t cfg_len=0, read_sz=8, linebuf_sz=0, read_pos=0;
 	size_t opt_len=0, val_len=0;
@@ -227,9 +258,9 @@ static int add_option(FILE *f, np_arg_list **optlst){
 		if(linebuf==NULL || read_pos+read_sz >= linebuf_sz){
 			linebuf_sz=(linebuf_sz>0)?linebuf_sz<<1:read_sz;
 			linebuf=realloc(linebuf, linebuf_sz);
-			if(linebuf==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n"));
+			if(linebuf==NULL) die(STATE_UNKNOWN, "%s\n", _("malloc() failed!"));
 		}
-		if(fgets(&linebuf[read_pos], read_sz, f)==NULL) done_reading=1;
+		if(fgets(&linebuf[read_pos], (int)read_sz, f)==NULL) done_reading=1;
 		else {
 			read_pos=strlen(linebuf);
 			if(linebuf[read_pos-1]=='\n') {
@@ -258,9 +289,9 @@ static int add_option(FILE *f, np_arg_list **optlst){
 	for(valend=valptr; valend<lineend; valend++);
 	--valend;
 	/* Finally trim off trailing spaces */
-	for(valend; isspace(*valend); valend--);
+	for(; isspace(*valend); valend--);
 	/* calculate the length of "--foo" */
-	opt_len=1+optend-optptr;
+	opt_len=(size_t)(1+optend-optptr);
 	/* 1-character params needs only one dash */
 	if(opt_len==1)
 		cfg_len=1+(opt_len);
@@ -269,7 +300,7 @@ static int add_option(FILE *f, np_arg_list **optlst){
 	/* if valptr<lineend then we have to also allocate space for "=bar" */
 	if(valptr<lineend) {
 		equals=value=1;
-		val_len=1+valend-valptr;
+		val_len=(size_t)(1+valend-valptr);
 		cfg_len+=1+val_len;
 	}
 	/* if valptr==valend then we have "=" but no "bar" */
@@ -283,11 +314,11 @@ static int add_option(FILE *f, np_arg_list **optlst){
 	/* okay, now we have all the info we need, so we create a new np_arg_list
 	 * element and set the argument...
 	 */
-	optnew=(np_arg_list *)malloc(sizeof(np_arg_list));
+	optnew=malloc(sizeof(np_arg_list));
 	optnew->next=NULL;
 
 	read_pos=0;
-	optnew->arg=(char *)malloc(cfg_len+1);
+	optnew->arg=malloc(cfg_len+1);
 	/* 1-character params needs only one dash */
 	if(opt_len==1) {
 		strncpy(&optnew->arg[read_pos], "-", 1);
@@ -317,71 +348,36 @@ static int add_option(FILE *f, np_arg_list **optlst){
 	return 0;
 }
 
-static char* default_file(void){
-	struct stat sb;
-	char *np_env=NULL, *default_file=NULL;
-	char temp_file[MAX_INPUT_BUFFER];
-	size_t len;
-
-	if((np_env=getenv("NAGIOS_CONFIG_PATH"))!=NULL) {
-		/* skip any starting colon... */
-		while(*np_env==':') np_env++;
-		/* Look for NP_DEFAULT_INI_FILENAME1 and NP_DEFAULT_INI_FILENAME2 in
-		 * every PATHs defined (colon-separated).
-		 */
-		while((len=strcspn(np_env,":"))>0){
-			/* Test NP_DEFAULT_INI_FILENAME[1-2] in current np_env token */
-			if(test_file(np_env,len,NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
-			   test_file(np_env,len,NP_DEFAULT_INI_FILENAME2,temp_file)==1){
-				default_file=strdup(temp_file);
-				break;
+static char *default_file_in_path(void){
+	char *config_path, **file;
+	char *dir, *ini_file, *tokens;
+
+	if((config_path=getenv("NAGIOS_CONFIG_PATH"))==NULL)
+		return NULL;
+
+	if((tokens=strdup(config_path))==NULL)
+		die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory"));
+	for(dir=strtok(tokens, ":"); dir!=NULL; dir=strtok(NULL, ":")){
+		for(file=default_ini_file_names; *file!=NULL; file++){
+			if((asprintf(&ini_file, "%s/%s", dir, *file))<0)
+				die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory"));
+			if(access(ini_file, F_OK)==0){
+				free(tokens);
+				return ini_file;
 			}
-
-			/* Move on to the next token */
-			np_env+=len;
-			while(*np_env==':') np_env++;
-		} /* while(...) */
-	} /* if(getenv("NAGIOS_CONFIG_PATH")) */
-
-	/* Look for NP_DEFAULT_INI_FILENAME1 in NP_DEFAULT_INI_NAGIOS_PATH[1-4] */
-	if(!default_file){
-		if(test_file(NP_DEFAULT_INI_NAGIOS_PATH1,strlen(NP_DEFAULT_INI_NAGIOS_PATH1),NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
-		   test_file(NP_DEFAULT_INI_NAGIOS_PATH2,strlen(NP_DEFAULT_INI_NAGIOS_PATH2),NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
-		   test_file(NP_DEFAULT_INI_NAGIOS_PATH3,strlen(NP_DEFAULT_INI_NAGIOS_PATH3),NP_DEFAULT_INI_FILENAME1,temp_file)==1 ||
-		   test_file(NP_DEFAULT_INI_NAGIOS_PATH4,strlen(NP_DEFAULT_INI_NAGIOS_PATH4),NP_DEFAULT_INI_FILENAME1,temp_file)==1)
-			default_file=strdup(temp_file);
-	}
-
-	/* Look for NP_DEFAULT_INI_FILENAME2 in NP_DEFAULT_INI_PATH[1-3] */
-	if(!default_file){
-		if(test_file(NP_DEFAULT_INI_PATH1,strlen(NP_DEFAULT_INI_PATH1),NP_DEFAULT_INI_FILENAME2,temp_file)==1 ||
-		   test_file(NP_DEFAULT_INI_PATH2,strlen(NP_DEFAULT_INI_PATH2),NP_DEFAULT_INI_FILENAME2,temp_file)==1 ||
-		   test_file(NP_DEFAULT_INI_PATH3,strlen(NP_DEFAULT_INI_PATH3),NP_DEFAULT_INI_FILENAME2,temp_file)==1)
-			default_file=strdup(temp_file);
+		}
 	}
-
-	/* Return default_file or empty string (should return NULL if we want plugins
-	 * to die there)...
-	 */
-	if(default_file)
-		return default_file;
-	return "";
+	free(tokens);
+	return NULL;
 }
 
-/* put together len bytes from env and the filename and test for its
- * existence. Returns 1 if found, 0 if not and -1 if test wasn't performed.
- */
-static int test_file(const char* env, int len, const char* file, char* temp_file){
-
-	/* test if len + filelen + '/' + '\0' fits in temp_file */
-	if((len+strlen(file)+2)>MAX_INPUT_BUFFER)	return -1;
-
-	strncpy(temp_file,env,len);
-	temp_file[len]='\0';
-	strncat(temp_file,"/",len+1);
-	strncat(temp_file,file,len+strlen(file)+1);
+static char *default_file(void){
+	char **p, *ini_file;
 
-	if(access(temp_file, F_OK) == 0) return 1;
-	return 0;
+	if((ini_file=default_file_in_path())!=NULL)
+		return ini_file;
+	for(p=default_ini_path_names; *p!=NULL; p++)
+		if (access(*p, F_OK)==0)
+			return *p;
+	return NULL;
 }
-

+ 0 - 40
lib/parse_ini.h

@@ -13,46 +13,6 @@ typedef struct np_arg_el {
 	struct np_arg_el *next;
 } np_arg_list;
 
-/* FIXME: This is in plugins/common.c. Should be eventually moved to lib/
- * (although for this particular one a configure settings should be ideal)
- */
-#ifndef MAX_INPUT_BUFFER
-# define MAX_INPUT_BUFFER 8192
-#endif /* MAX_INPUT_BUFFER */
-
-/* Filenames (see below) */
-#ifndef NP_DEFAULT_INI_FILENAME1
-# define NP_DEFAULT_INI_FILENAME1 "plugins.ini"
-#endif /* NP_DEFAULT_INI_FILENAME1 */
-#ifndef NP_DEFAULT_INI_FILENAME2
-# define NP_DEFAULT_INI_FILENAME2 "nagios-plugins.ini"
-#endif /* NP_DEFAULT_INI_FILENAME2 */
-
-/* Config paths ending in nagios (search for NP_DEFAULT_INI_FILENAME1) */
-#ifndef NP_DEFAULT_INI_NAGIOS_PATH1
-# define NP_DEFAULT_INI_NAGIOS_PATH1 "/etc/nagios"
-#endif /* NP_DEFAULT_INI_NAGIOS_PATH1 */
-#ifndef NP_DEFAULT_INI_NAGIOS_PATH2
-# define NP_DEFAULT_INI_NAGIOS_PATH2 "/usr/local/nagios/etc"
-#endif /* NP_DEFAULT_INI_NAGIOS_PATH2 */
-#ifndef NP_DEFAULT_INI_NAGIOS_PATH3
-# define NP_DEFAULT_INI_NAGIOS_PATH3 "/usr/local/etc/nagios"
-#endif /* NP_DEFAULT_INI_NAGIOS_PATH3 */
-#ifndef NP_DEFAULT_INI_NAGIOS_PATH4
-# define NP_DEFAULT_INI_NAGIOS_PATH4 "/etc/opt/nagios"
-#endif /* NP_DEFAULT_INI_NAGIOS_PATH4 */
-
-/* Config paths not ending in nagios (search for NP_DEFAULT_INI_FILENAME2) */
-#ifndef NP_DEFAULT_INI_PATH1
-# define NP_DEFAULT_INI_PATH1 "/etc"
-#endif /* NP_DEFAULT_INI_PATH1 */
-#ifndef NP_DEFAULT_INI_PATH2
-# define NP_DEFAULT_INI_PATH2 "/usr/local/etc"
-#endif /* NP_DEFAULT_INI_PATH2 */
-#ifndef NP_DEFAULT_INI_PATH3
-# define NP_DEFAULT_INI_PATH3 "/etc/opt"
-#endif /* NP_DEFAULT_INI_PATH3 */
-
 /* np_load_defaults: load the default configuration (if present) for
  * a plugin from the ini file
  */

+ 6 - 3
lib/tests/test_utils.c

@@ -21,6 +21,7 @@
 
 #include "tap.h"
 
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -29,6 +30,7 @@
 int
 main (int argc, char **argv)
 {
+	char state_path[1024];
 	range	*range;
 	double	temp;
 	thresholds *thresholds = NULL;
@@ -345,9 +347,10 @@ main (int argc, char **argv)
 
 	np_enable_state("allowedchars_in_keyname", 77);
 	temp_state_key = this_nagios_plugin->state;
+	sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/allowedchars_in_keyname", (unsigned long)geteuid());
 	ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" );
 	ok( !strcmp(temp_state_key->name, "allowedchars_in_keyname"), "Got key name with valid chars" );
-	ok( !strcmp(temp_state_key->_filename, "/usr/local/nagios/var/check_test/allowedchars_in_keyname"), "Got internal filename" );
+	ok( !strcmp(temp_state_key->_filename, state_path), "Got internal filename" );
 
 
 	/* Don't do this test just yet. Will die */
@@ -359,9 +362,9 @@ main (int argc, char **argv)
 
 	np_enable_state("funnykeyname", 54);
 	temp_state_key = this_nagios_plugin->state;
+	sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/funnykeyname", (unsigned long)geteuid());
 	ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" );
-	ok( !strcmp(temp_state_key->name, "funnykeyname"), "Got key name" );
-
+	ok( !strcmp(temp_state_key->name, state_path), "Got key name" );
 
 
 	ok( !strcmp(temp_state_key->_filename, "/usr/local/nagios/var/check_test/funnykeyname"), "Got internal filename" );

+ 86 - 87
lib/utils_base.c

@@ -40,23 +40,22 @@ nagios_plugin *this_nagios_plugin=NULL;
 int _np_state_read_file(FILE *);
 
 void np_init( char *plugin_name, int argc, char **argv ) {
-	if (this_nagios_plugin==NULL) {
+	if (!this_nagios_plugin) {
 		this_nagios_plugin = calloc(1, sizeof(nagios_plugin));
-		if (this_nagios_plugin==NULL) {
-			die(STATE_UNKNOWN, _("Cannot allocate memory: %s"),
-			    strerror(errno));
+		if (!this_nagios_plugin) {
+			die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 		}
 		this_nagios_plugin->plugin_name = strdup(plugin_name);
-		if (this_nagios_plugin->plugin_name==NULL)
-			die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
+		if (!this_nagios_plugin->plugin_name)
+			die(STATE_UNKNOWN, "%s %s\n", _("Cannot execute strdup:"), strerror(errno));
 		this_nagios_plugin->argc = argc;
 		this_nagios_plugin->argv = argv;
 	}
 }
 
 void np_set_args( int argc, char **argv ) {
-	if (this_nagios_plugin==NULL)
-		die(STATE_UNKNOWN, _("This requires np_init to be called"));
+	if (!this_nagios_plugin)
+		die(STATE_UNKNOWN, "%s\n", _("This requires np_init to be called"));
 
 	this_nagios_plugin->argc = argc;
 	this_nagios_plugin->argv = argv;
@@ -64,8 +63,8 @@ void np_set_args( int argc, char **argv ) {
 
 
 void np_cleanup() {
-	if (this_nagios_plugin!=NULL) {
-		if(this_nagios_plugin->state!=NULL) {
+	if (this_nagios_plugin) {
+		if(this_nagios_plugin->state) {
 			if(this_nagios_plugin->state->state_data) { 
 				np_free(this_nagios_plugin->state->state_data->data);
 				np_free(this_nagios_plugin->state->state_data);
@@ -91,7 +90,7 @@ die (int result, const char *fmt, ...)
 	va_start (ap, fmt);
 	vprintf (fmt, ap);
 	va_end (ap);
-	if(this_nagios_plugin!=NULL) {
+	if(this_nagios_plugin) {
 		np_cleanup();
 	}
 	exit (result);
@@ -129,7 +128,7 @@ range
 	}
 
 	end_str = index(str, ':');
-	if (end_str != NULL) {
+	if (end_str) {
 		if (str[0] == '~') {
 			temp_range->start_infinity = TRUE;
 		} else {
@@ -141,12 +140,12 @@ range
 		end_str = str;
 	}
 	end = strtod(end_str, NULL);
-	if (strcmp(end_str, "") != 0) {
+	if (strcmp(end_str, "")) {
 		set_range_end(temp_range, end);
 	}
 
-	if (temp_range->start_infinity == TRUE ||
-		temp_range->end_infinity == TRUE ||
+	if (temp_range->start_infinity ||
+		temp_range->end_infinity ||
 		temp_range->start <= temp_range->end) {
 		return temp_range;
 	}
@@ -160,20 +159,21 @@ _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_st
 {
 	thresholds *temp_thresholds = NULL;
 
-	if ((temp_thresholds = calloc(1, sizeof(thresholds))) == NULL)
-		die(STATE_UNKNOWN, _("Cannot allocate memory: %s"),
-		    strerror(errno));
+	if (!(temp_thresholds = calloc(1, sizeof(thresholds))))
+		die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 
 	temp_thresholds->warning = NULL;
 	temp_thresholds->critical = NULL;
 
-	if (warn_string != NULL) {
-		if ((temp_thresholds->warning = parse_range_string(warn_string)) == NULL) {
+	if (warn_string) {
+		if (!(temp_thresholds->warning = parse_range_string(warn_string))) {
+			free(temp_thresholds);
 			return NP_RANGE_UNPARSEABLE;
 		}
 	}
-	if (critical_string != NULL) {
-		if ((temp_thresholds->critical = parse_range_string(critical_string)) == NULL) {
+	if (critical_string) {
+		if (!(temp_thresholds->critical = parse_range_string(critical_string))) {
+			free(temp_thresholds);
 			return NP_RANGE_UNPARSEABLE;
 		}
 	}
@@ -190,9 +190,9 @@ set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_str
 	case 0:
 		return;
 	case NP_RANGE_UNPARSEABLE:
-		die(STATE_UNKNOWN, _("Range format incorrect"));
+		die(STATE_UNKNOWN, "%s\n", _("Range format incorrect"));
 	case NP_WARN_WITHIN_CRIT:
-		die(STATE_UNKNOWN, _("Warning level is a subset of critical and will not be alerted"));
+		die(STATE_UNKNOWN, "%s\n", _("Warning level is a subset of critical and will not be alerted"));
 		break;
 	}
 }
@@ -228,19 +228,19 @@ check_range(double value, range *my_range)
 		yes = FALSE;
 	}
 
-	if (my_range->end_infinity == FALSE && my_range->start_infinity == FALSE) {
+	if (!my_range->end_infinity && !my_range->start_infinity) {
 		if ((my_range->start <= value) && (value <= my_range->end)) {
 			return no;
 		} else {
 			return yes;
 		}
-	} else if (my_range->start_infinity == FALSE && my_range->end_infinity == TRUE) {
+	} else if (!my_range->start_infinity && my_range->end_infinity) {
 		if (my_range->start <= value) {
 			return no;
 		} else {
 			return yes;
 		}
-	} else if (my_range->start_infinity == TRUE && my_range->end_infinity == FALSE) {
+	} else if (my_range->start_infinity && !my_range->end_infinity) {
 		if (value <= my_range->end) {
 			return no;
 		} else {
@@ -255,13 +255,13 @@ check_range(double value, range *my_range)
 int
 get_status(double value, thresholds *my_thresholds)
 {
-	if (my_thresholds->critical != NULL) {
-		if (check_range(value, my_thresholds->critical) == TRUE) {
+	if (my_thresholds->critical) {
+		if (check_range(value, my_thresholds->critical)) {
 			return STATE_CRITICAL;
 		}
 	}
-	if (my_thresholds->warning != NULL) {
-		if (check_range(value, my_thresholds->warning) == TRUE) {
+	if (my_thresholds->warning) {
+		if (check_range(value, my_thresholds->warning)) {
 			return STATE_WARNING;
 		}
 	}
@@ -303,12 +303,12 @@ int np_check_if_root(void) { return (geteuid() == 0); }
 int np_warn_if_not_root(void) {
 	int status = np_check_if_root();
 	if(!status) {
-		printf(_("Warning: "));
-		printf(_("This plugin must be either run as root or setuid root.\n"));
-		printf(_("To run as root, you can use a tool like sudo.\n"));
-		printf(_("To set the setuid permissions, use the command:\n"));
+		printf("%s", _("Warning: "));
+		printf("%s\n", _("This plugin must be either run as root or setuid root."));
+		printf("%s\n", _("To run as root, you can use a tool like sudo."));
+		printf("%s\n", _("To set the setuid permissions, use the command:"));
 		/* XXX could we use something like progname? */
-		printf("\tchmod u+s yourpluginfile\n");
+		printf("\t%s\n", _("chmod u+s yourpluginfile"));
 	}
 	return status;
 }
@@ -327,7 +327,7 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
 		/* Strip any leading space */
 		for (varlist; isspace(varlist[0]); varlist++);
 
-		if (strncmp(name, varlist, strlen(name)) == 0) {
+		if (!strncmp(name, varlist, strlen(name))) {
 			varlist += strlen(name);
 			/* strip trailing spaces */
 			for (varlist; isspace(varlist[0]); varlist++);
@@ -346,7 +346,7 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
 					value[tmp-varlist] = '\0';
 				} else {
 					/* Value is delimited by a \0 */
-					if (strlen(varlist) == 0) continue;
+					if (!strlen(varlist)) continue;
 					value = (char *)calloc(1, strlen(varlist) + 1);
 					strncpy(value, varlist, strlen(varlist));
 					value[strlen(varlist)] = '\0';
@@ -412,14 +412,14 @@ char *_np_state_generate_key() {
 	keyname[40]='\0';
 	
 	p = strdup(keyname);
-	if(p==NULL) {
-		die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
+	if(!p) {
+		die(STATE_UNKNOWN, "%s %s\n", _("Cannot execute strdup:"), strerror(errno));
 	}
 	return p;
 }
 
 void _cleanup_state_data() {
-	if (this_nagios_plugin->state->state_data!=NULL) {
+	if (this_nagios_plugin->state->state_data) {
 		np_free(this_nagios_plugin->state->state_data->data);
 		np_free(this_nagios_plugin->state->state_data);
 	}
@@ -436,7 +436,7 @@ char* _np_state_calculate_location_prefix(){
 	/* Do not allow passing NP_STATE_DIRECTORY in setuid plugins
 	 * for security reasons */
 
-	if (np_suid() == FALSE) {
+	if (!np_suid()) {
 		env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY");
 		if(env_dir && env_dir[0] != '\0')
 			return env_dir;
@@ -454,28 +454,27 @@ void np_enable_state(char *keyname, int expected_data_version) {
 	char *temp_filename = NULL;
 	char *temp_keyname = NULL;
 	char *p=NULL;
+	int ret;
 
-	if(this_nagios_plugin==NULL)
-		die(STATE_UNKNOWN, _("This requires np_init to be called"));
+	if(!this_nagios_plugin)
+		die(STATE_UNKNOWN, "%s\n", _("This requires np_init to be called"));
 
 	this_state = (state_key *) calloc(1, sizeof(state_key));
-	if(this_state==NULL)
-		die(STATE_UNKNOWN, _("Cannot allocate memory: %s"),
-		    strerror(errno));
+	if(!this_state)
+		die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 
-	if(keyname==NULL) {
+	if(!keyname) {
 		temp_keyname = _np_state_generate_key();
 	} else {
 		temp_keyname = strdup(keyname);
-		if(temp_keyname==NULL)
-			die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
+		if(!temp_keyname)
+			die(STATE_UNKNOWN, "%s %s\n", _("Cannot execute strdup:"), strerror(errno));
 	}
 	/* Die if invalid characters used for keyname */
 	p = temp_keyname;
 	while(*p!='\0') {
-		if(! (isalnum(*p) || *p == '_')) {
-			die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'"));
-		}
+		if(! (isalnum(*p) || *p == '_'))
+			die(STATE_UNKNOWN, "%s\n", _("Invalid character for keyname - only alphanumerics or '_'"));
 		p++;
 	}
 	this_state->name=temp_keyname;
@@ -484,7 +483,9 @@ void np_enable_state(char *keyname, int expected_data_version) {
 	this_state->state_data=NULL;
 
 	/* Calculate filename */
-	asprintf(&temp_filename, "%s/%s/%s", _np_state_calculate_location_prefix(), this_nagios_plugin->plugin_name, this_state->name);
+	ret = asprintf(&temp_filename, "%s/%lu/%s/%s", _np_state_calculate_location_prefix(), (unsigned long)geteuid(), this_nagios_plugin->plugin_name, this_state->name);
+	if (ret < 0)
+		die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 	this_state->_filename=temp_filename;
 
 	this_nagios_plugin->state = this_state;
@@ -502,17 +503,16 @@ state_data *np_state_read() {
 	FILE *statefile;
 	int rc = FALSE;
 
-	if(this_nagios_plugin==NULL)
-		die(STATE_UNKNOWN, _("This requires np_init to be called"));
+	if(!this_nagios_plugin)
+		die(STATE_UNKNOWN, "%s\n", _("This requires np_init to be called"));
 
 	/* Open file. If this fails, no previous state found */
 	statefile = fopen( this_nagios_plugin->state->_filename, "r" );
-	if(statefile!=NULL) {
+	if(statefile) {
 
 		this_state_data = (state_data *) calloc(1, sizeof(state_data));
-		if(this_state_data==NULL)
-			die(STATE_UNKNOWN, _("Cannot allocate memory: %s"),
-			    strerror(errno));
+		if(!this_state_data)
+			die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 
 		this_state_data->data=NULL;
 		this_nagios_plugin->state->state_data = this_state_data;
@@ -522,7 +522,7 @@ state_data *np_state_read() {
 		fclose(statefile);
 	}
 
-	if(rc==FALSE) {
+	if(!rc) {
 		_cleanup_state_data();
 	}
 
@@ -545,15 +545,13 @@ int _np_state_read_file(FILE *f) {
 
 	/* Note: This introduces a limit of 1024 bytes in the string data */
 	line = (char *) calloc(1, 1024);
-	if(line==NULL)
-		die(STATE_UNKNOWN, _("Cannot allocate memory: %s"),
-		    strerror(errno));
+	if(!line)
+		die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 
 	while(!failure && (fgets(line,1024,f))!=NULL){
 		pos=strlen(line);
-		if(line[pos-1]=='\n') {
+		if(line[pos-1]=='\n')
 			line[pos-1]='\0';
-		}
 
 		if(line[0] == '#') continue;
 
@@ -585,7 +583,7 @@ int _np_state_read_file(FILE *f) {
 			case STATE_DATA_TEXT:
 				this_nagios_plugin->state->state_data->data = strdup(line);
 				if(this_nagios_plugin->state->state_data->data==NULL)
-					die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
+					die(STATE_UNKNOWN, "%s %s\n", _("Cannot execute strdup:"), strerror(errno));
 				expected=STATE_DATA_END;
 				status=TRUE;
 				break;
@@ -613,25 +611,26 @@ void np_state_write_string(time_t data_time, char *data_string) {
 	char *directories=NULL;
 	char *p=NULL;
 
-	if(data_time==0)
+	if(!data_time)
 		time(&current_time);
 	else
 		current_time=data_time;
 	
 	/* If file doesn't currently exist, create directories */
-	if(access(this_nagios_plugin->state->_filename,F_OK)!=0) {
-		asprintf(&directories, "%s", this_nagios_plugin->state->_filename);
-		if(directories==NULL)
-			die(STATE_UNKNOWN, _("Cannot allocate memory: %s"),
-			    strerror(errno));
+	if(access(this_nagios_plugin->state->_filename,F_OK)) {
+		result = asprintf(&directories, "%s", this_nagios_plugin->state->_filename);
+		if (result < 0)
+			die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
+		if(!directories)
+			die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 
 		for(p=directories+1; *p; p++) {
 			if(*p=='/') {
 				*p='\0';
-				if((access(directories,F_OK)!=0) && (mkdir(directories, S_IRWXU)!=0)) {
+				if(access(directories,F_OK) && mkdir(directories, S_IRWXU)) {
 					/* Can't free this! Otherwise error message is wrong! */
 					/* np_free(directories); */ 
-					die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories);
+					die(STATE_UNKNOWN, "%s %s\n", _("Cannot create directory:"), directories);
 				}
 				*p='/';
 			}
@@ -639,22 +638,23 @@ void np_state_write_string(time_t data_time, char *data_string) {
 		np_free(directories);
 	}
 
-	asprintf(&temp_file,"%s.XXXXXX",this_nagios_plugin->state->_filename);
-	if(temp_file==NULL)
-		die(STATE_UNKNOWN, _("Cannot allocate memory: %s"),
-		    strerror(errno));
+	result = asprintf(&temp_file,"%s.XXXXXX",this_nagios_plugin->state->_filename);
+	if (result < 0)
+		die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
+	if(!temp_file)
+		die(STATE_UNKNOWN, "%s %s\n", _("Cannot allocate memory:"), strerror(errno));
 
 	if((fd=mkstemp(temp_file))==-1) {
 		np_free(temp_file);
-		die(STATE_UNKNOWN, _("Cannot create temporary filename"));
+		die(STATE_UNKNOWN, "%s\n", _("Cannot create temporary filename"));
 	}
 
 	fp=(FILE *)fdopen(fd,"w");
-	if(fp==NULL) {
+	if(!fp) {
 		close(fd);
 		unlink(temp_file);
 		np_free(temp_file);
-		die(STATE_UNKNOWN, _("Unable to open temporary state file"));
+		die(STATE_UNKNOWN, "%s\n", _("Unable to open temporary state file"));
 	}
 	
 	fprintf(fp,"# NP State file\n");
@@ -671,18 +671,17 @@ void np_state_write_string(time_t data_time, char *data_string) {
 
 	fsync(fd);
 
-	if(result!=0) {
+	if(result) {
 		unlink(temp_file);
 		np_free(temp_file);
-		die(STATE_UNKNOWN, _("Error writing temp file"));
+		die(STATE_UNKNOWN, "%s\n", _("Error writing temp file"));
 	}
 
-	if(rename(temp_file, this_nagios_plugin->state->_filename)!=0) {
+	if(rename(temp_file, this_nagios_plugin->state->_filename)) {
 		unlink(temp_file);
 		np_free(temp_file);
-		die(STATE_UNKNOWN, _("Cannot rename state temp file"));
+		die(STATE_UNKNOWN, "%s\n", _("Cannot rename state temp file"));
 	}
 
 	np_free(temp_file);
 }
-

+ 34 - 9
lib/utils_cmd.c

@@ -79,12 +79,14 @@ static pid_t *_cmd_pids = NULL;
  * If that fails and the macro isn't defined, we fall back to an educated
  * guess. There's no guarantee that our guess is adequate and the program
  * will die with SIGSEGV if it isn't and the upper boundary is breached. */
+#define DEFAULT_MAXFD  256   /* fallback value if no max open files value is set */
+#define MAXFD_LIMIT   8192   /* upper limit of open files */
 #ifdef _SC_OPEN_MAX
 static long maxfd = 0;
 #elif defined(OPEN_MAX)
 # define maxfd OPEN_MAX
 #else	/* sysconf macro unavailable, so guess (may be wildly inaccurate) */
-# define maxfd 256
+# define maxfd DEFAULT_MAXFD
 #endif
 
 
@@ -112,10 +114,18 @@ cmd_init (void)
 	if (!maxfd && (maxfd = sysconf (_SC_OPEN_MAX)) < 0) {
 		/* possibly log or emit a warning here, since there's no
 		 * guarantee that our guess at maxfd will be adequate */
-		maxfd = 256;
+		maxfd = DEFAULT_MAXFD;
 	}
 #endif
 
+	/* if maxfd is unnaturally high, we force it to a lower value
+	 * ( e.g. on SunOS, when ulimit is set to unlimited: 2147483647 this would cause
+	 * a segfault when following calloc is called ...  ) */
+
+	if ( maxfd > MAXFD_LIMIT ) {
+		maxfd = MAXFD_LIMIT;
+	}
+
 	if (!_cmd_pids)
 		_cmd_pids = calloc (maxfd, sizeof (pid_t));
 }
@@ -284,7 +294,7 @@ int
 cmd_run (const char *cmdstring, output * out, output * err, int flags)
 {
 	int fd, pfd_out[2], pfd_err[2];
-	int i = 0, argc;
+	int i = 0, argc, rst;
 	size_t cmdlen;
 	char **argv = NULL;
 	char *cmd = NULL;
@@ -308,11 +318,16 @@ cmd_run (const char *cmdstring, output * out, output * err, int flags)
 	cmd[cmdlen] = '\0';
 
 	/* This is not a shell, so we don't handle "???" */
-	if (strstr (cmdstring, "\"")) return -1;
+	if (strstr (cmdstring, "\"")) {
+		free(cmd);
+		return -1;
+	}
 
 	/* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
-	if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''"))
+	if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) {
+		free(cmd);
 		return -1;
+	}
 
 	/* each arg must be whitespace-separated, so args can be a maximum
 	 * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */
@@ -321,6 +336,7 @@ cmd_run (const char *cmdstring, output * out, output * err, int flags)
 
 	if (argv == NULL) {
 		printf ("%s\n", _("Could not malloc argv array in popen()"));
+		free(cmd);
 		return -1;
 	}
 
@@ -331,8 +347,11 @@ cmd_run (const char *cmdstring, output * out, output * err, int flags)
 
 		if (strstr (str, "'") == str) {	/* handle SIMPLE quoted strings */
 			str++;
-			if (!strstr (str, "'"))
-				return -1;							/* balanced? */
+			if (!strstr (str, "'")) { /* balanced? */
+				free(cmd);
+				free(argv);
+				return -1;
+			}
 			cmd = 1 + strstr (str, "'");
 			str[strcspn (str, "'")] = 0;
 		}
@@ -342,17 +361,23 @@ cmd_run (const char *cmdstring, output * out, output * err, int flags)
 				str[strcspn (str, " \t\r\n")] = 0;
 			}
 			else {
+				free(cmd);
 				cmd = NULL;
 			}
 		}
 
-		if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n"))
+		if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) {
+			free(cmd);
 			cmd = NULL;
+		}
 
 		argv[i++] = str;
 	}
 
-	return cmd_run_array (argv, out, err, flags);
+	rst = cmd_run_array (argv, out, err, flags);
+	free(cmd);
+	free(argv);
+	return rst;
 }
 
 int

+ 1 - 1
nagios-plugins.spec.in

@@ -155,7 +155,7 @@ fi
 %if %{islinux}
 getent passwd %{npusr} > /dev/null 2> /dev/null
 if [ $? -ne 0 ] ; then
-	useradd -r -d %{nshome} -c "%{npusr}" -g %{npgrp} %{npusr} || \
+	useradd -r -d %{nphome} -c "%{npusr}" -g %{npgrp} %{npusr} || \
 		%nnmmsg Unexpected error adding user "%{npusr}". Aborting install process.
 fi
 %endif

+ 13 - 4
plugins-root/check_dhcp.c

@@ -466,11 +466,20 @@ int send_dhcp_discover(int sock){
 	discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH;
 
 	/*
-	 * transaction ID is supposed to be random.  We won't use the address so
-	 * we don't care about high entropy here.  time(2) is good enough.
+	 * transaction ID is supposed to be random.
+	 * This allows for proper randomness if the system supports it, and fallback to
+	 * srand & random if not.
 	 */
-	srand(time(NULL));
-	packet_xid=random();
+	int randfd = open("/dev/urandom", O_RDONLY);
+	if (randfd > 2 && read(randfd, (char *)&packet_xid, sizeof(uint32_t)) >= 0) {
+		/* no-op as we have successfully filled packet_xid */
+	}
+	else {
+		 /* fallback bad rand */
+		srand(time(NULL));
+		packet_xid=random();
+	}
+	if (randfd > 2) close(randfd);
 	discover_packet.xid=htonl(packet_xid);
 
 	/**** WHAT THE HECK IS UP WITH THIS?!?  IF I DON'T MAKE THIS CALL, ONLY ONE SERVER RESPONSE IS PROCESSED!!!! ****/

+ 3 - 2
plugins-scripts/check_file_age.pl

@@ -33,7 +33,7 @@ sub print_help ();
 sub print_usage ();
 
 my ($opt_c, $opt_f, $opt_w, $opt_C, $opt_W, $opt_h, $opt_V, $opt_i);
-my ($result, $message, $age, $size, $st);
+my ($result, $message, $age, $size, $st, $perfdata);
 
 $PROGNAME="check_file_age";
 
@@ -87,6 +87,7 @@ unless (-e $opt_f) {
 $st = File::stat::stat($opt_f);
 $age = time - $st->mtime;
 $size = $st->size;
+$perfdata = "age=${age}s;${opt_w};${opt_c} size=${size}B;${opt_W};${opt_C};0";
 
 
 $result = 'OK';
@@ -98,7 +99,7 @@ elsif (($opt_w and $age > $opt_w) or ($opt_W and $size < $opt_W)) {
 	$result = 'WARNING';
 }
 
-print "FILE_AGE $result: $opt_f is $age seconds old and $size bytes\n";
+print "FILE_AGE $result: $opt_f is $age seconds old and $size bytes | $perfdata\n";
 exit $ERRORS{$result};
 
 sub print_usage () {

+ 38 - 19
plugins-scripts/check_ifstatus.pl

@@ -9,6 +9,7 @@
 #  Added -u option (4/2003)
 #  Added -M option (10/2003)
 #  Added SNMPv3 support (10/2003)
+#  Added -n option (07/2014)
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -90,8 +91,10 @@ my $ifXTable;
 my $opt_h ;
 my $opt_V ;
 my $opt_u;
+my $opt_n;
 my $opt_x ;
 my %excluded ;
+my %unused_names ;
 my @unused_ports ;
 my %session_opts;
 
@@ -166,27 +169,30 @@ alarm(0);
 foreach $key (keys %ifStatus) {
 
 	# skip unused interfaces
-	if (!defined($ifStatus{$key}{'notInUse'})) {
+	my $ifName = $ifStatus{$key}{$snmpIfDescr};
+
+	if (!defined($ifStatus{$key}{'notInUse'}) && !grep(/^${ifName}/, @unused_ports )) {
 		# check only if interface is administratively up
-    if ($ifStatus{$key}{$snmpIfAdminStatus} == 1 ) {
-    
-			# check only if interface type is not listed in %excluded
-			if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) {
-				if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ;}
-				if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) {
-								$ifdown++ ;
-								if (defined $ifXTable) {
-									$ifmessage .= sprintf("%s: down -> %s<BR>",
-                                $ifStatus{$key}{$snmpIfName},
-																$ifStatus{$key}{$snmpIfAlias});
-								}else{
-									$ifmessage .= sprintf("%s: down <BR>",
-																$ifStatus{$key}{$snmpIfDescr});
-								}
+		if ($ifStatus{$key}{$snmpIfAdminStatus} == 1 ) {
+			#check only if interface is not excluded
+			if (!defined $unused_names{$ifStatus{$key}{$snmpIfDescr}} ) {
+				# check only if interface type is not listed in %excluded
+				if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) {
+					if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ; }
+					if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) {
+									$ifdown++ ;
+									if (defined $ifXTable) {
+										$ifmessage .= sprintf("%s: down -> %s<BR>\n", $ifStatus{$key}{$snmpIfName}, $ifStatus{$key}{$snmpIfAlias});
+									}else{
+										$ifmessage .= sprintf("%s: down <BR>\n",$ifStatus{$key}{$snmpIfDescr});
+									}
+					}
+					if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;}
+				} else {
+					$ifexclude++;
 				}
-				if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;}
-			}else{
-				$ifexclude++;
+			} else {
+				$ifunused++;
 			}
 		
 		}
@@ -254,6 +260,8 @@ sub print_help() {
 	printf "                     the descriptive name.  Do not use if you don't know what this is. \n";
 	printf "   -x (--exclude)    A comma separated list of ifType values that should be excluded \n";
 	printf "                     from the report (default for an empty list is PPP(23).\n";
+	printf "   -n (--unused_ports_by_name) A comma separated list of ifDescr values that should be excluded \n";
+	printf "                     from the report (default is an empty exclusion list).\n";
 	printf "   -u (--unused_ports) A comma separated list of ifIndex values that should be excluded \n";
 	printf "                     from the report (default is an empty exclusion list).\n";
 	printf "                     See the IANAifType-MIB for a list of interface types.\n";
@@ -294,6 +302,7 @@ sub process_arguments() {
 		"I"		=> \$ifXTable, "ifmib" => \$ifXTable,
 		"x:s"		=>	\$opt_x,   "exclude:s" => \$opt_x,
 		"u=s" => \$opt_u,  "unused_ports=s" => \$opt_u,
+		"n=s" => \$opt_n, "unused_ports_by_name=s" => \$opt_n,
 		"M=i" => \$maxmsgsize, "maxmsgsize=i" => \$maxmsgsize,
 		"t=i" => \$timeout,    "timeout=i" => \$timeout,
 		);
@@ -401,6 +410,16 @@ sub process_arguments() {
 		}
 	}
 	
+	# Excluded interface descriptors
+	if (defined $opt_n) {
+		my @unused = split(/,/,$opt_n);
+		if ( @unused ) {
+			foreach $key (@unused) {
+				$unused_names{$key} = 1;
+			}
+		}
+	}
+
 	# Excluded interface ports (ifIndex) - management reasons
 	if ($opt_u) {
 		@unused_ports = split(/,/,$opt_u);

+ 21 - 4
plugins-scripts/check_log.sh

@@ -68,7 +68,9 @@ RM="/bin/rm"
 CHMOD="/bin/chmod"
 TOUCH="/bin/touch"
 
-PROGNAME=`/bin/basename $0`
+PATH="@TRUSTED_PATH@"
+export PATH
+PROGNAME=`basename $0`
 PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'`
 REVISION="@NP_VERSION@"
 
@@ -78,6 +80,9 @@ print_usage() {
     echo "Usage: $PROGNAME -F logfile -O oldlog -q query"
     echo "Usage: $PROGNAME --help"
     echo "Usage: $PROGNAME --version"
+    echo "     Aditional parameter:"
+    echo "        -w (--max_warning) If used, determines the maximum matching value to return as warning, when finding more matching lines than this parameter will return as critical. If not used, will consider as default 0 (any matching will consider as critical)"
+    echo "Usage: $PROGNAME -F logfile -O oldlog -q query -w <number>"
 }
 
 print_help() {
@@ -138,6 +143,14 @@ while test -n "$1"; do
             oldlog=$2
             shift
             ;;
+        --max_warning)
+            MAX_WARNING=$2
+            shift
+            ;;
+        -w)
+            MAX_WARNING=$2
+            shift
+            ;;
         --query)
             query=$2
             shift
@@ -208,11 +221,15 @@ $RM -f $tempdiff
 $CAT $logfile > $oldlog
 
 if [ "$count" = "0" ]; then # no matches, exit with no error
-    echo "Log check ok - 0 pattern matches found"
+    echo "Log check ok - 0 pattern matches found|match=$count;;;0"
     exitstatus=$STATE_OK
 else # Print total matche count and the last entry we found
-    echo "($count) $lastentry"
-    exitstatus=$STATE_CRITICAL
+    echo "($count) $lastentry|match=$count;;;0"
+    if [ $MAX_WARNING ] && [ $count -le $MAX_WARNING ] ; then
+        exitstatus=$STATE_WARNING
+    else
+        exitstatus=$STATE_CRITICAL
+    fi
 fi
 
 exit $exitstatus

+ 22 - 8
plugins-scripts/check_mailq.pl

@@ -28,12 +28,13 @@
 use POSIX;
 use strict;
 use Getopt::Long;
-use vars qw($opt_V $opt_h $opt_v $verbose $PROGNAME $opt_w $opt_c $opt_t
+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 lib  utils.pm;
 use utils qw(%ERRORS &print_revision &support &usage );
 
+my ($sudo)
 
 sub print_help ();
 sub print_usage ();
@@ -55,6 +56,17 @@ if ($status){
 	exit $ERRORS{"UNKNOWN"};
 }
 
+if ($opt_s) {
+	if (defined $utils::PATH_TO_SUDO && -x $utils::PATH_TO_SUDO) {
+		$sudo = $utils::PATH_TO_SUDO;
+	} else {
+		print "ERROR: Cannot execute sudo\n";
+		exit $ERRORS{'UNKNOWN'};
+	}
+} else {
+	$sudo = "";
+}
+
 $SIG{'ALRM'} = sub {
 	print ("ERROR: timed out waiting for $utils::PATH_TO_MAILQ \n");
 	exit $ERRORS{"WARNING"};
@@ -67,7 +79,7 @@ if ($mailq eq "sendmail") {
 
 	## open mailq 
 	if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) {
-		if (! open (MAILQ, "$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'};
 		}
@@ -296,7 +308,7 @@ elsif ( $mailq eq "postfix" ) {
 
      ## open mailq
         if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) {
-                if (! open (MAILQ, "$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'};
                 }
@@ -378,7 +390,7 @@ elsif ( $mailq eq "qmail" ) {
 
 	# open qmail-qstat 
 	if ( defined $utils::PATH_TO_QMAIL_QSTAT && -x $utils::PATH_TO_QMAIL_QSTAT ) {
-		if (! open (MAILQ, "$utils::PATH_TO_QMAIL_QSTAT | " ) ) {
+		if (! open (MAILQ, "$sudo $utils::PATH_TO_QMAIL_QSTAT | " ) ) {
 			print "ERROR: could not open $utils::PATH_TO_QMAIL_QSTAT \n";
 			exit $ERRORS{'UNKNOWN'};
 		}
@@ -460,7 +472,7 @@ elsif ( $mailq eq "qmail" ) {
 elsif ( $mailq eq "exim" ) {
 	## open mailq 
 	if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) {
-		if (! open (MAILQ, "$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'};
 		}
@@ -503,7 +515,7 @@ elsif ( $mailq eq "exim" ) {
 elsif ( $mailq eq "nullmailer" ) {
 	## open mailq
 	if ( defined $utils::PATH_TO_MAILQ && -x $utils::PATH_TO_MAILQ ) {
-		if (! open (MAILQ, "$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'};
 		}
@@ -554,7 +566,8 @@ sub process_arguments(){
 		 "M:s" => \$opt_M, "mailserver:s" => \$opt_M, # mailserver (default	sendmail)
 		 "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 
+		 "t=i" => \$opt_t, "timeout=i"  => \$opt_t,
+		 "s"   => \$opt_s, "sudo"       => \$opt_s
 		 );
 
 	if ($opt_V) {
@@ -612,7 +625,7 @@ sub process_arguments(){
 }
 
 sub print_usage () {
-	print "Usage: $PROGNAME -w <warn> -c <crit> [-W <warn>] [-C <crit>] [-M <MTA>] [-t <timeout>] [-v verbose]\n";
+	print "Usage: $PROGNAME -w <warn> -c <crit> [-W <warn>] [-C <crit>] [-M <MTA>] [-t <timeout>] [-s] [-v]\n";
 }
 
 sub print_help () {
@@ -629,6 +642,7 @@ sub print_help () {
 	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 = sendmail)\n";
+	print "-s (--sudo)	= Use sudo to call the mailq command\n";
 	print "-h (--help)\n";
 	print "-V (--version)\n";
 	print "-v (--verbose)   = debugging output\n";

+ 2 - 0
plugins-scripts/check_oracle.sh

@@ -6,6 +6,8 @@
 #  This Nagios plugin was created to check Oracle status
 #
 
+PATH="@TRUSTED_PATH@"
+export PATH
 PROGNAME=`basename $0`
 PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'`
 REVISION="@NP_VERSION@"

+ 2 - 2
plugins-scripts/check_sensors.sh

@@ -1,7 +1,7 @@
 #!/bin/sh
 
-PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
-
+PATH="@TRUSTED_PATH@"
+export PATH
 PROGNAME=`basename $0`
 PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'`
 REVISION="@NP_VERSION@"

+ 1 - 1
plugins-scripts/t/check_disk_smb.t

@@ -90,7 +90,7 @@ SKIP: {
 	SKIP: {
 		skip "no non responsive host defined", 1 if ( ! $host_nonresponsive );
 		$res = NPTest->testCmd( "./$plugin -H $host_nonresponsive -s np_foobar ");
-		cmp_ok( $res->return_code, '==', 3, "Exit UNKNOWN with non responsive host" );
+		cmp_ok( $res->return_code, '>=', 2, "Exit CRITICAL/UNKNOWN with non responsive host" );
 	}
 
 }

+ 7 - 1
plugins-scripts/t/check_file_age.t

@@ -5,13 +5,14 @@
 #
 
 use strict;
-use Test::More tests => 16;
+use Test::More tests => 17;
 use NPTest;
 
 my $successOutput = '/^FILE_AGE OK: /';
 my $warningOutput = '/^FILE_AGE WARNING: /';
 my $criticalOutput = '/^FILE_AGE CRITICAL: /';
 my $unknownOutput = '/^FILE_AGE UNKNOWN: /';
+my $performanceOutput = '/ \| age=[0-9]+s;[0-9]+;[0-9]+ size=[0-9]+B;[0-9]+;[0-9]+;0$/';
 
 my $result;
 my $temp_file = "/tmp/check_file_age.tmp";
@@ -57,6 +58,11 @@ $result = NPTest->testCmd(
 	);
 cmp_ok( $result->return_code, '==', 0, "Checking file size" );
 
+$result = NPTest->testCmd(
+	"./check_file_age -f $temp_file -c 1000 -W 100"
+	);
+like( $result->output, $performanceOutput, "Checking for performance output" );
+
 $result = NPTest->testCmd(
 	"./check_file_age -f /non/existent --ignore-missing"
 	);

+ 1 - 0
plugins-scripts/utils.pm.in

@@ -17,6 +17,7 @@ sub support();
 sub is_hostname;
 
 ## updated by autoconf
+$PATH_TO_SUDO    = "@PATH_TO_SUDO@";
 $PATH_TO_RPCINFO = "@PATH_TO_RPCINFO@" ;
 $PATH_TO_LMSTAT  = "@PATH_TO_LMSTAT@" ;
 $PATH_TO_SMBCLIENT = "@PATH_TO_SMBCLIENT@" ;

+ 1 - 1
plugins/Makefile.am

@@ -71,7 +71,7 @@ check_apt_LDADD = $(BASEOBJS)
 check_cluster_LDADD = $(BASEOBJS)
 check_dbi_LDADD = $(NETLIBS) $(DBILIBS)
 check_dig_LDADD = $(NETLIBS) $(MATHLIBS)
-check_disk_LDADD = $(BASEOBJS)
+check_disk_LDADD = $(BASEOBJS) $(THREADLIBS)
 check_dns_LDADD = $(NETLIBS)
 check_dummy_LDADD = $(BASEOBJS)
 check_fping_LDADD = $(NETLIBS)

+ 1 - 1
plugins/check_apt.c

@@ -224,7 +224,7 @@ int run_upgrade(int *pkgcount, int *secpkgcount){
 	char *cmdline=NULL, rerrbuf[64];
 
 	/* initialize ereg as it is possible it is printed while uninitialized */
-	memset(&ereg, "\0", sizeof(ereg.buffer));
+	memset(&ereg, '\0', sizeof(ereg.buffer));
 
 	if(upgrade==NO_UPGRADE) return STATE_OK;
 

+ 2 - 1
plugins/check_by_ssh.c

@@ -169,7 +169,8 @@ process_arguments (int argc, char **argv)
 		{"verbose", no_argument, 0, 'v'},
 		{"fork", no_argument, 0, 'f'},
 		{"timeout", required_argument, 0, 't'},
-		{"host", required_argument, 0, 'H'},
+		{"host", required_argument, 0, 'H'},    /* backward compatibility */
+		{"hostname", required_argument, 0, 'H'},
 		{"port", required_argument,0,'p'},
 		{"output", required_argument, 0, 'O'},
 		{"name", required_argument, 0, 'n'},

+ 3 - 3
plugins/check_dbi.c

@@ -211,7 +211,7 @@ main (int argc, char **argv)
 	}
 
 	if (dbi_conn_connect (conn) < 0) {
-		np_dbi_print_error (conn, "UNKOWN - failed to connect to database");
+		np_dbi_print_error (conn, "UNKNOWN - failed to connect to database");
 		return STATE_UNKNOWN;
 	}
 
@@ -237,7 +237,7 @@ main (int argc, char **argv)
 			printf ("Selecting database '%s'\n", np_dbi_database);
 
 		if (dbi_conn_select_db (conn, np_dbi_database)) {
-			np_dbi_print_error (conn, "UNKOWN - failed to select database '%s'",
+			np_dbi_print_error (conn, "UNKNOWN - failed to select database '%s'",
 					np_dbi_database);
 			return STATE_UNKNOWN;
 		}
@@ -450,7 +450,7 @@ process_arguments (int argc, char **argv)
 				new = realloc (np_dbi_options,
 						(np_dbi_options_num + 1) * sizeof (*new));
 				if (! new) {
-					printf ("UNKOWN - failed to reallocate memory\n");
+					printf ("UNKNOWN - failed to reallocate memory\n");
 					exit (STATE_UNKNOWN);
 				}
 

+ 6 - 3
plugins/check_dig.c

@@ -94,8 +94,8 @@ main (int argc, char **argv)
   timeout_interval_dig = ceil((double) timeout_interval / (double) number_tries);
 
   /* get the command to run */
-  xasprintf (&command_line, "%s @%s -p %d %s -t %s %s %s +tries=%d +time=%d",
-            PATH_TO_DIG, dns_server, server_port, query_address, record_type, dig_args, query_transport, number_tries, timeout_interval_dig);
+  xasprintf (&command_line, "%s %s %s -p %d @%s %s %s +tries=%d +time=%d",
+  	PATH_TO_DIG, dig_args, query_transport, server_port, dns_server, query_address, record_type, number_tries, timeout_interval_dig);
 
   alarm (timeout_interval);
   gettimeofday (&tv, NULL);
@@ -300,7 +300,10 @@ process_arguments (int argc, char **argv)
       dns_server = argv[c];
     }
     else {
-      dns_server = strdup ("127.0.0.1");
+      if (strcmp(query_transport,"-6") == 0)
+        dns_server = strdup("::1");
+      else
+        dns_server = strdup ("127.0.0.1");
     }
   }
 

+ 56 - 4
plugins/check_disk.c

@@ -51,6 +51,9 @@ const char *email = "devel@nagios-plugins.org";
 # include <limits.h>
 #endif
 #include "regex.h"
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
 
 #ifdef __CYGWIN__
 # include <windows.h>
@@ -130,6 +133,7 @@ void print_help (void);
 void print_usage (void);
 double calculate_percent(uintmax_t, uintmax_t);
 void stat_path (struct parameter_list *p);
+void *do_stat_path (void *p);
 void get_stats (struct parameter_list *p, struct fs_usage *fsp);
 void get_path_stats (struct parameter_list *p, struct fs_usage *fsp);
 
@@ -172,6 +176,7 @@ main (int argc, char **argv)
   char *details;
   char *perf;
   char *preamble;
+  char *flag_header;
   double inode_space_pct;
   double warning_high_tide;
   double critical_high_tide;
@@ -354,6 +359,12 @@ 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 (%.0f%%",
                 output,
                 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
@@ -363,18 +374,20 @@ main (int argc, char **argv)
       /* Whether or not to put all disks on new line */
       if (newlines) {
         if (path->dused_inodes_percent < 0) {
-          xasprintf(&output, "%s inode=-);\n", output);
+          xasprintf(&output, "%s inode=-)%s;\n", output, (disk_result ? "]" : ""));
         } else {
-          xasprintf(&output, "%s inode=%.0f%%);\n", output, path->dfree_inodes_percent );
+          xasprintf(&output, "%s inode=%.0f%%)%s;\n", output, path->dfree_inodes_percent, ((disk_result && verbose) ? "]" : ""));
         }
       } else {
         if (path->dused_inodes_percent < 0) {
-          xasprintf(&output, "%s inode=-);", output);
+          xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
         } else {
-          xasprintf(&output, "%s inode=%.0f%%);", output, path->dfree_inodes_percent );
+          xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose) ? "]" : ""));
         }
       }
 
+      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%%"),
@@ -975,6 +988,44 @@ print_usage (void)
 void
 stat_path (struct parameter_list *p)
 {
+#ifdef HAVE_PTHREAD_H
+  pthread_t stat_thread;
+  int statdone = 0;
+  int timer = timeout_interval;
+  struct timespec req, rem;
+
+  req.tv_sec = 0;
+  pthread_create(&stat_thread, NULL, do_stat_path, p);
+  while (timer-- > 0) {
+    req.tv_nsec = 10000000;
+    nanosleep(&req, &rem);
+    if (pthread_kill(stat_thread, 0)) {
+      statdone = 1;
+      break;
+    } else {
+      req.tv_nsec = 990000000;
+      nanosleep(&req, &rem);
+    }
+  }
+  if (statdone == 1) {
+    pthread_join(stat_thread, NULL);
+  } else {
+    pthread_detach(stat_thread);
+    if (verbose >= 3)
+      printf("stat did not return within %ds on %s\n", timeout_interval, p->name);
+    printf("DISK %s - ", _("CRITICAL"));
+    die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("hangs"), _("Timeout"));
+  }
+#else
+  do_stat_path(p);
+#endif
+}
+
+void *
+do_stat_path (void *in)
+{
+  struct parameter_list *p = in;
+
   /* Stat entry to check that dir exists and is accessible */
   if (verbose >= 3)
     printf("calling stat on %s\n", p->name);
@@ -984,6 +1035,7 @@ stat_path (struct parameter_list *p)
     printf("DISK %s - ", _("CRITICAL"));
     die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
   }
+  return NULL;
 }
 
 

+ 109 - 132
plugins/check_dns.c

@@ -28,6 +28,12 @@
 * 
 * 
 *****************************************************************************/
+#define IF_RECORD(label, querytype, verb_str) if (strstr (chld_out.line[i], label) && (strncmp(query_type, querytype, query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) { \
+      if (verbose) printf(verb_str); \
+      temp_buffer = rindex (chld_out.line[i], ' '); \
+      addresses[n_addresses++] = check_new_address(temp_buffer); \
+      strncpy(query_found, querytype, sizeof(query_found)); \
+      memset(query_found, '\0', sizeof(query_found));
 
 const char *progname = "check_dns";
 const char *copyright = "2000-2014";
@@ -48,6 +54,7 @@ void print_usage (void);
 #define ADDRESS_LENGTH 384 
 char query_address[ADDRESS_LENGTH] = "";
 char dns_server[ADDRESS_LENGTH] = "";
+char tmp_dns_server[ADDRESS_LENGTH] = "";
 char ptr_server[ADDRESS_LENGTH] = "";
 char query_type[16] = "";
 int query_set = FALSE;
@@ -77,11 +84,9 @@ check_new_address(char *temp_buffer)
         /* NOOP */;
 
       strip(temp_buffer);
-      if (temp_buffer==NULL || strlen(temp_buffer)==0) {
-        die (STATE_CRITICAL,
-             _("DNS CRITICAL - '%s' returned empty host name string\n"),
-             NSLOOKUP_COMMAND);
-      }
+      if (temp_buffer==NULL || strlen(temp_buffer)==0)
+        die (STATE_CRITICAL, "%s%s%s\n", _("DNS CRITICAL - '"), NSLOOKUP_COMMAND, _("' returned empty host name string"));
+
       return temp_buffer;
 }
 
@@ -94,8 +99,8 @@ main (int argc, char **argv)
   char **addresses = NULL;
   int n_addresses = 0;
   char *msg = NULL;
-  char query_found[16] = "";
-  int query_size = 16;
+  char query_found[24] = "";
+  int query_size = 24;
   char *temp_buffer = NULL;
   int non_authoritative = TRUE;
   int result = STATE_UNKNOWN;
@@ -112,16 +117,14 @@ main (int argc, char **argv)
   textdomain (PACKAGE);
 
   /* Set signal handling and alarm */
-  if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
+  if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR)
     usage_va(_("Cannot catch SIGALRM"));
-  }
 
   /* Parse extra opts if any */
   argv=np_extra_opts (&argc, argv, progname);
 
-  if (process_arguments (argc, argv) == ERROR) {
+  if (process_arguments (argc, argv) == ERROR)
     usage_va(_("Could not parse arguments"));
-  }
 
   /* get the command to run */
   xasprintf (&command_line, "%s %s %s %s", NSLOOKUP_COMMAND, query_type, query_address, dns_server);
@@ -148,6 +151,39 @@ main (int argc, char **argv)
     if (verbose)
       puts(chld_out.line[i]);
 
+    /* bug ID: 2946553 - Older versions of bind will use all available dns
+    + servers, we have to match the one specified */
+    if (strlen(dns_server) > 0 && strstr(chld_out.line[i], "Server:")) {
+        temp_buffer = strchr(chld_out.line[i], ':');
+        temp_buffer++;
+
+	if (temp_buffer > (char *)1) {
+          /* Strip leading tabs */
+          for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++)
+            /* NOOP */;
+
+        strip(temp_buffer);
+        if (temp_buffer==NULL || strlen(temp_buffer)==0)
+          die (STATE_CRITICAL, "%s%s%s\n", _("DNS CRITICAL - '"), NSLOOKUP_COMMAND, _("' returned empty server string"));
+
+        if (strcmp(temp_buffer, dns_server) != 0)
+          die (STATE_CRITICAL, "%s %s\n", _("DNS CRITICAL - No response from DNS server:"), dns_server);
+      }
+    }
+    /* Provide the server name\ip to error_scan when not using -s */
+    else if (strlen(tmp_dns_server) == 0) {
+	temp_buffer = strchr(chld_out.line[i], ':');
+	temp_buffer++;
+	if (temp_buffer > (char *)1) {
+	  /* Strip leading tabs */
+	  for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++)
+	      /* NOOP */;
+
+	  strip(temp_buffer);
+	  strncpy(tmp_dns_server, temp_buffer, ADDRESS_LENGTH);
+	}
+    }
+
     if (strstr (chld_out.line[i], "Authoritative answers can be found from:")) {
       non_authoritative = FALSE;
       break;
@@ -156,24 +192,17 @@ main (int argc, char **argv)
     if (strstr (chld_out.line[i], "Name:"))
       parse_address = TRUE;
     /* begin handling types of records */
-    if (strstr (chld_out.line[i], "AAAA address") && (strncmp(query_type, "-querytype=AAAA", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found AAAA record\n");
-      temp_buffer = rindex (chld_out.line[i], ' ');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=AAAA", sizeof(query_found));
-    }
-    else if (strstr (chld_out.line[i], "exchanger =") && (strncmp(query_type, "-querytype=MX", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found MX record\n");
-      temp_buffer = index (chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=MX", sizeof(query_found));
-    }
-    else if (strstr (chld_out.line[i], "service =") && (strncmp(query_type, "-querytype=SRV", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found SRV record\n");
-      temp_buffer = index (chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=SRV", sizeof(query_found));
-    }
+    IF_RECORD("AAAA address", "-querytype=AAAA", "Found AAAA record\n") }
+    else IF_RECORD("exchanger =", "-querytype=MX", "Found MX record\n") }
+    else IF_RECORD("service =", "-querytype=SRV", "Found SRV record\n") }
+    else IF_RECORD("nameserver =", "-querytype=NS", "Found NS record\n") }
+    else IF_RECORD("dname =", "-querytype=DNAME", "Found DNAME record\n") }
+    else IF_RECORD("protocol =", "-querytype=WKS", "Found WKS record\n") }
+    /* TODO: needs to be changed to handle txt output and max size of txt recrods */
+    else IF_RECORD("text =", "-querytype=TXT", "Found TXT record\n") }
+    /* only matching for origin records, if requested other fields could be included at a later date */
+    else IF_RECORD("origin =", "-querytype=SOA", "Found SOA record\n") }
+    /* cnames cannot use macro as we must check for accepting them separately */
     else if (accept_cname && strstr (chld_out.line[i], "canonical name =") && (strncmp(query_type, "-querytype=CNAME", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
       if (verbose) printf("Found CNAME record\n");
       temp_buffer = index (chld_out.line[i], '=');
@@ -187,60 +216,26 @@ main (int argc, char **argv)
       addresses[n_addresses++] = check_new_address(temp_buffer);
       strncpy(query_found, "-querytype=A", sizeof(query_found));
     }
-    else if (strstr (chld_out.line[i], "nameserver =") && (strncmp(query_type, "-querytype=NS", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found NS record\n");
-      temp_buffer = index (chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=NS", sizeof(query_found));
-    }
-    else if (strstr (chld_out.line[i], "dname =") && (strncmp(query_type, "-querytype=DNAME", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found DNAME record\n");
-      temp_buffer = index (chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=DNAME", sizeof(query_found));
-    }
     /* must be after other records with "name" as an identifier, as ptr does not spefify */
-    else if (strstr (chld_out.line[i], "name =") && (strncmp(query_type, "-querytype=PTR", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found PTR record\n");
-      temp_buffer = index (chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=PTR", sizeof(query_found));
-    }
-    else if (strstr (chld_out.line[i], "protocol =") && (strncmp(query_type, "-querytype=WKS", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found WKS record\n");
-      temp_buffer = index (chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=WKS", sizeof(query_found));
-    }
-    /* TODO: needs to be changed to handle txt output and max size of txt recrods */
-    else if (strstr (chld_out.line[i], "text =") && (strncmp(query_type, "-querytype=TXT", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found TXT record\n");
-      temp_buffer = index (chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=TXT", sizeof(query_found));
-    }
-    /* only matching for origin records, if requested other fields could be included at a later date */
-    else if (strstr (chld_out.line[i], "origin =") && (strncmp(query_type, "-querytype=SOA", query_size) == 0 || strncmp(query_type, "-querytype=ANY", query_size) == 0)) {
-      if (verbose) printf("Found SOA record\n");
-      temp_buffer = index(chld_out.line[i], '=');
-      addresses[n_addresses++] = check_new_address(temp_buffer);
-      strncpy(query_found, "-querytype=SOA", sizeof(query_found));
-    }
+    else IF_RECORD("name =", "-querytype=PTR", "Found PTR record\n") }
     /* needed for non-query ptr\reverse lookup checks */
     else if (strstr(chld_out.line[i], ".in-addr.arpa") && !query_set) {
       if ((temp_buffer = strstr(chld_out.line[i], "name = ")))
-        addresses[n_addresses++] = strdup(temp_buffer + 7);
+        addresses[n_addresses++] = strdup(temp_buffer);
       else {
         msg = (char *)_("Warning plugin error");
         result = STATE_WARNING;
       }
     }
 
-    if (strstr (chld_out.line[i], _("Non-authoritative answer:"))) {
+    if (strstr (chld_out.line[i], _("Non-authoritative answer:")))
       non_authoritative = TRUE;
-    }
 
-    result = error_scan (chld_out.line[i]);
+    int tmp = error_scan(chld_out.line[i]);
+    result = (result == STATE_UNKNOWN)
+      ? tmp
+      : (result < tmp)
+        ? tmp : result;
     if (result != STATE_OK) {
       msg = strchr (chld_out.line[i], ':');
       if(msg) msg++;
@@ -264,9 +259,9 @@ main (int argc, char **argv)
     int i,slen;
     char *adrp;
     qsort(addresses, n_addresses, sizeof(*addresses), qstrcmp);
-    for(i=0, slen=1; i < n_addresses; i++) {
+    for(i=0, slen=1; i < n_addresses; i++)
       slen += strlen(addresses[i])+1;
-    }
+
     adrp = address = malloc(slen);
     for(i=0; i < n_addresses; i++) {
       if (i) *adrp++ = ',';
@@ -275,9 +270,7 @@ main (int argc, char **argv)
     }
     *adrp = 0;
   } else
-    die (STATE_CRITICAL,
-         _("DNS CRITICAL - '%s' msg parsing exited with no address\n"),
-         NSLOOKUP_COMMAND);
+    die (STATE_CRITICAL, "%s%s%s\n", _("DNS CRITICAL - '"), NSLOOKUP_COMMAND, _("' msg parsing exited with no address"));
 
   /* compare to expected address */
   if (result == STATE_OK && expected_address_cnt > 0) {
@@ -291,7 +284,7 @@ main (int argc, char **argv)
     if (result == STATE_CRITICAL) {
       /* Strip off last semicolon... */
       temp_buffer[strlen(temp_buffer)-2] = '\0';
-      xasprintf(&msg, _("expected '%s' but got '%s'"), temp_buffer, address);
+      xasprintf(&msg, "%s%s%s%s%s", _("expected '"), temp_buffer, _("' but got '"), address, "'");
     }
   }
 
@@ -300,18 +293,18 @@ main (int argc, char **argv)
     result = STATE_CRITICAL;
 
     if (strncmp(dns_server, "", 1))
-      xasprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address);
+      xasprintf(&msg, "%s %s %s %s", _("server"), dns_server, _("is not authoritative for"), query_address);
     else
-      xasprintf(&msg, _("there is no authoritative server for %s"), query_address);
+      xasprintf(&msg, "%s %s", _("there is no authoritative server for"), query_address);
   }
 
   /* compare query type to query found, if query type is ANY we can skip as any record is accepted*/
   if (result == STATE_OK && strncmp(query_type, "", 1) && (strncmp(query_type, "-querytype=ANY", 15) != 0)) {
     if (strncmp(query_type, query_found, 16) != 0) {
       if (verbose)
-        printf( "Failed query for %s only found %s, or nothing\n", query_type, query_found);
+        printf( "%s %s %s %s %s\n", _("Failed query for"), query_type, _("only found"), query_found, _(", or nothing"));
       result = STATE_CRITICAL;
-      xasprintf(&msg, _("query type of %s was not found for %s"), query_type, query_address);
+      xasprintf(&msg, "%s %s %s %s", _("query type of"), query_type, _("was not found for"), query_address);
     }
   }
 
@@ -326,14 +319,14 @@ main (int argc, char **argv)
 
     result = get_status(elapsed_time, time_thresholds);
     if (result == STATE_OK) {
-      printf ("DNS %s: ", _("OK"));
+      printf ("%s %s: ", _("DNS"), _("OK"));
     } else if (result == STATE_WARNING) {
-      printf ("DNS %s: ", _("WARNING"));
+      printf ("%s %s: ", _("DNS"), _("WARNING"));
     } else if (result == STATE_CRITICAL) {
-      printf ("DNS %s: ", _("CRITICAL"));
+      printf ("%s %s: ", _("DNS"), _("CRITICAL"));
     }
     printf (ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time);
-    printf (_(". %s returns %s"), query_address, address);
+    printf (". %s %s %s", query_address, _("returns"), address);
     if ((time_thresholds->warning != NULL) && (time_thresholds->critical != NULL)) {
       printf ("|%s\n", fperfdata ("time", elapsed_time, "s",
                                   TRUE, time_thresholds->warning->end,
@@ -353,14 +346,11 @@ main (int argc, char **argv)
       printf ("|%s\n", fperfdata ("time", elapsed_time, "s", FALSE, 0, FALSE, 0, TRUE, 0, FALSE, 0));
   }
   else if (result == STATE_WARNING)
-    printf (_("DNS WARNING - %s\n"),
-            !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
+    printf ("%s %s\n", _("DNS WARNING -"), !strcmp (msg, "") ? _("Probably a non-existent host/domain") : msg);
   else if (result == STATE_CRITICAL)
-    printf (_("DNS CRITICAL - %s\n"),
-            !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
+    printf ("%s %s\n", _("DNS CRITICAL -"), !strcmp (msg, "") ? _("Probably a non-existent host/domain") : msg);
   else
-    printf (_("DNS UNKNOWN - %s\n"),
-            !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
+    printf ("%s %s\n", _("DNS UNKNOWN -"), !strcmp (msg, "") ? _("Probably a non-existent host/domain") : msg);
 
   return result;
 }
@@ -379,11 +369,11 @@ error_scan (char *input_buffer)
 
   /* DNS server is not running... */
   else if (strstr (input_buffer, "No response from server"))
-    die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
+    die (STATE_CRITICAL, "%s %s\n", _("No response from DNS"), (strlen(dns_server)==0)?tmp_dns_server:dns_server);
 
   /* Host name is valid, but server doesn't have records... */
   else if (strstr (input_buffer, "No records") || strstr (input_buffer, "No answer"))
-    die (STATE_CRITICAL, _("DNS %s has no records\n"), dns_server);
+    die (STATE_CRITICAL, "%s %s %s\n", _("DNS"), (strlen(dns_server)==0)?tmp_dns_server:dns_server, _("has no records"));
 
   /* Connection was refused */
   else if (strstr (input_buffer, "Connection refused") ||
@@ -391,29 +381,29 @@ error_scan (char *input_buffer)
            strstr (input_buffer, "Refused") ||
            (strstr (input_buffer, "** server can't find") &&
             strstr (input_buffer, ": REFUSED")))
-    die (STATE_CRITICAL, _("Connection to DNS %s was refused\n"), dns_server);
+    die (STATE_CRITICAL, "%s %s %s\n", _("Connection to DNS"), (strlen(dns_server)==0)?tmp_dns_server:dns_server, _("was refused"));
 
   /* Query refused (usually by an ACL in the namserver) */
   else if (strstr (input_buffer, "Query refused"))
-    die (STATE_CRITICAL, _("Query was refused by DNS server at %s\n"), dns_server);
+    die (STATE_CRITICAL, "%s %s\n", _("Query was refused by DNS server at"), (strlen(dns_server)==0)?tmp_dns_server:dns_server);
 
   /* No information (e.g. nameserver IP has two PTR records) */
   else if (strstr (input_buffer, "No information"))
-    die (STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
+    die (STATE_CRITICAL, "%s %s\n", _("No information returned by DNS server at"), (strlen(dns_server)==0)?tmp_dns_server:dns_server);
 
   /* Host or domain name does not exist */
   else if (strstr (input_buffer, "Non-existent") ||
            strstr (input_buffer, "** server can't find") ||
      strstr (input_buffer,"NXDOMAIN"))
-    die (STATE_CRITICAL, _("Domain %s was not found by the server\n"), query_address);
+    die (STATE_CRITICAL, "%s %s %s\n", _("Domain"), query_address, _("was not found by the server"));
 
   /* Network is unreachable */
   else if (strstr (input_buffer, "Network is unreachable"))
-    die (STATE_CRITICAL, _("Network is unreachable\n"));
+    die (STATE_CRITICAL, "%s\n", _("Network is unreachable"));
 
   /* Internal server failure */
   else if (strstr (input_buffer, "Server failure"))
-    die (STATE_CRITICAL, _("DNS failure for %s\n"), dns_server);
+    die (STATE_CRITICAL, "%s %s\n", _("DNS failure for"), (strlen(dns_server)==0)?tmp_dns_server:dns_server);
 
   /* Request error or the DNS lookup timed out */
   else if (strstr (input_buffer, "Format error") ||
@@ -478,7 +468,7 @@ process_arguments (int argc, char **argv)
       break;
     case 'H': /* hostname */
       if (strlen (optarg) >= ADDRESS_LENGTH)
-        die (STATE_UNKNOWN, _("Input buffer overflow\n"));
+        die (STATE_UNKNOWN, "%s\n", _("Input buffer overflow"));
       strcpy (query_address, optarg);
       break;
     case 's': /* server name */
@@ -486,37 +476,39 @@ process_arguments (int argc, char **argv)
        * Better to confirm nslookup response matches */
       host_or_die(optarg);
       if (strlen (optarg) >= ADDRESS_LENGTH)
-        die (STATE_UNKNOWN, _("Input buffer overflow\n"));
+        die (STATE_UNKNOWN, "%s\n", _("Input buffer overflow"));
       strcpy (dns_server, optarg);
       break;
     case 'r': /* reverse server name */
       /* TODO: Is this host_or_die necessary? */
       host_or_die(optarg);
       if (strlen (optarg) >= ADDRESS_LENGTH)
-        die (STATE_UNKNOWN, _("Input buffer overflow\n"));
+        die (STATE_UNKNOWN, "%s\n", _("Input buffer overflow"));
       strcpy (ptr_server, optarg);
       break;
     case 'a': /* expected address */
       if (strlen (optarg) >= ADDRESS_LENGTH)
-        die (STATE_UNKNOWN, _("Input buffer overflow\n"));
+        die (STATE_UNKNOWN, "%s\n", _("Input buffer overflow"));
       expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
       expected_address[expected_address_cnt] = strdup(optarg);
       expected_address_cnt++;
       break;
     case 'q': /* querytype -- A or AAAA or ANY or SRV or TXT, etc. */
       if (strlen (optarg) < 1 || strlen (optarg) > 5)
-	die (STATE_UNKNOWN, _("Missing valid querytype parameter.  Try using 'A' or 'AAAA' or 'SRV'\n"));
+	die (STATE_UNKNOWN, "%s\n", _("Missing valid querytype parameter.  Try using 'A' or 'AAAA' or 'SRV'"));
       strntoupper(optarg, sizeof(optarg));
       strcpy(query_type, "-querytype=");
       strcat(query_type, optarg);
       query_set = TRUE;
+      /* logic is set such that we must accept cnames if they are querying for them */
+      if (strcmp(query_type, "-querytype=CNAME") != 0)
+        break;
+    case 'n': /* accept cname responses as a result */
+      accept_cname = TRUE;
       break;
     case 'A': /* expect authority */
       expect_authority = TRUE;
       break;
-    case 'n': /* accept cname responses as a result */
-      accept_cname = TRUE;
-      break;
     case 'w':
       warning = optarg;
       break;
@@ -528,21 +520,6 @@ process_arguments (int argc, char **argv)
     }
   }
 
-  c = optind;
-  if (strlen(query_address)==0 && c<argc) {
-    if (strlen(argv[c])>=ADDRESS_LENGTH)
-      die (STATE_UNKNOWN, _("Input buffer overflow\n"));
-    strcpy (query_address, argv[c++]);
-  }
-
-  if (strlen(dns_server)==0 && c<argc) {
-    /* TODO: See -s option */
-    host_or_die(argv[c]);
-    if (strlen(argv[c]) >= ADDRESS_LENGTH)
-      die (STATE_UNKNOWN, _("Input buffer overflow\n"));
-    strcpy (dns_server, argv[c++]);
-  }
-
   set_thresholds(&time_thresholds, warning, critical);
 
   return validate_arguments ();
@@ -564,7 +541,7 @@ print_help (void)
 {
   print_revision (progname, NP_VERSION);
 
-  printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
+  printf ("%s\n", "Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>");
   printf (COPYRIGHT, copyright, email);
 
   printf ("%s\n", _("This plugin uses the nslookup program to obtain the IP address for the given host/domain query."));
@@ -578,27 +555,27 @@ print_help (void)
   printf (UT_HELP_VRSN);
   printf (UT_EXTRA_OPTS);
 
-  printf (" -H, --hostname=HOST\n");
+  printf ("%s\n", " -H, --hostname=HOST");
   printf ("    %s\n", _("The name or address you want to query"));
-  printf (" -s, --server=HOST\n");
+  printf ("%s\n", " -s, --server=HOST");
   printf ("    %s\n", _("Optional DNS server you want to use for the lookup"));
-  printf (" -q, --querytype=TYPE\n");
+  printf ("%s\n", " -q, --querytype=TYPE");
   printf ("    %s\n", _("Optional DNS record query type where TYPE =(A, AAAA, SRV, TXT, MX, ANY)"));
   printf ("    %s\n", _("The default query type is 'A' (IPv4 host entry)"));
-  printf (" -a, --expected-address=IP-ADDRESS|HOST\n");
+  printf ("%s\n", " -a, --expected-address=IP-ADDRESS|HOST");
   printf ("    %s\n", _("Optional IP-ADDRESS you expect the DNS server to return. HOST must end with"));
   printf ("    %s\n", _("a dot (.). This option can be repeated multiple times (Returns OK if any"));
   printf ("    %s\n", _("value match). If multiple addresses are returned at once, you have to match"));
   printf ("    %s\n", _("the whole string of addresses separated with commas (sorted alphabetically)."));
   printf ("    %s\n", _("If you would like to test for the presence of a cname, combine with -n param."));
-  printf (" -A, --expect-authority\n");
+  printf ("%s\n", " -A, --expect-authority");
   printf ("    %s\n", _("Optionally expect the DNS server to be authoritative for the lookup"));
-  printf (" -n, --accept-cname\n");
+  printf ("%s\n", " -n, --accept-cname");
   printf ("    %s\n", _("Optionally accept cname responses as a valid result to a query"));
   printf ("    %s\n", _("The default is to ignore cname responses as part of the result"));
-  printf (" -w, --warning=seconds\n");
+  printf ("%s\n", " -w, --warning=seconds");
   printf ("    %s\n", _("Return warning if elapsed time exceeds value. Default off"));
-  printf (" -c, --critical=seconds\n");
+  printf ("%s\n", " -c, --critical=seconds");
   printf ("    %s\n", _("Return critical if elapsed time exceeds value. Default off"));
 
   printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
@@ -611,5 +588,5 @@ void
 print_usage (void)
 {
   printf ("%s\n", _("Usage:"));
-  printf ("%s -H host [-s server] [-q type ] [-a expected-address] [-A] [-n] [-t timeout] [-w warn] [-c crit]\n", progname);
+  printf ("%s %s\n", progname, "-H host [-s server] [-q type ] [-a expected-address] [-A] [-n] [-t timeout] [-w warn] [-c crit]");
 }

+ 148 - 14
plugins/check_http.c

@@ -673,6 +673,115 @@ expected_statuscode (const char *reply, const char *statuscodes)
   return result;
 }
 
+char *
+decode_chunked_page (const char *raw, char *dst)
+{
+  unsigned long int chunksize;
+  char *raw_pos = (char *)raw;
+  char *dst_pos = (char *)dst;
+  const char *raw_end = raw + strlen(raw);
+
+  while (chunksize = strtoul(raw_pos, NULL, 16)) {
+    if (chunksize <= 0) {
+      die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse chunked body, invalid chunk size\n"));
+    }
+
+    // soak up the optional chunk params (which we will ignore)
+    while (*raw_pos && *raw_pos != '\r' && *raw_pos != '\n') raw_pos++;
+
+    // soak up the leading CRLF
+    if (*raw_pos && *raw_pos == '\r' && *(++raw_pos) && *raw_pos == '\n') {
+      raw_pos++;
+    }
+    else {
+      die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse chunked body, invalid format\n"));
+    }
+
+    // move chunk from raw into dst, only if we can fit within the buffer
+    if (*raw_pos && *dst_pos && (raw_pos + chunksize) < raw_end ) {
+      strncpy(dst_pos, raw_pos, chunksize);
+    }
+    else {
+      die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse chunked body, too large for destination\n"));
+    }
+
+    raw_pos += chunksize;
+    dst_pos += chunksize;
+
+    // soak up the ending CRLF
+    if (*raw_pos && *raw_pos == '\r' && *(++raw_pos) && *raw_pos == '\n') {
+      raw_pos++;
+    }
+    else {
+      die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse chunked body, invalid format\n"));
+    }
+  }
+
+  if (*dst_pos) *dst_pos = '\0';
+  else {
+    die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
+  }
+
+  return dst;
+}
+
+static char *
+header_value (const char *headers, const char *header)
+{
+  char *s;
+  char *value;
+  const char *value_end;
+  int value_size;
+
+  if (!(s = strcasestr(headers, header))) {
+    return NULL;
+  }
+
+  s += strlen(header);
+
+  while (*s && (isspace(*s) || *s == ':')) s++;
+  while (*s && isspace(*s)) s++;
+
+  value_end = strchr(s, '\r');
+  if (!value_end) {
+      die (STATE_UNKNOWN, _("HTTP_UNKNOWN - Failed to parse response headers\n"));
+  }
+
+  value_size = value_end - s;
+
+  value = malloc(value_size + 1);
+  if (!value) {
+    die (STATE_UNKNOWN, _("HTTP_UNKNOWN - Memory allocation error\n"));
+  }
+
+  if (!strncpy(value, s, value_size)) {
+    die(STATE_UNKNOWN, _("HTTP_UNKNOWN - Memory copy failure\n"));
+  }
+  value[value_size] = '\0';
+
+  return value;
+}
+
+static int
+chunked_transfer_encoding (const char *headers)
+{
+  int result;
+  char *encoding = header_value(headers, "Transfer-Encoding");
+  if (!encoding) {
+    return 0;
+  }
+
+  if (! strncmp(encoding, "chunked", sizeof("chunked"))) {
+    result = 1;
+  }
+  else {
+    result = 0;
+  }
+
+  free(encoding);
+  return result;
+}
+
 static int
 check_document_dates (const char *headers, char **msg)
 {
@@ -866,6 +975,7 @@ check_http (void)
   double elapsed_time_transfer = 0.0;
   int page_len = 0;
   int result = STATE_OK;
+  char *force_host_header = NULL;
 
   /* try to connect to the host at the given port number */
   gettimeofday (&tv_temp, NULL);
@@ -895,18 +1005,32 @@ check_http (void)
   /* tell HTTP/1.1 servers not to keep the connection alive */
   xasprintf (&buf, "%sConnection: close\r\n", buf);
 
+  /* check if Host header is explicitly set in options */
+  if (http_opt_headers_count) {
+    for (i = 0; i < http_opt_headers_count ; i++) {
+      if (strcmp(http_opt_headers[i], "Host: ")) {
+        force_host_header = http_opt_headers[i];
+      }
+    }
+  }
+
   /* optionally send the host header info */
   if (host_name) {
-    /*
-     * Specify the port only if we're using a non-default port (see RFC 2616,
-     * 14.23).  Some server applications/configurations cause trouble if the
-     * (default) port is explicitly specified in the "Host:" header line.
-     */
-    if ((use_ssl == FALSE && server_port == HTTP_PORT) ||
-        (use_ssl == TRUE && server_port == HTTPS_PORT))
-      xasprintf (&buf, "%sHost: %s\r\n", buf, host_name);
-    else
-      xasprintf (&buf, "%sHost: %s:%d\r\n", buf, host_name, server_port);
+    if (force_host_header) {
+      xasprintf (&buf, "%s%s\r\n", buf, force_host_header);
+    }
+    else {
+      /*
+       * Specify the port only if we're using a non-default port (see RFC 2616,
+       * 14.23).  Some server applications/configurations cause trouble if the
+       * (default) port is explicitly specified in the "Host:" header line.
+       */
+      if ((use_ssl == FALSE && server_port == HTTP_PORT) ||
+          (use_ssl == TRUE && server_port == HTTPS_PORT))
+        xasprintf (&buf, "%sHost: %s\r\n", buf, host_name);
+      else
+        xasprintf (&buf, "%sHost: %s:%d\r\n", buf, host_name, server_port);
+    }
   }
 
   /* Inform server we accept any MIME type response
@@ -918,7 +1042,9 @@ check_http (void)
   /* optionally send any other header tag */
   if (http_opt_headers_count) {
     for (i = 0; i < http_opt_headers_count ; i++) {
-      xasprintf (&buf, "%s%s\r\n", buf, http_opt_headers[i]);
+      if (force_host_header != http_opt_headers[i]) {
+        xasprintf (&buf, "%s%s\r\n", buf, http_opt_headers[i]);
+      }
     }
     /* This cannot be free'd here because a redirection will then try to access this and segfault */
     /* Covered in a testcase in tests/check_http.t */
@@ -1041,13 +1167,21 @@ check_http (void)
     page += (size_t) strcspn (page, "\r\n");
     pos = page;
     if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
-        (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
+        (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2)) {
       page += (size_t) 2;
-    else
+      pos += (size_t) 2;
+    }
+    else {
       page += (size_t) 1;
+      pos += (size_t) 1;
+    }
   }
   page += (size_t) strspn (page, "\r\n");
   header[pos - header] = 0;
+
+  if (chunked_transfer_encoding(header))
+    page = decode_chunked_page(page, page);
+
   if (verbose)
     printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
                 (no_body ? "  [[ skipped ]]" : page));
@@ -1122,6 +1256,7 @@ check_http (void)
     result = max_state_alt(check_document_dates(header, &msg), result);
   }
 
+
   /* Page and Header content checks go here */
   if (strlen (header_expect)) {
     if (!strstr (header, header_expect)) {
@@ -1134,7 +1269,6 @@ check_http (void)
     }
   }
 
-
   if (strlen (string_expect)) {
     if (!strstr (page, string_expect)) {
       strncpy(&output_string_search[0],string_expect,sizeof(output_string_search));

+ 30 - 8
plugins/check_ldap.c

@@ -54,6 +54,7 @@ void print_usage (void);
 
 char ld_defattr[] = "(objectclass=*)";
 char *ld_attr = ld_defattr;
+char *ld_uri = NULL;
 char *ld_host = NULL;
 char *ld_base = NULL;
 char *ld_passwd = NULL;
@@ -121,13 +122,29 @@ main (int argc, char *argv[])
 	gettimeofday (&tv, NULL);
 
 	/* initialize ldap */
+	if (ld_uri != NULL)
+	{
+#ifdef HAVE_LDAP_INITIALIZE
+		int result = ldap_initialize(&ld, ld_uri);
+		if (result != LDAP_SUCCESS)
+		{
+			printf ("Failed to connect to LDAP server at %s: %s\n",
+				ld_uri, ldap_err2string(result));
+			return STATE_CRITICAL;
+		}
+#else
+		printf ("Sorry, this version of %s was compiled without URI support!\n",
+			argv[0]);
+		return STATE_CRITICAL;
+#endif
+	}
 #ifdef HAVE_LDAP_INIT
-	if (!(ld = ldap_init (ld_host, ld_port))) {
+	else if (!(ld = ldap_init (ld_host, ld_port))) {
 		printf ("Could not connect to the server at port %i\n", ld_port);
 		return STATE_CRITICAL;
 	}
 #else
-	if (!(ld = ldap_open (ld_host, ld_port))) {
+	else if (!(ld = ldap_open (ld_host, ld_port))) {
 		if (verbose)
 			ldap_perror(ld, "ldap_open");
 		printf (_("Could not connect to the server at port %i\n"), ld_port);
@@ -248,6 +265,7 @@ process_arguments (int argc, char **argv)
 		{"version", no_argument, 0, 'V'},
 		{"timeout", required_argument, 0, 't'},
 		{"hostname", required_argument, 0, 'H'},
+		{"uri", required_argument, 0, 'U'},
 		{"base", required_argument, 0, 'b'},
 		{"attr", required_argument, 0, 'a'},
 		{"bind", required_argument, 0, 'D'},
@@ -276,7 +294,7 @@ process_arguments (int argc, char **argv)
 	}
 
 	while (1) {
-		c = getopt_long (argc, argv, "hvV234TS6t:c:w:H:b:p:a:D:P:", longopts, &option);
+		c = getopt_long (argc, argv, "hvV234TS6t:c:w:H:b:p:a:D:P:U:", longopts, &option);
 
 		if (c == -1 || c == EOF)
 			break;
@@ -291,6 +309,9 @@ process_arguments (int argc, char **argv)
 		case 't':									/* timeout period */
 			timeout_interval = parse_timeout_string(optarg);
 			break;
+		case 'U':
+			ld_uri = optarg;
+			break;
 		case 'H':
 			ld_host = optarg;
 			break;
@@ -372,11 +393,12 @@ process_arguments (int argc, char **argv)
 int
 validate_arguments ()
 {
-	if (ld_host==NULL || strlen(ld_host)==0)
-		usage4 (_("Please specify the host name\n"));
+	if ((ld_host==NULL || strlen(ld_host)==0) &&
+		(ld_uri==NULL || strlen(ld_uri)==0))
+		usage4 (_("Please specify the host name or LDAP URI\n"));
 
 	if (ld_base==NULL)
-		usage4 (_("Please specify the LDAP base\n"));
+		usage4 (_("Please specify the LDAP base DN\n"));
 
 	return OK;
 }
@@ -446,8 +468,8 @@ void
 print_usage (void)
 {
   printf ("%s\n", _("Usage:"));
-	printf (" %s -H <host> -b <base_dn> [-p <port>] [-a <attr>] [-D <binddn>]",progname);
-  printf ("\n       [-P <password>] [-w <warn_time>] [-c <crit_time>] [-t timeout]%s\n",
+  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",
 #ifdef HAVE_LDAP_SET_OPTION
 			"\n       [-2|-3] [-4|-6]"
 #else

+ 29 - 9
plugins/check_mrtgtraf.c

@@ -41,6 +41,7 @@ int validate_arguments (void);
 void print_help(void);
 void print_usage(void);
 
+int verbose = false;
 char *log_file = NULL;
 int expire_minutes = -1;
 int use_average = TRUE;
@@ -88,6 +89,7 @@ main (int argc, char **argv)
 		usage4 (_("Unable to open MRTG log file"));
 
 	line = 0;
+
 	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
 
 		line++;
@@ -104,22 +106,32 @@ main (int argc, char **argv)
 		/* grab the timestamp */
 		temp_buffer = strtok (input_buffer, " ");
 		timestamp = strtoul (temp_buffer, NULL, 10);
+		if (verbose)
+			printf("%s %lu\n", _("Found timestamp of:"), timestamp);
 
 		/* grab the average incoming transfer rate */
 		temp_buffer = strtok (NULL, " ");
 		average_incoming_rate = strtoul (temp_buffer, NULL, 10);
+		if (verbose)
+			printf("%s %lu\n", _("Found average incoming rate of:"), average_incoming_rate);
 
 		/* grab the average outgoing transfer rate */
 		temp_buffer = strtok (NULL, " ");
 		average_outgoing_rate = strtoul (temp_buffer, NULL, 10);
+		if (verbose)
+			printf("%s %lu\n", _("Found average outgoing rate of:"), average_outgoing_rate);
 
 		/* grab the maximum incoming transfer rate */
 		temp_buffer = strtok (NULL, " ");
 		maximum_incoming_rate = strtoul (temp_buffer, NULL, 10);
+		if (verbose)
+			printf("%s %lu\n", _("Found maximum incoming rate of:"), maximum_incoming_rate);
 
 		/* grab the maximum outgoing transfer rate */
 		temp_buffer = strtok (NULL, " ");
 		maximum_outgoing_rate = strtoul (temp_buffer, NULL, 10);
+		if (verbose)
+			printf("%s %lu\n", _("Found maximum outgoing rate of:"), maximum_outgoing_rate);
 	}
 
 	/* close the log file */
@@ -138,47 +150,49 @@ main (int argc, char **argv)
 
 	/* else check the incoming/outgoing rates */
 	if (use_average == TRUE) {
+		if (verbose) printf("%s\n", _("Using average rates not maximum."));
 		incoming_rate = average_incoming_rate;
 		outgoing_rate = average_outgoing_rate;
 	}
 	else {
+		if (verbose) printf("%s\n", _("Using default maximum rates."));
 		incoming_rate = maximum_incoming_rate;
 		outgoing_rate = maximum_outgoing_rate;
 	}
 
 	/* report incoming traffic in Bytes/sec */
 	if (incoming_rate < 1024) {
-		strcpy (incoming_speed_rating, "B/s");
+		strcpy (incoming_speed_rating, "B");
 		adjusted_incoming_rate = (double) incoming_rate;
 	}
 
 	/* report incoming traffic in KBytes/sec */
 	else if (incoming_rate < (1024 * 1024)) {
-		strcpy (incoming_speed_rating, "KB/s");
+		strcpy (incoming_speed_rating, "KB");
 		adjusted_incoming_rate = (double) (incoming_rate / 1024.0);
 	}
 
 	/* report incoming traffic in MBytes/sec */
 	else {
-		strcpy (incoming_speed_rating, "MB/s");
+		strcpy (incoming_speed_rating, "MB");
 		adjusted_incoming_rate = (double) (incoming_rate / 1024.0 / 1024.0);
 	}
 
 	/* report outgoing traffic in Bytes/sec */
 	if (outgoing_rate < 1024) {
-		strcpy (outgoing_speed_rating, "B/s");
+		strcpy (outgoing_speed_rating, "B");
 		adjusted_outgoing_rate = (double) outgoing_rate;
 	}
 
 	/* report outgoing traffic in KBytes/sec */
 	else if (outgoing_rate < (1024 * 1024)) {
-		strcpy (outgoing_speed_rating, "KB/s");
+		strcpy (outgoing_speed_rating, "KB");
 		adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0);
 	}
 
 	/* report outgoing traffic in MBytes/sec */
 	else {
-		strcpy (outgoing_speed_rating, "MB/s");
+		strcpy (outgoing_speed_rating, "MB");
 		adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0 / 1024.0);
 	}
 
@@ -191,7 +205,7 @@ main (int argc, char **argv)
 		result = STATE_WARNING;
 	}
 
-	xasprintf (&error_message, _("%s. In = %0.1f %s, %s. Out = %0.1f %s|%s %s\n"),
+	xasprintf (&error_message, _("%s. In = %0.1f %s/s, %s. Out = %0.1f %s/s|%s %s\n"),
 	          (use_average == TRUE) ? _("Avg") : _("Max"), adjusted_incoming_rate,
 	          incoming_speed_rating, (use_average == TRUE) ? _("Avg") : _("Max"),
 	          adjusted_outgoing_rate, outgoing_speed_rating,
@@ -224,6 +238,7 @@ process_arguments (int argc, char **argv)
 		{"aggregation", required_argument, 0, 'a'},
 		{"critical", required_argument, 0, 'c'},
 		{"warning", required_argument, 0, 'w'},
+		{"verbose", no_argument, 0, 'v'},
 		{"version", no_argument, 0, 'V'},
 		{"help", no_argument, 0, 'h'},
 		{0, 0, 0, 0}
@@ -242,7 +257,7 @@ process_arguments (int argc, char **argv)
 	}
 
 	while (1) {
-		c = getopt_long (argc, argv, "hVF:e:a:c:w:", longopts, &option);
+		c = getopt_long (argc, argv, "hVvF:e:a:c:w:", longopts, &option);
 
 		if (c == -1 || c == EOF)
 			break;
@@ -268,6 +283,9 @@ process_arguments (int argc, char **argv)
 			sscanf (optarg, "%lu,%lu", &incoming_warning_threshold,
 							&outgoing_warning_threshold);
 			break;
+		case 'v':
+			verbose = true;
+			break;
 		case 'V':									/* version */
 			print_revision (progname, NP_VERSION);
 			exit (STATE_OK);
@@ -356,9 +374,11 @@ print_help (void)
   printf ("    %s\n", _("Warning threshold pair <incoming>,<outgoing>"));
   printf (" %s\n", "-c, --critical");
   printf ("    %s\n", _("Critical threshold pair <incoming>,<outgoing>"));
+  printf (" %s\n", _("-v, --verbose"));
+  printf ("    %s\n", _("Verbose output durring plugin runtime."));
 
   printf ("\n");
-	printf ("%s\n", _("Notes:"));
+  printf ("%s\n", _("Notes:"));
   printf (" %s\n", _("- MRTG stands for Multi Router Traffic Grapher. It can be downloaded from"));
   printf (" %s\n", "  http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
   printf (" %s\n", _("- While MRTG can monitor things other than traffic rates, this"));

+ 1 - 0
plugins/check_nagios.c

@@ -66,6 +66,7 @@ main (int argc, char **argv)
 	int procppid = 0;
 	int procvsz = 0;
 	int procrss = 0;
+	char *proc_cgroup_hierarchy;
 	float procpcpu = 0;
 	char procstat[8];
 #ifdef PS_USES_PROCETIME

+ 1 - 1
plugins/check_ntp.c

@@ -616,7 +616,7 @@ double jitter_request(const char *host, int *status){
 				if (bytes_read != ntp_cm_ints + req.count)
 					die(STATE_UNKNOWN, _("Invalid NTP response: %d bytes read does not equal %d plus %d data segment"), bytes_read, ntp_cm_ints, req.count); 
 				/* else null terminate */
-				strncpy(req.data[req.count], "\0", 1);
+				req.data[req.count] = '\0';
 
 				DBG(print_ntp_control_message(&req));
 

+ 6 - 3
plugins/check_ntp_peer.c

@@ -599,17 +599,20 @@ int main(int argc, char *argv[]){
 	}
 	oresult = result;
 	
-	if(do_truechimers)
+	if(do_truechimers) {
 		tresult = get_status(num_truechimers, truechimer_thresholds);
 		result = max_state_alt(result, tresult);
+	}
 
-	if(do_stratum)
+	if(do_stratum) {
 		sresult = get_status(stratum, stratum_thresholds);
 		result = max_state_alt(result, sresult);
+	}
 
-	if(do_jitter)
+	if(do_jitter) {
 		jresult = get_status(jitter, jitter_thresholds);
 		result = max_state_alt(result, jresult);
+	}
 
 	switch (result) {
 		case STATE_CRITICAL :

+ 48 - 6
plugins/check_procs.c

@@ -70,6 +70,7 @@ int options = 0; /* bitmask of filter criteria to test against */
 #define PCPU 256
 #define ELAPSED 512
 #define EREG_ARGS 1024
+#define CGROUP_HIERARCHY 2048
 
 #define KTHREAD_PARENT "kthreadd" /* the parent process of kernel threads:
 							ppid of procs are compared to pid of this proc*/
@@ -93,6 +94,7 @@ int rss;
 float pcpu;
 char *statopts;
 char *prog;
+char *cgroup_hierarchy;
 char *args;
 char *input_filename = NULL;
 regex_t re_args;
@@ -121,6 +123,7 @@ main (int argc, char **argv)
 	char *input_buffer;
 	char *input_line;
 	char *procprog;
+	char *proc_cgroup_hierarchy;
 
 	pid_t mypid = 0;
 	pid_t myppid = 0;
@@ -138,6 +141,7 @@ main (int argc, char **argv)
 	char procstat[8];
 	char procetime[MAX_INPUT_BUFFER] = { '\0' };
 	char *procargs;
+	char *tmp;
 
 	const char *zombie = "Z";
 
@@ -161,6 +165,7 @@ main (int argc, char **argv)
 
 	input_buffer = malloc (MAX_INPUT_BUFFER);
 	procprog = malloc (MAX_INPUT_BUFFER);
+	proc_cgroup_hierarchy = malloc (MAX_INPUT_BUFFER);
 
 	xasprintf (&metric_name, "PROCS");
 	metric = METRIC_PROCS;
@@ -210,6 +215,7 @@ main (int argc, char **argv)
 			printf ("%s", input_line);
 
 		strcpy (procprog, "");
+		strcpy (proc_cgroup_hierarchy, "");
 		xasprintf (&procargs, "%s", "");
 
 		cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
@@ -229,11 +235,17 @@ main (int argc, char **argv)
 			/* we need to convert the elapsed time to seconds */
 			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\n", 
+			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",
 					procs, procuid, procvsz, procrss,
-					procpid, procppid, procpcpu, procstat, 
+					procpid, procppid, procpcpu, procstat,
 					procetime, procprog, procargs);
+				if (strstr(PS_COMMAND, "cgroup") != NULL) {
+					printf(" proc_cgroup_hierarchy=%s\n", proc_cgroup_hierarchy);
+				} else {
+					printf("\n");
+				}
+			}
 
 			/* Ignore self */
 			if ((usepid && mypid == procpid) ||
@@ -283,6 +295,17 @@ main (int argc, char **argv)
 				resultsum |= RSS;
 			if ((options & PCPU)  && (procpcpu >= pcpu))
 				resultsum |= PCPU;
+			if (options & CGROUP_HIERARCHY) {
+				if(!strncmp(proc_cgroup_hierarchy,"-", 2) && !strncmp(cgroup_hierarchy,"/", 2)) {
+					resultsum |= CGROUP_HIERARCHY;
+				} else {
+					if((tmp = strstr(proc_cgroup_hierarchy,":/")) != NULL) {
+						if(!strcmp(tmp+1,cgroup_hierarchy)) {
+							resultsum |= CGROUP_HIERARCHY;
+						};
+					};
+				};
+			};
 
 			found++;
 
@@ -292,10 +315,15 @@ 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\n", 
+				printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s",
 					procuid, procvsz, procrss,
 					procpid, procppid, procpcpu, procstat, 
 					procetime, procprog, procargs);
+				if (strstr(PS_COMMAND, "cgroup") != NULL) {
+					printf(" cgroup_hierarchy=%s\n", cgroup_hierarchy);
+				} else {
+					printf("\n");
+				}
 			}
 
 			if (metric == METRIC_VSZ)
@@ -409,6 +437,7 @@ process_arguments (int argc, char **argv)
 		{"input-file", required_argument, 0, CHAR_MAX+2},
 		{"no-kthreads", required_argument, 0, 'k'},
 		{"traditional-filter", no_argument, 0, 'T'},
+		{"cgroup-hierarchy", required_argument, 0, 'g'},
 		{0, 0, 0, 0}
 	};
 
@@ -417,7 +446,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:T",
+		c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:Tg:",
 			longopts, &option);
 
 		if (c == -1 || c == EOF)
@@ -487,6 +516,15 @@ process_arguments (int argc, char **argv)
 			          prog);
 			options |= PROG;
 			break;
+		case 'g':									/* cgroup hierarchy */
+			if (cgroup_hierarchy)
+				break;
+			else
+				cgroup_hierarchy = optarg;
+			xasprintf (&fmt, _("%s%scgroup hierarchy '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
+			          cgroup_hierarchy);
+			options |= CGROUP_HIERARCHY;
+			break;
 		case 'a':									/* args (full path name with args) */
 			/* TODO: allow this to be passed in with --metric */
 			if (args)
@@ -556,7 +594,7 @@ process_arguments (int argc, char **argv)
 				metric = METRIC_ELAPSED;
 				break;
 			}
-				
+
 			usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
 		case 'k':	/* linux kernel thread filter */
 			kthread_filter = 1;
@@ -744,6 +782,8 @@ print_help (void)
   printf ("   %s\n", _("Only scan for exact matches of COMMAND (without path)."));
   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");
+  printf ("   %s\n", _("Only scan for processes belonging to STRING hierarchy (works on Linux only)."));
 
 	printf(_("\n\
 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
@@ -761,6 +801,8 @@ be the total number of running processes\n\n"));
   printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
   printf ("  %s\n", _("Warning if not two processes with command name portsentry."));
   printf ("  %s\n\n", _("Critical if < 2 or > 1024 processes"));
+  printf (" %s\n", "check_procs -c 1:1 -C bind -g /");
+  printf ("  %s\n\n", _("Critical if not one processes with command name bind belonging to root cgroup."));
   printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
   printf ("  %s\n", _("Warning alert if > 10 processes with command arguments containing"));
   printf ("  %s\n\n", _("'/usr/local/bin/perl' and owned by root"));

+ 5 - 5
plugins/check_real.c

@@ -163,22 +163,22 @@ main (int argc, char **argv)
 
 		/* Part I - Server Check */
 
-		/* send the OPTIONS request */
-		sprintf (buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\n", host_name,
+		/* send the DESCRIBE request */
+		sprintf (buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n", host_name,
 						 server_port, server_url);
 		result = send (sd, buffer, strlen (buffer), 0);
 
 		/* send the header sync */
-		sprintf (buffer, "CSeq: 2\n");
+		sprintf (buffer, "CSeq: 2\r\n");
 		result = send (sd, buffer, strlen (buffer), 0);
 
 		/* send a newline so the server knows we're done with the request */
-		sprintf (buffer, "\n");
+		sprintf (buffer, "\r\n");
 		result = send (sd, buffer, strlen (buffer), 0);
 
 		/* watch for the REAL connection string */
 		result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
-		buffer[result] = "\0"; /* null terminate recieved buffer */
+		buffer[result] = '\0'; /* null terminate recieved buffer */
 
 		/* return a CRITICAL status if we couldn't read any data */
 		if (result == -1) {

+ 44 - 12
plugins/check_snmp.c

@@ -103,6 +103,8 @@ int errcode, excode;
 
 char *server_address = NULL;
 char *community = NULL;
+char **contextargs = NULL;
+char *context = NULL;
 char **authpriv = NULL;
 char *proto = NULL;
 char *seclevel = NULL;
@@ -127,6 +129,7 @@ size_t nunits = 0;
 size_t unitv_size = OID_COUNT_STEP;
 int numoids = 0;
 int numauthpriv = 0;
+int numcontext = 0;
 int verbose = 0;
 int usesnmpgetnext = FALSE;
 char *warning_thresholds = NULL;
@@ -303,8 +306,8 @@ main (int argc, char **argv)
 		snmpcmd = strdup (PATH_TO_SNMPGET);
 	}
 
-	/* 10 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */
-	command_line = calloc (10 + numauthpriv + 1 + numoids + 1, sizeof (char *));
+	/* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */
+	command_line = calloc (10 + numcontext + numauthpriv + 1 + numoids + 1, sizeof (char *));
 	command_line[0] = snmpcmd;
 	command_line[1] = strdup ("-Le");
 	command_line[2] = strdup ("-t");
@@ -316,23 +319,28 @@ main (int argc, char **argv)
 	command_line[8] = "-v";
 	command_line[9] = strdup (proto);
 
+	for (i = 0; i < numcontext; i++) {
+		command_line[10 + i] = contextargs[i];
+	}
+	
 	for (i = 0; i < numauthpriv; i++) {
-		command_line[10 + i] = authpriv[i];
+		command_line[10 + numcontext + i] = authpriv[i];
 	}
 
-	xasprintf (&command_line[10 + numauthpriv], "%s:%s", server_address, port);
+	xasprintf (&command_line[10 + numcontext + numauthpriv], "%s:%s", server_address, port);
 
 	/* 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",
-		snmpcmd, command_interval, retries, strlen(miblist) ? miblist : "''", proto, "[authpriv]",
-		server_address, port);
+	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]", server_address, port);
 
 	for (i = 0; i < numoids; i++) {
-		command_line[10 + numauthpriv + 1 + i] = oids[i];
+		command_line[10 + numcontext + numauthpriv + 1 + i] = oids[i];
 		xasprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]);	
 	}
 
-	command_line[10 + numauthpriv + 1 + numoids] = NULL;
+	command_line[10 + numcontext + numauthpriv + 1 + numoids] = NULL;
 
 	if (verbose)
 		printf ("%s\n", cl_hidden_auth);
@@ -584,6 +592,17 @@ main (int argc, char **argv)
 			len = sizeof(perfstr)-strlen(perfstr)-1;
 			strncat(perfstr, show, len>ptr-show ? ptr-show : len);
 
+			if (warning_thresholds) {
+				strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
+				strncat(perfstr, warning_thresholds, sizeof(perfstr)-strlen(perfstr)-1);
+			}
+
+			if (critical_thresholds) {
+				if (!warning_thresholds) strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
+				strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
+				strncat(perfstr, critical_thresholds, sizeof(perfstr)-strlen(perfstr)-1);
+			}
+
 			if (type)
 				strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
 			if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL) {
@@ -682,6 +701,7 @@ process_arguments (int argc, char **argv)
 		{"retries", required_argument, 0, 'e'},
 		{"miblist", required_argument, 0, 'm'},
 		{"protocol", required_argument, 0, 'P'},
+		{"context", required_argument, 0, 'N'},
 		{"seclevel", required_argument, 0, 'L'},
 		{"secname", required_argument, 0, 'U'},
 		{"authproto", required_argument, 0, 'a'},
@@ -711,7 +731,7 @@ process_arguments (int argc, char **argv)
 	}
 
 	while (1) {
-		c = getopt_long (argc, argv, "nhvVOt:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:L:U:a:x:A:X:",
+		c = getopt_long (argc, argv, "nhvVOt:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:",
 									 longopts, &option);
 
 		if (c == -1 || c == EOF)
@@ -749,6 +769,9 @@ process_arguments (int argc, char **argv)
 		case 'P':	/* SNMP protocol version */
 			proto = optarg;
 			break;
+		case 'N':	/* SNMPv3 context */
+			context = optarg;
+			break;
 		case 'L':	/* security level */
 			seclevel = optarg;
 			break;
@@ -992,6 +1015,13 @@ validate_arguments ()
 		authpriv[1] = strdup (community);
 	}
 	else if ( strcmp (proto, "3") == 0 ) {		/* snmpv3 args */
+		if (!(context == NULL)) {
+			numcontext = 2;
+			contextargs = calloc (numcontext, sizeof (char *));
+			contextargs[0] = strdup ("-n");
+			contextargs[1] = strdup (context);
+		}
+		
 		if (seclevel == NULL)
 			xasprintf(&seclevel, "noAuthNoPriv");
 
@@ -1135,6 +1165,8 @@ print_help (void)
 	printf ("    %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
 	printf (" %s\n", "-P, --protocol=[1|2c|3]");
 	printf ("    %s\n", _("SNMP protocol version"));
+	printf (" %s\n", "-N, --context=CONTEXT");
+	printf ("    %s\n", _("SNMPv3 context"));
 	printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
 	printf ("    %s\n", _("SNMPv3 securityLevel"));
 	printf (" %s\n", "-a, --authproto=[MD5|SHA]");
@@ -1242,6 +1274,6 @@ print_usage (void)
 	printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname);
 	printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
 	printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
-	printf ("[-m miblist] [-P snmp version] [-L seclevel] [-U secname] [-a authproto]\n");
-	printf ("[-A authpasswd] [-x privproto] [-X privpasswd]\n");
+	printf ("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
+	printf ("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd]\n");
 }

+ 6 - 6
plugins/check_ssh.c

@@ -250,18 +250,18 @@ ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol
 
 		if (remote_version && strcmp(remote_version, ssh_server)) {
 			printf
-				(_("SSH WARNING - %s (protocol %s) version mismatch, expected '%s'\n"),
+				(_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"),
 				 ssh_server, ssh_proto, remote_version);
 			close(sd);
-			exit (STATE_WARNING);
+			exit (STATE_CRITICAL);
 		}
 
 		if (remote_protocol && strcmp(remote_protocol, ssh_proto)) {
 			printf
-				(_("SSH WARNING - %s (protocol %s) protocol version mismatch, expected '%s'\n"),
+				(_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s'\n"),
 				 ssh_server, ssh_proto, remote_protocol);
 			close(sd);
-			exit (STATE_WARNING);
+			exit (STATE_CRITICAL);
 		}
 
 		elapsed_time = (double)deltime(tv) / 1.0e6;
@@ -304,10 +304,10 @@ print_help (void)
 	printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
 
 	printf (" %s\n", "-r, --remote-version=STRING");
-  printf ("    %s\n", _("Warn if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
+  printf ("    %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
 
 	printf (" %s\n", "-P, --remote-protocol=STRING");
-  printf ("    %s\n", _("Warn if protocol doesn't match expected protocol version (ex: 2.0)"));
+  printf ("    %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)"));
 
 	printf (UT_VERBOSE);
 

+ 4 - 4
plugins/check_tcp.c

@@ -172,7 +172,7 @@ main (int argc, char **argv)
 	}
 	else if (!strncmp(SERVICE, "JABBER", 6)) {
 		SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n";
-		EXPECT = "<?xml version=\'1.0\'?><stream:stream xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'";
+		EXPECT = "<?xml version=\'1.0\'";
 		QUIT = "</stream:stream>\n";
 		flags |= FLAG_HIDE_OUTPUT;
 		PORT = 5222;
@@ -253,8 +253,8 @@ main (int argc, char **argv)
 	}
 #endif /* HAVE_SSL */
 
-	if (server_send != NULL) {		/* Something to send? */
-		my_send(server_send, strlen(server_send));
+	if (server_send != NULL &&  strlen(server_send) > my_send(server_send, strlen(server_send))) {		/* Something to send? and validate return*/
+		die(STATE_UNKNOWN, "%s - %s", _("No data sent to host"), strerror(errno));
 	}
 
 	if (delay > 0) {
@@ -640,7 +640,7 @@ print_help (void)
 	printf (UT_IPv46);
 
 	printf (" %s\n", "-E, --escape");
-  printf ("    %s\n", _("Can use \\n, \\r, \\t or \\ in send or quit string. Must come before send or quit option"));
+  printf ("    %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option"));
   printf ("    %s\n", _("Default: nothing added to send, \\r\\n added to end of quit"));
   printf (" %s\n", "-s, --send=STRING");
   printf ("    %s\n", _("String to send to the server"));

+ 3 - 3
plugins/check_ups.c

@@ -66,7 +66,7 @@ enum {
 #define UPSSTATUS_BOOST    512
 #define UPSSTATUS_CHRG    1024
 #define UPSSTATUS_DISCHRG 2048
-#define UPSSTATUS_UNKOWN  4096
+#define UPSSTATUS_UNKNOWN  4096
 
 enum { NOSUCHVAR = ERROR-1 };
 
@@ -181,7 +181,7 @@ main (int argc, char **argv)
 			if (status & UPSSTATUS_DISCHRG) {
 				xasprintf (&ups_status, "%s%s", ups_status, _(", Discharging"));
 			}
-			if (status & UPSSTATUS_UNKOWN) {
+			if (status & UPSSTATUS_UNKNOWN) {
 				xasprintf (&ups_status, "%s%s", ups_status, _(", Unknown"));
 			}
 		}
@@ -379,7 +379,7 @@ determine_status (void)
 		else if (!strcmp (ptr, "DISCHRG"))
 			status |= UPSSTATUS_DISCHRG;
 		else
-			status |= UPSSTATUS_UNKOWN;
+			status |= UPSSTATUS_UNKNOWN;
 	}
 
 	return OK;

+ 1 - 1
plugins/negate.c

@@ -98,7 +98,7 @@ main (int argc, char **argv)
 		die (max_state_alt (result, STATE_UNKNOWN), _("No data returned from command\n"));
 
 	for (i = 0; i < chld_out.lines; i++) {
-		if (subst_text && result >= 0 && result <= 4 && result != state[result])  {
+		if (subst_text && result >= 0 && result <= 3 && result != state[result])  {
 			/* Loop over each match found */
 			while ((sub = strstr (chld_out.line[i], state_text (result)))) {
 				/* Terminate the first part and skip over the string we'll substitute */

+ 6 - 7
plugins/netutils.c

@@ -158,7 +158,7 @@ int
 np_net_connect (const char *host_name, int port, int *sd, int proto)
 {
 	struct addrinfo hints;
-	struct addrinfo *r, *res;
+	struct addrinfo *res;
 	struct sockaddr_un su;
 	char port_str[6], host[MAX_HOST_ADDRESS_LENGTH];
 	size_t len;
@@ -192,19 +192,18 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
 			return STATE_UNKNOWN;
 		}
 
-		r = res;
-		while (r) {
+		while (res) {
 			/* attempt to create a socket */
-			*sd = socket (r->ai_family, socktype, r->ai_protocol);
+			*sd = socket (res->ai_family, socktype, res->ai_protocol);
 
 			if (*sd < 0) {
 				printf ("%s\n", _("Socket creation failed"));
-				freeaddrinfo (r);
+				freeaddrinfo (res);
 				return STATE_UNKNOWN;
 			}
 
 			/* attempt to open a connection */
-			result = connect (*sd, r->ai_addr, r->ai_addrlen);
+			result = connect (*sd, res->ai_addr, res->ai_addrlen);
 
 			if (result == 0) {
 				was_refused = FALSE;
@@ -220,7 +219,7 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
 			}
 
 			close (*sd);
-			r = r->ai_next;
+			res = res->ai_next;
 		}
 		freeaddrinfo (res);
 	}

+ 1 - 1
plugins/netutils.h

@@ -41,7 +41,7 @@
 # include <sys/un.h>
 # ifndef UNIX_PATH_MAX
    /* linux uses this, on sun it's hard-coded at 108 without a define */
-#  define UNIX_PATH_MAX 108
+#  define UNIX_PATH_MAX 104
 # endif /* UNIX_PATH_MAX */
 #endif /* HAVE_SYS_UN_H */
 

+ 9 - 3
plugins/sslutils.c

@@ -49,13 +49,16 @@ int np_net_ssl_init_with_hostname_and_version(int sd, char *host_name, int versi
 
 int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, char *privkey) {
 	SSL_METHOD *method = NULL;
+	long ssl_options = NULL;
 
 	switch (version) {
 	case 0: /* Deafult to auto negotiation */
 		method = SSLv23_client_method();
+		ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
 		break;
 	case 1: /* TLSv1 protocol */
 		method = TLSv1_client_method();
+		ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
 		break;
 	case 2: /* SSLv2 protocol */
 #if defined(USE_GNUTLS) || defined(OPENSSL_NO_SSL2)
@@ -63,10 +66,12 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
 		return STATE_CRITICAL;
 #else
 		method = SSLv2_client_method();
+		ssl_options = SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
 #endif
 		break;
 	case 3: /* SSLv3 protocol */
 		method = SSLv3_client_method();
+		ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_TLSv1;
 		break;
 	default: /* Unsupported */
 		printf("%s\n", _("CRITICAL - Unsupported SSL protocol version."));
@@ -92,8 +97,9 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
 		}
 	}
 #ifdef SSL_OP_NO_TICKET
-	SSL_CTX_set_options(c, SSL_OP_NO_TICKET);
+	ssl_options |= SSL_OP_NO_TICKET;
 #endif
+	if (ssl_options) SSL_CTX_set_options(c, ssl_options);
 	SSL_CTX_set_mode(c, SSL_MODE_AUTO_RETRY);
 	if ((s = SSL_new(c)) != NULL) {
 #ifdef SSL_set_tlsext_host_name
@@ -167,9 +173,9 @@ int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
 		printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject."));
 		return STATE_CRITICAL;
 	}
-	cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, cn, sizeof(cn));
+	cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, cn, sizeof(cn)-1);
 	if (cnlen == -1)
-		strcpy(cn, _("Unknown CN"));
+		strncpy(cn, _("Unknown CN\0"), 12);
 
 	/* Retrieve timestamp of certificate */
 	tm = X509_get_notAfter(certificate);

+ 1 - 0
plugins/t/check_dns.t

@@ -74,6 +74,7 @@ cmp_ok( $res->return_code, '==', 2, "Critical threshold passed");
 
 $res = NPTest->testCmd("./check_dns -H $hostname_valid -t 5 -w 0 -c 5");
 cmp_ok( $res->return_code, '==', 1, "Warning threshold passed");
+like( $res->output, '/\|time=[\d\.]+s;0.0*;5\.0*;0\.0*/', "Output performance data OK" );
 
 $res = NPTest->testCmd("./check_dns -H $hostname_invalid -t 1");
 cmp_ok( $res->return_code, '==', 2, "Invalid $hostname_invalid");

+ 1 - 1
plugins/t/check_procs.t

@@ -26,7 +26,7 @@ $result = NPTest->testCmd( "./check_procs -w 100000 -c 100000 -s Z" );
 is( $result->return_code, 0, "Checking less than 100000 zombie processes" );
 like( $result->output, '/^PROCS OK: [0-9]+ process(es)? with /', "Output correct" );
 
-if(fork() == 0) { exec("sleep 7"); } # fork a test process
+if(fork() == 0) { exec("sleep 7"); } else { sleep(1) } # fork a test process in child and give child time to fork in parent
 $result = NPTest->testCmd( "./check_procs -a 'sleep 7'" );
 is( $result->return_code, 0, "Parent process is ignored" );
 like( $result->output, '/^PROCS OK: 1 process?/', "Output correct" );

+ 1 - 1
plugins/t/negate.t

@@ -50,7 +50,7 @@ is( $res->output, "OK: a dummy okay", "The quoted string is passed through to su
 $res = NPTest->testCmd( "./negate '$PWD/check_dummy 0' 'a dummy okay'" );
 is( $res->output, "No data returned from command", "Bad command, as expected (trying to execute './check_dummy 0')");
 
-$res = NPTest->testCmd( './negate $PWD/check_dummy 0 \'$$ a dummy okay\'' );
+$res = NPTest->testCmd( './negate '.$PWD.'/check_dummy 0 \'$$ a dummy okay\'' );
 is( $res->output, 'OK: $$ a dummy okay', 'Proves that $$ is not being expanded again' );
 
 my %state = (

+ 27 - 5
plugins/tests/check_http.t

@@ -17,7 +17,7 @@ use Test::More;
 use NPTest;
 use FindBin qw($Bin);
 
-my $common_tests = 70;
+my $common_tests = 72;
 my $ssl_only_tests = 8;
 # Check that all dependent modules are available
 eval {
@@ -54,6 +54,18 @@ my $port_https_expired = $port_http + 2;
 # This array keeps sockets around for implementing timeouts
 my @persist;
 
+# Helper for returning chunked responses
+our $ckn = 0;
+sub chunked_resp {
+	$ckn++;
+	return "foo" if ($ckn < 2);
+	return "bar" if ($ckn < 3);
+	return "baz" if ($ckn < 4);
+	return "\n"  if ($ckn < 5);
+	$ckn = 0     if ($ckn < 6);
+	return undef;
+}
+
 # Start up all servers
 my @pids;
 my $pid = fork();
@@ -74,6 +86,7 @@ if ($pid) {
 				my $d = HTTP::Daemon::SSL->new(
 					LocalPort => $port_https_expired,
 					LocalAddr => "127.0.0.1",
+					ReuseAddr => 1,
 					SSL_cert_file => "$Bin/certs/expired-cert.pem",
 					SSL_key_file => "$Bin/certs/expired-key.pem",
 				) || die;
@@ -85,6 +98,7 @@ if ($pid) {
 			my $d = HTTP::Daemon::SSL->new(
 				LocalPort => $port_https,
 				LocalAddr => "127.0.0.1",
+				ReuseAddr => 1,
 				SSL_cert_file => "$Bin/certs/server-cert.pem",
 				SSL_key_file => "$Bin/certs/server-key.pem",
 			) || die;
@@ -101,6 +115,7 @@ if ($pid) {
 	my $d = HTTP::Daemon->new(
 		LocalPort => $port_http,
 		LocalAddr => "127.0.0.1",
+		ReuseAddr => 1,
 	) || die;
 	print "Please contact http at: <URL:", $d->url, ">\n";
 	run_server( $d );
@@ -124,6 +139,8 @@ sub run_server {
 				$c->send_crlf;
 				sleep 1;
 				$c->send_response("slow");
+			} elsif ($r->method eq "GET" and $r->url->path eq "/chunked") {
+				$c->send_response(HTTP::Response->new(200, 'OK', undef, \&chunked_resp));
 			} elsif ($r->url->path eq "/method") {
 				if ($r->method eq "DELETE") {
 					$c->send_error(HTTP::Status->RC_METHOD_NOT_ALLOWED);
@@ -185,21 +202,21 @@ SKIP: {
 
 	$result = NPTest->testCmd( "$command -p $port_https -S -C 14" );
 	is( $result->return_code, 0, "$command -p $port_https -S -C 14" );
-	is( $result->output, 'OK - Certificate \'Ton Voon\' will expire on 03/03/2019 21:41.', "output ok" );
+	is( $result->output, 'OK - Certificate \'Ton Voon\' will expire on Sun Mar  3 21:41:00 2019.', "output ok" );
 
 	$result = NPTest->testCmd( "$command -p $port_https -S -C 14000" );
 	is( $result->return_code, 1, "$command -p $port_https -S -C 14000" );
-	like( $result->output, '/WARNING - Certificate \'Ton Voon\' expires in \d+ day\(s\) \(03/03/2019 21:41\)./', "output ok" );
+	like( $result->output, '/WARNING - Certificate \'Ton Voon\' expires in \d+ day\(s\) \(Sun Mar  3 21:41:00 2019\)./', "output ok" );
 
 	# Expired cert tests
 	$result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" );
 	is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" );
-	like( $result->output, '/CRITICAL - Certificate \'Ton Voon\' expires in \d+ day\(s\) \(03/03/2019 21:41\)./', "output ok" );
+	like( $result->output, '/CRITICAL - Certificate \'Ton Voon\' expires in \d+ day\(s\) \(Sun Mar  3 21:41:00 2019\)./', "output ok" );
 
 	$result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" );
 	is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" );
 	is( $result->output,
-		'CRITICAL - Certificate \'Ton Voon\' expired on 03/05/2009 00:13.',
+		'CRITICAL - Certificate \'Ton Voon\' expired on Thu Mar  5 00:13:00 2009.',
 		"output ok" );
 
 }
@@ -364,6 +381,11 @@ sub run_common_tests {
 	is( $result->return_code, 0, $cmd);
 	like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
 
+  $cmd = "$command -u /chunked -s foobarbaz";
+  $result = NPTest->testCmd( $cmd );
+  is( $result->return_code, 0, $cmd);
+  like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
   # These tests may block
 	print "ALRM\n";
 

+ 10 - 1
plugins/tests/check_snmp.t

@@ -20,7 +20,16 @@ if ($@) {
 	plan skip_all => "Missing required module for test: $@";
 } else {
 	if (-x "./check_snmp") {
-		plan tests => $tests;
+        # check if snmpd has perl support
+        my $test = `snmpd -c tests/conf/snmpd.conf -C -r -H 2>&1`;
+        if(!defined $test) {
+	        plan skip_all => "snmpd required";
+        }
+        elsif($test =~ m/Warning: Unknown token: perl/) {
+	        plan skip_all => "snmpd has no perl support";
+        } else {
+		    plan tests => $tests;
+        }
 	} else {
 		plan skip_all => "No check_snmp compiled";
 	}

+ 2 - 2
po/de.po

@@ -1857,7 +1857,7 @@ msgstr ""
 
 #: plugins/check_mrtg.c:359
 msgid ""
-"packets/sec, etc.  I use MRTG in conjuction with the Novell NLM that allows"
+"packets/sec, etc.  I use MRTG in conjunction with the Novell NLM that allows"
 msgstr ""
 
 #: plugins/check_mrtg.c:360
@@ -5067,7 +5067,7 @@ msgstr ""
 
 #: plugins/check_ide_smart.c:384
 #, c-format
-msgid "ERROR - Status '%d' unkown. %d/%d tests passed\n"
+msgid "ERROR - Status '%d' unknown. %d/%d tests passed\n"
 msgstr ""
 
 #: plugins/check_ide_smart.c:417

+ 2 - 2
po/fr.po

@@ -1902,7 +1902,7 @@ msgstr ""
 
 #: plugins/check_mrtg.c:359
 msgid ""
-"packets/sec, etc.  I use MRTG in conjuction with the Novell NLM that allows"
+"packets/sec, etc.  I use MRTG in conjunction with the Novell NLM that allows"
 msgstr ""
 
 #: plugins/check_mrtg.c:360
@@ -5142,7 +5142,7 @@ msgstr "OK - En fonctionnement (%d/%d les tests on été réussi)\n"
 
 #: plugins/check_ide_smart.c:384
 #, c-format
-msgid "ERROR - Status '%d' unkown. %d/%d tests passed\n"
+msgid "ERROR - Status '%d' unknown. %d/%d tests passed\n"
 msgstr "ERREUR - État '%d' inconnu. %d/%d les tests on réussi\n"
 
 #: plugins/check_ide_smart.c:417

+ 2 - 2
po/nagios-plugins.pot

@@ -1800,7 +1800,7 @@ msgstr ""
 
 #: plugins/check_mrtg.c:359
 msgid ""
-"packets/sec, etc.  I use MRTG in conjuction with the Novell NLM that allows"
+"packets/sec, etc.  I use MRTG in conjunction with the Novell NLM that allows"
 msgstr ""
 
 #: plugins/check_mrtg.c:360
@@ -4928,7 +4928,7 @@ msgstr ""
 
 #: plugins/check_ide_smart.c:384
 #, c-format
-msgid "ERROR - Status '%d' unkown. %d/%d tests passed\n"
+msgid "ERROR - Status '%d' unknown. %d/%d tests passed\n"
 msgstr ""
 
 #: plugins/check_ide_smart.c:417

+ 2 - 0
test.pl.in

@@ -9,6 +9,8 @@ use Getopt::Long;
 
 use NPTest qw(DetermineTestHarnessDirectory TestsFrom);
 
+$ENV{LC_ALL} = 'C';
+
 my @tstdir;
 
 if ( ! GetOptions( "testdir:s" => \@tstdir ) )

+ 38 - 0
tools/find_authors

@@ -0,0 +1,38 @@
+#!/usr/bin/env sh
+
+#usernames that do not match attributed name
+declare -a usernames=("Jean-Claude_Computing" "Rafael" "linkslice" "juliopedreira" "nagios" "arvanus" "nafets" "abrist" "awiddersheim" "Holger_Weiß" "palli" "dermoth" "M._Remy" "tonvoon" "nagiosplugins" "Thomas_Guyot-Sionnest_thomas@aei.ca" "M._Sean_Finney" "(no_author)" "LAURENT_LICOUR")
+authors=()
+count=0
+THANKS="THANKS.in"
+AUTHORS="AUTHORS"
+
+# 1 - array to check against
+# 2 - name to search for
+# return 0 - no match, 1 - match
+check_names () {
+	declare -a int_arr=("${!1}")
+	for name in ${int_arr[@]}; do
+		if [[ "${2}" == "${name}" ]]; then
+			return 1
+		fi
+	done
+	return 0
+}
+
+# compare lists
+for name in $(git log | grep "Author:" | sed 's/Author: //g' | sed 's/ <.*>//g' | sed 's/ /_/g'); do
+	# skip to next name if found
+	if echo "${name}" | sed 's/_/ /g' | grep -q -f - "${THANKS}" || \
+	echo "${name}" | sed 's/_/ /g' | grep -q -f - "${AUTHORS}"; then
+		continue;
+	# name was not found, keep only one instance of it
+	elif $(check_names authors[@] "${name}") && $(check_names usernames[@] "${name}"); then
+			authors=("${authors[@]}" "${name}")
+	fi
+done
+
+echo "Authors not found:"
+for name in ${authors[@]}; do
+	echo "${name}" | sed 's/_/ /g'
+done

+ 2 - 0
tools/generate-change-log

@@ -19,6 +19,7 @@ use Text::Wrap;
 
 # The lines will have a length of no more than $columns - 1.
 $Text::Wrap::columns = 81;
+$Text::Wrap::huge    = 'overflow';
 
 if (system('git rev-parse --git-dir >/dev/null 2>&1') != 0) {
 	print "Not a Git repository, so I won't update the ChangeLog.\n";
@@ -51,6 +52,7 @@ while ($git_log =~ /$regex/gm) {
 	$prev_date = $commit{date};
 	$prev_name = $commit{name};
 	$prev_email = $commit{email};
+	$commit{message} =~ s/\s*Signed\-off\-by.*$//sgmx;
 
 	my @files = split(/\n/, $commit{files});
 	my @message = map { s/^ {4}//; $_ } split(/\n/, $commit{message});