[Nagios-users] Re: Large scale network monitoring limits with nagios

Noah Leaman noah at mac.com
Fri Mar 12 15:36:40 CET 2004


I would be very interested in those patches as well.

--  
Noah
On Mar 12, 2004, at 5:34 AM, Fredrik Wänglund wrote:

> I think there was an discussion on this sorting-topc some month ago. I  
> thought that resulted in some pathes that changed the code to  
> hash-based sorting...
> Anyone know where those patches are?
>
> /FredrikW
>
>
> michael at optusnet.com.au wrote:
>
>> Noah Leaman <noah at mac.com> writes:
>>> Hopes it's o.k. cross posting to both groups on this matter...
>>>
>>> Using the concept of one service per up/down trap for each network
>>> interface, I tested a little by creating a very simple set of nagios
>>> configs, but with about 8000 PASSIVE service checks and no active
>>> service checks. of course there was no problem in terms of scheduling
>>> issues, but the CGIs all crawled to a snails pace. In my setup  
>>> (nagios
>>> 1.2, Dual G4 first-gen xServe) it takes about 30 secs to display the
>>> Status Summary page.
>> Yes, this is what I'd expect. The problem is that nagios out of the
>> box has some terrible code in it. In particular, there's a lot of
>> places (including the display cgi's) that use O(n^2) algorithms.
>> Some of the time the problem is hidden; Upper level code will do  
>> "foreach (list) { action }" where 'action' calls a function
>> also does a linear search of the same list. oops.
>> Other times the problem is obvious: Code that adds elements
>> to the end of a singly linked list. By doing a linear
>> search from the beginning. For each item added. For 12,000
>> items. oops.
>> In our local version we create hash tables, and pre/post-sort lists to
>> work around the worst of the problems.
>> If you dig through the list archives you'll see the patches that
>> were sent in to fix it for 1.1.
>> That still leaves the other big problem with the passive service
>> checks. Believe it or not, sending a passive result makes nagios
>> fork()!! The parent process reads the check result, fork()s and then
>> resends the result again to the parent. Rather wild stuff. :)
>> Even better is that the child process has to wait around
>> for the parent to handle the send.
>> This is normally masked because the main event loop simply
>> doesn't check the named pipe very frequently, so normally
>> your external scripts will blow up with massive queues
>> waiting for nagios to read the pipe.
>> Nagios out of the box is simply not ready for reasonable
>> scale yet.
>> Michael.
>> Ps. Ok. I saved you some effort. I dug up the local patches:
>> (Note: I didn't write these)
>> * Check the named pipe frequently.
>> * Don't fork() too often when handling passive check results.
>> * Use hash tables and sorted lists to get rid of most of the
>>    O(n^2) places.
>> * Sleep only for a short time in the main loop.
>> * allow check for auth-smtp.
>> * fix a few bugs.
>> * introduces depedancy on glib.
>> diff -ru nagios-1.1-virgin/base/Makefile.in  
>> nagios-1.1/base/Makefile.in
>> --- nagios-1.1-virgin/base/Makefile.in	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/base/Makefile.in	Tue Oct  7 13:03:51 2003
>> @@ -10,9 +10,9 @@
>>  SRC_XDATA=../xdata
>>   CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE
>> +CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE `pkg-config glib --cflags`
>>  #CFLAGS=-O3 -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align  
>> -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs  
>> -DHAVE_CONFIG_H -DNSCORE
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `pkg-config glib --libs`
>>   prefix=@prefix@
>>  exec_prefix=@exec_prefix@
>> diff -ru nagios-1.1-virgin/cgi/Makefile.in nagios-1.1/cgi/Makefile.in
>> --- nagios-1.1-virgin/cgi/Makefile.in	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/cgi/Makefile.in	Tue Oct  7 13:03:51 2003
>> @@ -25,9 +25,9 @@
>>   CP=@CP@
>>  CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@ -DNSCGI
>> +CFLAGS=@CFLAGS@ @DEFS@ -DNSCGI `pkg-config glib --cflags`
>>  #CFLAGS=-O3 -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align  
>> -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs  
>> -DHAVE_CONFIG_H -DNSCGI
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `pkg-config glib --libs`
>>   CGIS=avail.cgi cmd.cgi config.cgi extinfo.cgi history.cgi  
>> notifications.cgi outages.cgi showlog.cgi status.cgi statuswml.cgi  
>> summary.cgi tac.cgi $(CGIEXTRAS)
>>  diff -ru nagios-1.1-virgin/common/common.h nagios-1.1/common/common.h
>> --- nagios-1.1-virgin/common/common.h	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/common/common.h	Tue Oct  7 13:03:51 2003
>> @@ -208,8 +208,12 @@
>>  #define	OK				0
>>  #define ERROR				-2	/* value was changed from -1 so as to not  
>> interfere with STATUS_UNKNOWN plugin result */
>>  +#ifndef TRUE
>>  #define TRUE				1
>> +#endif
>> +#ifndef FALSE
>>  #define FALSE				0
>> +#endif
>>    /****************** HOST CONFIG FILE READING OPTIONS  
>> ********************/
>> diff -ru nagios-1.1-virgin/common/config.h.in  
>> nagios-1.1/common/config.h.in
>> --- nagios-1.1-virgin/common/config.h.in	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/common/config.h.in	Tue Oct  7 13:03:51 2003
>> @@ -214,3 +214,7 @@
>>  #include <dirent.h>
>>  #endif
>>  +#define HAVE_GLIB_H 1
>> +#ifdef HAVE_GLIB_H
>> +#include <glib.h>
>> +#endif
>> diff -ru nagios-1.1-virgin/common/objects.c  
>> nagios-1.1/common/objects.c
>> --- nagios-1.1-virgin/common/objects.c	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/common/objects.c	Tue Oct  7 13:03:51 2003
>> @@ -59,7 +59,10 @@
>>  servicedependency       *servicedependency_list=NULL;
>>  hostdependency          *hostdependency_list=NULL;
>>  hostescalation          *hostescalation_list=NULL;
>> +GTree			*service_tree = NULL;
>> +GHashTable	*host_hash = NULL;
>>  +int service_list_add(char *key, service *v, void *data);
>>     
>> /******************************************************************/
>> @@ -99,6 +102,8 @@
>>  	printf("read_object_config_data() end\n");
>>  #endif
>>  +        g_tree_traverse(service_tree,  
>> (GTraverseFunc)service_list_add, G_IN_ORDER, NULL);
>> +
>>  	return result;
>>          }
>>  @@ -107,6 +112,13 @@
>>  /**************** OBJECT ADDITION FUNCTIONS ***********************/
>>  /******************************************************************/
>>  +int service_list_add(char *key, service *v, void *data)
>> +{
>> +        v->next = service_list;
>> +        service_list = v;
>> +        return 0;
>> +}
>> +                                                                      
>>                                                                        
>>                /* add a new timeperiod to the list in memory */
>> @@ -747,6 +759,16 @@
>>  	printf("\tNotification Interval:     
>> %d\n",new_host->notification_interval);
>>  	printf("\tNotification Time Period:  
>> %s\n",new_host->notification_period);
>>  #endif
>> +
>> +#ifdef HAVE_GLIB_H
>> +	/* Cache host in hash table */
>> +	if (!host_hash)
>> +		host_hash = g_hash_table_new(g_str_hash, g_str_equal);
>> +
>> +	if (host_hash)
>> +		g_hash_table_insert(host_hash, new_host->name, new_host);
>> +#endif
>> +
>>  #ifdef DEBUG0
>>  	printf("add_host() end\n");
>>  #endif
>> @@ -2173,40 +2195,7 @@
>>  	strcpy(new_service->perf_data,"");
>>   #endif
>> -	/* add new service to service list, sorted by host name then  
>> service description */
>> -	last_service=service_list;
>> -	for(temp_service=service_list;temp_service!=NULL; 
>> temp_service=temp_service->next){
>> -
>> -		if(strcmp(new_service->host_name,temp_service->host_name)<0){
>> -			new_service->next=temp_service;
>> -			if(temp_service==service_list)
>> -				service_list=new_service;
>> -			else
>> -				last_service->next=new_service;
>> -			break;
>> -		        }
>> -
>> -		else if(strcmp(new_service->host_name,temp_service->host_name)==0  
>> && strcmp(new_service->description,temp_service->description)<0){
>> -			new_service->next=temp_service;
>> -			if(temp_service==service_list)
>> -				service_list=new_service;
>> -			else
>> -				last_service->next=new_service;
>> -			break;
>> -		        }
>>  -		else
>> -			last_service=temp_service;
>> -	        }
>> -	if(service_list==NULL){
>> -		new_service->next=NULL;
>> -		service_list=new_service;
>> -	        }
>> -	else if(temp_service==NULL){
>> -		new_service->next=NULL;
>> -		last_service->next=new_service;
>> -	        }
>> -		
>>  #ifdef DEBUG1
>>  	printf("\tHost:                     %s\n",new_service->host_name);
>>  	printf("\tDescription:              %s\n",new_service->description);
>> @@ -2222,6 +2211,19 @@
>>  	printf("\tEvent Handler:             
>> %s\n",(new_service->event_handler==NULL)?"N/A":new_service- 
>> >event_handler);
>>  #endif
>>  +#ifdef HAVE_GLIB_H
>> +	/* Cache service in tree */
>> +	if (!service_tree)
>> +		service_tree = g_tree_new((GCompareFunc)strcmp);
>> +
>> +	if (service_tree)
>> +	{
>> +		char *key = calloc(strlen(new_service->host_name) +  
>> strlen(new_service->description) + 2, 1);
>> +		sprintf(key, "%s-%s", new_service->host_name,  
>> new_service->description);
>> +		g_tree_insert(service_tree, key, new_service);
>> +	}
>> +#endif
>> +
>>  #ifdef DEBUG0
>>  	printf("add_service() end\n");
>>  #endif
>> @@ -3226,6 +3228,13 @@
>>  	if(name==NULL)
>>  		return NULL;
>>  +#ifdef HAVE_GLIB_H
>> +	/* Lookup host in the hash */
>> +	if (host_hash)
>> +		return (host *)g_hash_table_lookup(host_hash, name);
>> +#endif
>> +
>> +
>>  	if(hst==NULL)
>>  		temp_host=host_list;
>>  	else
>> @@ -3500,6 +3509,18 @@
>>  	if(host_name==NULL || svc_desc==NULL)
>>  		return NULL;
>>  +#ifdef HAVE_GLIB_H
>> +	/* Lookup service in the tree */
>> +	if (service_tree)
>> +	{
>> +		char *key = calloc(strlen(host_name) + strlen(svc_desc) + 2, 1);
>> +		sprintf(key, "%s-%s", host_name, svc_desc);
>> +		temp_service = (service *)g_tree_lookup(service_tree, key);
>> +		free(key);
>> +		return temp_service;
>> +	}
>> +#endif
>> +
>>  	if(svcptr==NULL)
>>  		temp_service=service_list;
>>  	else
>> diff -ru nagios-1.1-virgin/common/statusdata.c  
>> nagios-1.1/common/statusdata.c
>> --- nagios-1.1-virgin/common/statusdata.c	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/common/statusdata.c	Tue Oct  7 13:04:12 2003
>> @@ -51,6 +51,7 @@
>>  #ifdef NSCGI
>>  hoststatus      *hoststatus_list=NULL;
>>  servicestatus   *servicestatus_list=NULL;
>> +GTree 		*servicestatus_tree=NULL;
>>   time_t program_start;
>>  int daemon_mode;
>> @@ -320,6 +321,7 @@
>>  /******************************************************************/
>>   +int servicestatus_list_add(servicestatus *key, void *v, void  
>> *data);
>>  /* reads in all status data */
>>  int read_status_data(char *config_file,int options){
>>  	int result=OK;
>> @@ -332,6 +334,7 @@
>>  	result=xsddb_read_status_data(config_file,options);
>>  #endif
>>  +	g_tree_traverse(servicestatus_tree,  
>> (GTraverseFunc)servicestatus_list_add, G_IN_ORDER, NULL);
>>  	return result;
>>          }
>>  @@ -341,6 +344,12 @@
>>  /********************** ADDITION FUNCTIONS ************************/
>>  /******************************************************************/
>>  +int servicestatus_list_add(servicestatus *key, void *v, void *data)
>> +{
>> +	key->next = servicestatus_list;
>> +	servicestatus_list = key;
>> +	return 0;
>> +}
>>   /* sets program status variables */
>>  int add_program_status(time_t _program_start, int _nagios_pid, int  
>> _daemon_mode, time_t _last_command_check, time_t _last_log_rotation,  
>> int _enable_notifications,int _execute_service_checks,int  
>> _accept_passive_service_checks,int _enable_event_handlers,int  
>> _obsess_over_services, int _enable_flap_detection, int  
>> _enable_failure_prediction, int _process_performance_data){
>> @@ -534,6 +543,16 @@
>>  	return OK;
>>          }
>>  +int servicestatus_cmp(servicestatus *a, servicestatus *b)
>> +{
>> +	int c;
>> +
>> +	c = strcmp(b->host_name, a->host_name);
>> +	if (c)
>> +		return c;
>> +
>> +	return strcmp(b->description, a->description);
>> +}
>>   /* adds a service status entry to the list in memory */
>>  int add_service_status(char *host_name,char *svc_description,char  
>> *status_string,time_t last_update,int current_attempt,int  
>> max_attempts,int state_type,time_t last_check,time_t next_check,int  
>> check_type,int checks_enabled,int accept_passive_checks,int  
>> event_handler_enabled,time_t last_state_change,int  
>> problem_has_been_acknowledged,char *last_hard_state_string,unsigned  
>> long time_ok,unsigned long time_warning,unsigned long  
>> time_unknown,unsigned long time_critical,time_t last_notification,int  
>> current_notification_number,int notifications_enabled, int latency,  
>> int execution_time, int flap_detection_enabled, int is_flapping,  
>> double percent_state_change, int scheduled_downtime_depth, int  
>> failure_prediction_enabled, int process_performance_data, int  
>> obsess_over_service, char *plugin_output){
>> @@ -543,6 +562,8 @@
>>  	int status;
>>  	int last_hard_state;
>>  +	if (!servicestatus_tree)
>> +		servicestatus_tree = g_tree_new( (GCompareFunc) servicestatus_cmp);
>>   	/* make sure we have what we need */
>>  	if(host_name==NULL)
>> @@ -724,41 +745,7 @@
>>  	/* scheduled downtime depth */
>>  	new_svcstatus->scheduled_downtime_depth=scheduled_downtime_depth;
>>  -
>> -	/* add new service status to list, sorted by host name then  
>> description */
>> -	last_svcstatus=servicestatus_list;
>> -	for(temp_svcstatus=servicestatus_list;temp_svcstatus!=NULL; 
>> temp_svcstatus=temp_svcstatus->next){
>> -
>> -		if(strcmp(new_svcstatus->host_name,temp_svcstatus->host_name)<0){
>> -			new_svcstatus->next=temp_svcstatus;
>> -			if(temp_svcstatus==servicestatus_list)
>> -				servicestatus_list=new_svcstatus;
>> -			else
>> -				last_svcstatus->next=new_svcstatus;
>> -			break;
>> -		        }
>> -
>> -		else  
>> if(strcmp(new_svcstatus->host_name,temp_svcstatus->host_name)==0 &&  
>> strcmp(new_svcstatus->description,temp_svcstatus->description)<0){
>> -			new_svcstatus->next=temp_svcstatus;
>> -			if(temp_svcstatus==servicestatus_list)
>> -				servicestatus_list=new_svcstatus;
>> -			else
>> -				last_svcstatus->next=new_svcstatus;
>> -			break;
>> -		        }
>> -
>> -		else
>> -			last_svcstatus=temp_svcstatus;
>> -	        }
>> -	if(servicestatus_list==NULL){
>> -		new_svcstatus->next=NULL;
>> -		servicestatus_list=new_svcstatus;
>> -	        }
>> -	else if(temp_svcstatus==NULL){
>> -		new_svcstatus->next=NULL;
>> -		last_svcstatus->next=new_svcstatus;
>> -	        }
>> -
>> +	g_tree_insert(servicestatus_tree, new_svcstatus, new_svcstatus);
>>   	return OK;
>>          }
>> diff -ru nagios-1.1-virgin/contrib/Makefile.in  
>> nagios-1.1/contrib/Makefile.in
>> --- nagios-1.1-virgin/contrib/Makefile.in	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/contrib/Makefile.in	Tue Oct  7 13:03:51 2003
>> @@ -5,8 +5,8 @@
>>  ###############################
>>   CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +CFLAGS=@CFLAGS@ @DEFS@ `pkg-config glib --cflags`
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `pkg-config glib --libs`
>>   # Source code directories
>>  SRC_COMMON=../common
>> diff -ru nagios-1.1-virgin/html/Makefile.in  
>> nagios-1.1/html/Makefile.in
>> --- nagios-1.1-virgin/html/Makefile.in	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/html/Makefile.in	Tue Oct  7 13:03:51 2003
>> @@ -1,6 +1,6 @@
>>  CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +CFLAGS=@CFLAGS@ @DEFS@ `pkg-config glib --cflags`
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `pkg-config glib --libs`
>>   prefix=@prefix@
>>  exec_prefix=@exec_prefix@
>> diff -ru nagios-1.1-virgin/cgi/status.c nagios-1.1/cgi/status.c
>> --- nagios-1.1-virgin/cgi/status.c	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/cgi/status.c	Tue Oct  7 12:29:00 2003
>> @@ -1151,6 +1151,7 @@
>>  	printf("<TH CLASS='status'>Attempt <A  
>> HREF='%s&sorttype=%d&sortoption=%d'><IMG SRC='%s%s' BORDER=0  
>> ALT='Sort by current attempt (ascending)'></A><A  
>> HREF='%s&sorttype=%d&sortoption=%d'><IMG SRC='%s%s' BORDER=0  
>> ALT='Sort by current attempt  
>> (descending)'></A></ 
>> TH>",temp_url,SORT_ASCENDING,SORT_CURRENTATTEMPT,url_images_path,UP_AR 
>> ROW_ICON,temp_url,SORT_DESCENDING,SORT_CURRENTATTEMPT,url_images_path, 
>> DOWN_ARROW_ICON);
>>   	printf("<TH CLASS='status'>Status Information</TH>\n");
>> +	printf("<TH CLASS='status'>Ack</TH>\n");
>>  	printf("</TR>\n");
>>   @@ -1499,6 +1500,15 @@
>>  			printf("<TD CLASS='status%s'  
>> nowrap>%s</TD>\n",status_bg_class,state_duration);
>>  			printf("<TD  
>> CLASS='status%s'>%d/%d</TD>\n",status_bg_class,temp_status- 
>> >current_attempt,temp_status->max_attempts);
>>  			printf("<TD  
>> CLASS='status%s'>%s </TD>\n",status_bg_class,temp_status- 
>> >information);
>> +			if (temp_status->status==SERVICE_OK)
>> +			{
>> +				printf("<TD CLASS='status%s'> </TD>\n",status_bg_class);
>> +			}
>> +			else
>> +			{
>> +				printf("<TD CLASS='status%s'><A HREF='%s?cmd_typ=34&host=%s",  
>> status_bg_class, COMMAND_CGI, url_encode(temp_status->host_name));
>> +				printf("&service=%s'>Ack</A></TD>\n",  
>> url_encode(temp_status->description));
>> +			}
>>   			printf("</TR>\n");
>>  diff -u -b -B -r1.1.1.1 Makefile.in
>> --- base/Makefile.in	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ base/Makefile.in	29 Jul 2003 08:22:54 -0000
>> @@ -10,9 +10,9 @@
>>  SRC_XDATA=../xdata
>>   CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE
>> +CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE `glib-config --cflags`
>>  #CFLAGS=-O3 -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align  
>> -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs  
>> -DHAVE_CONFIG_H -DNSCORE
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `glib-config --libs`
>>   prefix=@prefix@
>>  exec_prefix=@exec_prefix@
>> diff -u -b -B -r1.1.1.1 Makefile.in
>> --- cgi/Makefile.in	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ cgi/Makefile.in	29 Jul 2003 08:22:54 -0000
>> @@ -25,9 +25,9 @@
>>   CP=@CP@
>>  CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@ -DNSCGI
>> +CFLAGS=@CFLAGS@ @DEFS@ -DNSCGI `glib-config --cflags`
>>  #CFLAGS=-O3 -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align  
>> -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs  
>> -DHAVE_CONFIG_H -DNSCGI
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `glib-config --libs`
>>   CGIS=avail.cgi cmd.cgi config.cgi extinfo.cgi history.cgi  
>> notifications.cgi outages.cgi showlog.cgi status.cgi statuswml.cgi  
>> summary.cgi tac.cgi $(CGIEXTRAS)
>>  diff -u -b -B -r1.1.1.2 common.h
>> --- common/common.h	23 Jun 2003 01:57:24 -0000	1.1.1.2
>> +++ common/common.h	29 Jul 2003 08:22:54 -0000
>> @@ -208,8 +208,12 @@
>>  #define	OK				0
>>  #define ERROR				-2	/* value was changed from -1 so as to not  
>> interfere with STATUS_UNKNOWN plugin result */
>>  +#ifndef TRUE
>>  #define TRUE				1
>> +#endif
>> +#ifndef FALSE
>>  #define FALSE				0
>> +#endif
>>    /****************** HOST CONFIG FILE READING OPTIONS  
>> ********************/
>> diff -u -b -B -r1.1.1.1 config.h.in
>> --- common/config.h.in	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ common/config.h.in	29 Jul 2003 08:22:54 -0000
>> @@ -214,3 +214,7 @@
>>  #include <dirent.h>
>>  #endif
>>  +#define HAVE_GLIB_H 1
>> +#ifdef HAVE_GLIB_H
>> +#include <glib.h>
>> +#endif
>> diff -u -b -B -r1.1.1.1 objects.c
>> --- common/objects.c	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ common/objects.c	29 Jul 2003 08:22:54 -0000
>> @@ -59,6 +59,7 @@
>>  servicedependency       *servicedependency_list=NULL;
>>  hostdependency          *hostdependency_list=NULL;
>>  hostescalation          *hostescalation_list=NULL;
>> +GHashTable	*service_hash = NULL;
>>    @@ -2222,6 +2223,19 @@
>>  	printf("\tEvent Handler:             
>> %s\n",(new_service->event_handler==NULL)?"N/A":new_service- 
>> >event_handler);
>>  #endif
>>  +#ifdef HAVE_GLIB_H
>> +	/* Cache service in hash table */
>> +	if (!service_hash)
>> +		service_hash = g_hash_table_new(g_str_hash, g_str_equal);
>> +
>> +	if (service_hash)
>> +	{
>> +		char *key = calloc(strlen(new_service->host_name) +  
>> strlen(new_service->description) + 2, 1);
>> +		sprintf(key, "%s-%s", new_service->host_name,  
>> new_service->description);
>> +		g_hash_table_insert(service_hash, key, new_service);
>> +	}
>> +#endif
>> +
>>  #ifdef DEBUG0
>>  	printf("add_service() end\n");
>>  #endif
>> @@ -3500,6 +3514,18 @@
>>  	if(host_name==NULL || svc_desc==NULL)
>>  		return NULL;
>>  +#ifdef HAVE_GLIB_H
>> +	/* Lookup service in the hash */
>> +	if (service_hash)
>> +	{
>> +		char *key = calloc(strlen(host_name) + strlen(svc_desc) + 2, 1);
>> +		sprintf(key, "%s-%s", host_name, svc_desc);
>> +		temp_service = (service *)g_hash_table_lookup(service_hash, key);
>> +		free(key);
>> +		return temp_service;
>> +	}
>> +#endif
>> +
>>  	if(svcptr==NULL)
>>  		temp_service=service_list;
>>  	else
>> diff -u -b -B -r1.1.1.2 Makefile.in
>> --- contrib/Makefile.in	23 Jun 2003 01:57:24 -0000	1.1.1.2
>> +++ contrib/Makefile.in	29 Jul 2003 08:22:54 -0000
>> @@ -5,8 +5,8 @@
>>  ###############################
>>   CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +CFLAGS=@CFLAGS@ @DEFS@ `glib-config --cflags`
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `glib-config --libs`
>>   # Source code directories
>>  SRC_COMMON=../common
>> diff -u -b -B -r1.1.1.1 Makefile.in
>> --- html/Makefile.in	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ html/Makefile.in	29 Jul 2003 08:22:54 -0000
>> @@ -1,6 +1,6 @@
>>  CC=@CC@
>> -CFLAGS=@CFLAGS@ @DEFS@
>> -LDFLAGS=@LDFLAGS@ @LIBS@
>> +CFLAGS=@CFLAGS@ @DEFS@ `glib-config --cflags`
>> +LDFLAGS=@LDFLAGS@ @LIBS@ `glib-config --libs`
>>   prefix=@prefix@
>>  exec_prefix=@exec_prefix@
>> diff -ru nagios-1.1-virgin/cgi/status.c nagios-1.1/cgi/status.c
>> --- nagios-1.1-virgin/cgi/status.c	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/cgi/status.c	Wed Nov 26 18:01:16 2003
>> @@ -1293,9 +1293,15 @@
>>  				strncpy(status,"CRITICAL",sizeof(status));
>>  				status_class="CRITICAL";
>>  				if(temp_status->problem_has_been_acknowledged==TRUE)
>> +				{
>>  					status_bg_class="BGCRITICALACK";
>> +					status_class="BGCRITICALACK";
>> +				}
>>  				else if(temp_status->scheduled_downtime_depth>0)
>> +				{
>>  					status_bg_class="BGCRITICALSCHED";
>> +					status_class="BGCRITICALSCHED";
>> +				}
>>  				else
>>  					status_bg_class="BGCRITICAL";
>>  		                }
>> diff -ur nagios-1.1-virgin/base/nagios.c nagios-1.1/base/nagios.c
>> --- nagios-1.1-virgin/base/nagios.c	Thu Jul 10 08:30:10 2003
>> +++ nagios-1.1/base/nagios.c	Thu Jul 10 08:32:20 2003
>> @@ -51,6 +51,8 @@
>>  #include <getopt.h>
>>  #endif
>>  +#include <time.h>
>> +
>>  /******** BEGIN EMBEDDED PERL INTERPRETER DECLARATIONS ********/
>>   #ifdef EMBEDDEDPERL @@ -1497,6 +1499,8 @@
>>  		printf("Current/Max Outstanding Checks:  
>> %d/ 
>> %d\n",currently_running_service_checks,max_parallel_service_checks);
>>  #endif
>>  +		check_for_external_commands();
>> +
>>  		/* handle high priority events */
>>  		if(event_list_high!=NULL &&  
>> (current_time>=event_list_high->run_time)){
>>  @@ -1594,8 +1598,13 @@
>>  			        }
>>   			/* wait a second so we don't hog the CPU... */
>> -			else
>> -				sleep((unsigned int)sleep_time);
>> +			else {
>> +				struct timespec t;
>> +				t.tv_sec = 0;
>> +				t.tv_nsec = 1000 * 1000 * 50;
>> +				nanosleep(&t, NULL);
>> +				//check_for_external_commands();
>> +				}
>>  		        }
>>   		/* we don't have anything to do at this moment in time */
>> @@ -1606,7 +1615,12 @@
>>  				check_for_external_commands();
>>   			/* wait a second so we don't hog the CPU... */
>> -			sleep((unsigned int)sleep_time);
>> +
>> +			{ struct timespec t;
>> +			t.tv_sec = 0;
>> +			t.tv_nsec = 1000 * 1000 * 50;
>> +			nanosleep(&t, NULL); }
>> +
>>  		        }
>>  	        }
>>  --- commands.c.old	Sat Aug  2 14:13:23 2003
>> +++ nagios-1.1/base/commands.c	Sat Aug  2 14:13:53 2003
>> @@ -347,8 +347,19 @@
>>    	/**** PROCESS ALL PASSIVE CHECK RESULTS AT ONE TIME ****/
>> -	if(passive_check_result_list!=NULL)
>> -		process_passive_service_checks();
>> +        {
>> +                static unsigned int last_checked = 0;
>> +                unsigned int t;
>> +                                                                      
>>                                                   +                    
>>      /* Don't process more frequently than once every 5 seconds. */
>> +                        /* This does a fork!!! */
>> +                time(&t);
>> +                if(passive_check_result_list!=NULL && ((t -  
>> last_checked) > 5) ) {
>> +                        process_passive_service_checks();
>> +                        last_checked = t;
>> +                }
>> +        }
>> +
>>    #ifdef DEBUG0
>> --- commands.c.old	Sat Aug  2 15:37:31 2003
>> +++ nagios-1.1/base/commands.c	Sat Aug  2 15:44:36 2003
>> @@ -63,7 +63,7 @@
>>   extern FILE     *command_file_fp;
>>  -passive_check_result    *passive_check_result_list;
>> +passive_check_result    *passive_check_result_list = NULL;
>>   int             flush_pending_commands=FALSE;
>>  @@ -96,9 +96,6 @@
>>  	/* update the status log with new program information */
>>  	update_program_status(FALSE);
>>  -	/* reset passive check result list pointer */
>> -	passive_check_result_list=NULL;
>> -
>>  	/* reset flush flag */
>>  	flush_pending_commands=FALSE;
>>  @@ -1279,13 +1276,9 @@
>>   	new_pcr->next=NULL;
>>  -	/* add the passive check result to the end of the list in memory */
>> -	if(passive_check_result_list==NULL)
>> -		passive_check_result_list=new_pcr;
>> -	else{
>> -		for(temp_pcr=passive_check_result_list;temp_pcr->next!=NULL; 
>> temp_pcr=temp_pcr->next);
>> -		temp_pcr->next=new_pcr;
>> -	        }
>> +	/* add the passive check result to the head of the list in memory */
>> +	new_pcr->next = passive_check_result_list;
>> +	passive_check_result_list = new_pcr;
>>   #ifdef DEBUG0
>>  	printf("cmd_process_service_check_result() end\n");
>> @@ -2845,6 +2838,17 @@
>>   		/* the grandchild process should submit the service check  
>> result... */
>>  		if(pid==0){
>> +			passive_check_result *t, *t1;
>> +			/* Reverse passive list to correct the reverse that happened in  
>> collection. */
>> +
>> +			t = passive_check_result_list;
>> +			passive_check_result_list = NULL;
>> +			while (t) {
>> +				t1 = t->next;
>> +				t->next = passive_check_result_list;
>> +				passive_check_result_list = t;
>> +				t = t1;
>> +			}
>>   			/* write all service checks to the IPC pipe for later processing  
>> by the grandparent */
>>   
>> 			for(temp_pcr=passive_check_result_list;temp_pcr!=NULL; 
>> temp_pcr=temp_pcr->next){
>> Index: base/checks.c
>> ===================================================================
>> RCS file: /home/cvs/repos/nagios_source/base/checks.c,v
>> retrieving revision 1.1.1.1
>> diff -u -r1.1.1.1 checks.c
>> --- base/checks.c	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ base/checks.c	7 Dec 2003 21:15:43 -0000
>> @@ -522,6 +522,7 @@
>>  	time_t current_time;
>>  	int first_check=FALSE;
>>  	int state_was_logged=FALSE;
>> +	int output_changed = FALSE;
>>  	char old_plugin_output[MAX_PLUGINOUTPUT_LENGTH]="";
>>  	char temp_plugin_output[MAX_PLUGINOUTPUT_LENGTH]="";
>>  	char *temp_ptr;
>> @@ -617,6 +618,7 @@
>>  		dependency_result=DEPENDENCIES_OK;
>>  		first_check=FALSE;
>>  		state_was_logged=FALSE;
>> +		output_changed=FALSE;
>>  		strcpy(old_plugin_output,"");
>>  		strcpy(temp_plugin_output,"");
>>  @@ -705,6 +707,9 @@
>>  			/* grab the return code */
>>  			temp_service->current_state=queued_svc_msg.return_code;
>>  		        }
>> +		
>> +		if (strcmp(old_plugin_output,temp_service->plugin_output))
>> +			output_changed = TRUE;
>>   		/* get the host that this service runs on */
>>  		temp_host=find_host(temp_service->host_name,NULL);
>> @@ -835,7 +840,7 @@
>>  				state_was_logged=TRUE;
>>   				/* notify contacts about the service recovery */
>> -				service_notification(temp_service,NULL);
>> +				service_notification(temp_service,NULL,output_changed);
>>   				/* run the service event handler to handle the hard state  
>> change */
>>  				handle_service_event(temp_service,HARD_STATE);
>> @@ -1064,7 +1069,7 @@
>>  					check_pending_flex_service_downtime(temp_service);
>>   				/* (re)send notifications out about this service problem if the  
>> host is up (and was at last check also) and the dependencies were  
>> okay... */
>> -				service_notification(temp_service,NULL);
>> +				service_notification(temp_service,NULL,output_changed);
>>   				/* run the service event handler if we changed state from the  
>> last hard state or if this service is flagged as being volatile */
>>  				if(hard_state_change==TRUE || temp_service->is_volatile==TRUE)
>> @@ -1103,7 +1108,6 @@
>>   		/* if we're stalking this state type and state was not already  
>> logged AND the plugin output changed since last check, log it now..  
>> */
>>  		if(temp_service->state_type==HARD_STATE && state_change==FALSE &&  
>> state_was_logged==FALSE &&  
>> strcmp(old_plugin_output,temp_service->plugin_output)){
>> -
>>  			if((temp_service->current_state==STATE_OK &&  
>> temp_service->stalk_on_ok==TRUE))
>>  				log_service_event(temp_service,HARD_STATE);
>>  			
>> Index: base/commands.c
>> ===================================================================
>> RCS file: /home/cvs/repos/nagios_source/base/commands.c,v
>> retrieving revision 1.1.1.1
>> diff -u -r1.1.1.1 commands.c
>> --- base/commands.c	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ base/commands.c	7 Dec 2003 21:15:43 -0000
>> @@ -2277,7 +2277,7 @@
>>   	/* send out an acknowledgement notification */
>>  	if(notify==TRUE)
>> -		service_notification(svc,ack_data);
>> +		service_notification(svc,ack_data,0);
>>   	/* set the acknowledgement flag */
>>  	svc->problem_has_been_acknowledged=TRUE;
>> Index: base/flapping.c
>> ===================================================================
>> RCS file: /home/cvs/repos/nagios_source/base/flapping.c,v
>> retrieving revision 1.1.1.1
>> diff -u -r1.1.1.1 flapping.c
>> --- base/flapping.c	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ base/flapping.c	7 Dec 2003 21:15:43 -0000
>> @@ -321,7 +321,7 @@
>>   	/* should we send a recovery notification? */
>>  	if(svc->check_flapping_recovery_notification==TRUE &&  
>> svc->current_state==STATE_OK)
>> -		service_notification(svc,NULL);
>> +		service_notification(svc,NULL,0);
>>   	/* clear the recovery notification flag */
>>  	svc->check_flapping_recovery_notification=FALSE;
>> Index: base/nagios.h.in
>> ===================================================================
>> RCS file: /home/cvs/repos/nagios_source/base/nagios.h.in,v
>> retrieving revision 1.1.1.1
>> diff -u -r1.1.1.1 nagios.h.in
>> --- base/nagios.h.in	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ base/nagios.h.in	7 Dec 2003 21:15:44 -0000
>> @@ -367,10 +367,10 @@
>>    /**** Notification Functions ****/
>> -int check_service_notification_viability(service *,char *);		/*  
>> checks viability of notifying all contacts about a service */
>> +int check_service_notification_viability(service *,char *,int);		/*  
>> checks viability of notifying all contacts about a service */
>>  int is_valid_escalation_for_service_notification(service  
>> *,serviceescalation *);	/* checks if an escalation entry is valid for  
>> a particular service notification */
>>  int should_service_notification_be_escalated(service *);		/* checks  
>> if a service notification should be escalated */
>> -int service_notification(service *,char *);                         
>> 	/* notify all contacts about a service (problem or recovery) */
>> +int service_notification(service *,char *,int);                       
>>   	/* notify all contacts about a service (problem or recovery) */
>>  int check_contact_service_notification_viability(contact *, service  
>> *);	/* checks viability of notifying a contact about a service */   
>> int notify_contact_of_service(contact *,service *,char *);        	/*  
>> notify a single contact about a service */
>>  int check_host_notification_viability(host *,int,char *);		/* checks  
>> viability of notifying all contacts about a host */
>> Index: base/notifications.c
>> ===================================================================
>> RCS file: /home/cvs/repos/nagios_source/base/notifications.c,v
>> retrieving revision 1.1.1.1
>> diff -u -r1.1.1.1 notifications.c
>> --- base/notifications.c	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ base/notifications.c	7 Dec 2003 21:15:44 -0000
>> @@ -58,7 +58,7 @@
>>    /* notify contacts about a service problem or recovery */
>> -int service_notification(service *svc, char *ack_data){
>> +int service_notification(service *svc, char *ack_data, int  
>> output_changed) {
>>  	host *temp_host;
>>  	notification *temp_notification;
>>  	time_t current_time;
>> @@ -87,7 +87,7 @@
>>  	        }
>>   	/* check the viability of sending out a service notification */
>> -	if(check_service_notification_viability(svc,ack_data)==ERROR){
>> +	 
>> if(check_service_notification_viability(svc,ack_data,output_changed)== 
>> ERROR){
>>  #ifdef DEBUG4
>>  		printf("\tSending out a notification for this service is not  
>> viable at this time.\n");
>>  #endif
>> @@ -200,7 +200,7 @@
>>    /* checks the viability of sending out a service alert (top level  
>> filters) */
>> -int check_service_notification_viability(service *svc, char  
>> *ack_data){
>> +int check_service_notification_viability(service *svc, char  
>> *ack_data, int output_changed){
>>  	host *temp_host;
>>  	time_t current_time;
>>  	time_t timeperiod_start;
>> @@ -371,7 +371,12 @@
>>  	        }
>>   	/* don't notify if we haven't waited long enough since the last  
>> time (and the service is not marked as being volatile) */
>> -	if((current_time < svc->next_notification) &&  
>> svc->is_volatile==FALSE){
>> +	if((current_time < svc->next_notification) &&  
>> svc->is_volatile==FALSE &&
>> +		(!output_changed ||
>> +		 (svc->current_state==STATE_OK && !svc->stalk_on_ok) ||
>> +		 (svc->current_state==STATE_WARNING && !svc->stalk_on_warning) ||
>> +		 (svc->current_state==STATE_UNKNOWN && !svc->stalk_on_unknown) ||  
>> +		 (svc->current_state==STATE_CRITICAL && !svc->stalk_on_critical)  
>> )){
>>  #ifdef DEBUG4
>>  		printf("\tWe haven't waited long enough to re-notify contacts  
>> about this service!\n");
>>  		printf("\tNext valid notification time:  
>> %s",ctime(&svc->next_notification));
>> ? cgi/Makefile
>> ? cgi/authall.patch
>> ? cgi/avail.cgi
>> ? cgi/cgiutils.h
>> ? cgi/cmd.cgi
>> ? cgi/config.cgi
>> ? cgi/extinfo.cgi
>> ? cgi/histogram.cgi
>> ? cgi/history.cgi
>> ? cgi/notifications.cgi
>> ? cgi/outages.cgi
>> ? cgi/showlog.cgi
>> ? cgi/status.cgi
>> ? cgi/statusmap.cgi
>> ? cgi/statuswml.cgi
>> ? cgi/statuswrl.cgi
>> ? cgi/summary.cgi
>> ? cgi/tac.cgi
>> ? cgi/trends.cgi
>> Index: cgi/auth.c
>> ===================================================================
>> RCS file: /home/cvs/repos/nagios_source/cgi/auth.c,v
>> retrieving revision 1.1.1.1
>> diff -u -r1.1.1.1 auth.c
>> --- cgi/auth.c	23 Jun 2003 01:56:10 -0000	1.1.1.1
>> +++ cgi/auth.c	25 Feb 2004 00:35:29 -0000
>> @@ -198,9 +198,6 @@
>>  int is_authorized_for_host(host *hst, authdata *authinfo){
>>  	contact *temp_contact;
>>  -	if(hst==NULL)
>> -		return FALSE;
>> -
>>  	/* if we're not using authentication, fake it */
>>  	if(use_authentication==FALSE)
>>  		return TRUE;
>> @@ -213,6 +210,9 @@
>>  	if(is_authorized_for_all_hosts(authinfo)==TRUE)
>>  		return TRUE;
>>  +	if(hst==NULL)
>> +		return FALSE;
>> +
>>  	/* find the contact */
>>  	temp_contact=find_contact(authinfo->username,NULL);
>>  @@ -252,9 +252,6 @@
>>  	host *temp_host;
>>  	contact *temp_contact;
>>  -	if(svc==NULL)
>> -		return FALSE;
>> -
>>  	/* if we're not using authentication, fake it */
>>  	if(use_authentication==FALSE)
>>  		return TRUE;
>> @@ -266,6 +263,9 @@
>>  	/* if this user is authorized for all services, they are for this  
>> one... */
>>  	if(is_authorized_for_all_services(authinfo)==TRUE)
>>  		return TRUE;
>> +
>> +	if(svc==NULL)
>> +		return FALSE;
>>   	/* find the host */
>>  	temp_host=find_host(svc->host_name,NULL);
>> diff -ruN nagios-plugins-1.3.0.orig/plugins/check_smtp.c  
>> nagios-plugins-1.3.0/plugins/check_smtp.c
>> --- nagios-plugins-1.3.0.orig/plugins/check_smtp.c	2003-02-15  
>> 23:48:46.000000000 +1100
>> +++ nagios-plugins-1.3.0/plugins/check_smtp.c	2003-08-12  
>> 15:00:07.000000000 +1000
>> @@ -69,12 +69,77 @@
>>  char *server_address = NULL;
>>  char *server_expect = NULL;
>>  char *from_arg = " ";
>> +char *authtype = NULL;
>> +char *authuser = NULL;
>> +char *authpass = NULL;
>>  int warning_time = 0;
>>  int check_warning_time = FALSE;
>>  int critical_time = 0;
>>  int check_critical_time = FALSE;
>>  int verbose = FALSE;
>>  +/* encode64 routine from  
>> http://www.experts-exchange.com/Programming/Programming_Languages/C/ 
>> Q_20245582.html */
>> +
>> +#define BUFOVER             (-2)
>> +#define CHAR64(c)           (((c) < 0 || (c) > 127) ? -1 :  
>> index_64[(c)])
>> +static char     basis_64[] =
>> +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/???? 
>> ?????????????????????????????????????????????????????????????????????? 
>> ?????????????????????????????????????????????????????????????????";
>> +static char     index_64[128] = {
>> +  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
>> +  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
>> +  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
>> +  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
>> +  -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
>> +  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
>> +  -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
>> +  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
>> +};
>> +
>> +static int
>> +encode64(const char *_in, unsigned inlen, char *_out, unsigned  
>> outmax, unsigned *outlen)
>> +{
>> +
>> +  const unsigned char *in = (const unsigned char *) _in;
>> +  unsigned char  *out = (unsigned char *) _out;
>> +  unsigned char   oval;
>> +  char           *blah;
>> +  unsigned        olen;
>> +
>> +  olen = (inlen + 2) / 3 * 4;
>> +  if (outlen)
>> +      *outlen = olen;
>> +  if (outmax < olen)
>> +      return BUFOVER;
>> +
>> +  blah = (char *) out;
>> +  while (inlen >= 3)
>> +  {
>> +/* user provided max buffer size; make sure we don't go over it */
>> +      *out++ = basis_64[in[0] >> 2];
>> +      *out++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)];
>> +      *out++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
>> +      *out++ = basis_64[in[2] & 0x3f];
>> +      in += 3;
>> +      inlen -= 3;
>> +  }
>> +  if (inlen > 0)
>> +  {
>> +/* user provided max buffer size; make sure we don't go over it */
>> +      *out++ = basis_64[in[0] >> 2];
>> +      oval = (in[0] << 4) & 0x30;
>> +      if (inlen > 1)
>> +          oval |= in[1] >> 4;
>> +      *out++ = basis_64[oval];
>> +      *out++ = (inlen < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c];
>> +      *out++ = '=';
>> +  }
>> +
>> +  if (olen < outmax)
>> +      *out = '\0';
>> +
>> +  return OK;
>> +}
>> +
>>  int
>>  main (int argc, char **argv)
>>  {
>> @@ -83,6 +148,7 @@
>>  	char buffer[MAX_INPUT_BUFFER] = "";
>>  	char *from_str = NULL;
>>  	char *helocmd = NULL;
>> +	char *error_msg = NULL;
>>   	if (process_arguments (argc, argv) != OK)
>>  		usage ("Invalid command arguments supplied\n");
>> @@ -124,41 +190,134 @@
>>  		if (result == -1) {
>>  			printf ("recv() failed\n");
>>  			result = STATE_WARNING;
>> +		} else
>> +			result = STATE_OK;
>> +		
>> +		/* make sure we find the response we are looking for */
>> +		if (result == STATE_OK && !strstr (buffer, server_expect)) {
>> +			if (server_port == SMTP_PORT)
>> +				printf ("Invalid SMTP response received from host\n");
>> +			else
>> +				printf ("Invalid SMTP response received from host on port %d\n",
>> +								server_port);
>> +			result = STATE_WARNING;
>>  		}
>> -
>> -		else {
>> -
>> -			/* make sure we find the response we are looking for */
>> -			if (!strstr (buffer, server_expect)) {
>> -				if (server_port == SMTP_PORT)
>> -					printf ("Invalid SMTP response received from host\n");
>> -				else
>> -					printf ("Invalid SMTP response received from host on port %d\n",
>> -									server_port);
>> -				result = STATE_WARNING;
>> +		
>> +		if (result == STATE_OK && authtype != NULL) {
>> +			if (strcmp (authtype, "LOGIN") == 0) {
>> +				char abuf[MAX_INPUT_BUFFER];
>> +				unsigned alen;
>> +				int ret;
>> +				do {
>> +					if (authuser == NULL) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "no authuser specified";
>> +						break;
>> +					}
>> +					if (authpass == NULL) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "no authpass specified";
>> +						break;
>> +					}
>> +					send(sd, "AUTH LOGIN\r\n", strlen("AUTH LOGIN\r\n"), 0);
>> +					if (verbose == TRUE) {
>> +						printf ("sent AUTH LOGIN\n");
>> +					}
>> +					if ((ret = recv(sd, buffer, MAX_INPUT_BUFFER-1, 0)) == -1) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "recv() failed after AUTH LOGIN";
>> +						break;
>> +					}
>> +					buffer[ret] = 0;
>> +					if (verbose == TRUE) {
>> +						printf ("received %s\n", buffer);
>> +					}
>> +					if (strncmp (buffer, "334", 3) != 0) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "invalid response received after AUTH LOGIN";
>> +						break;
>> +					}
>> +					if (encode64 (authuser, strlen(authuser), abuf,  
>> MAX_INPUT_BUFFER, &alen) != OK) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "failed to base64-encode authuser";
>> +						break;
>> +					}
>> +					strcat (abuf, "\r\n");
>> +					send(sd, abuf, strlen(abuf), 0);
>> +					if (verbose == TRUE) {
>> +						printf ("sent %s\n", abuf);
>> +					}
>> +					if ((ret = recv(sd, buffer, MAX_INPUT_BUFFER-1, 0)) == -1) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "recv() failed after sending authuser";
>> +						break;
>> +					}
>> +					buffer[ret] = 0;
>> +					if (verbose == TRUE) {
>> +						printf ("received %s\n", buffer);
>> +					}
>> +					if (strncmp (buffer, "334", 3) != 0) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "invalid response received after authuser";
>> +						break;
>> +					}
>> +					if (encode64 (authpass, strlen(authpass), abuf,  
>> MAX_INPUT_BUFFER, &alen) != OK) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "failed to base64-encode authpass";
>> +						break;
>> +					}
>> +					strcat (abuf, "\r\n");
>> +					send(sd, abuf, strlen(abuf), 0);
>> +					if (verbose == TRUE) {
>> +						printf ("sent %s\n", abuf);
>> +					}
>> +					if ((ret = recv(sd, buffer, MAX_INPUT_BUFFER-1, 0)) == -1) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "recv() failed after sending authpass";
>> +						break;
>> +					}
>> +					buffer[ret] = 0;
>> +					if (verbose == TRUE) {
>> +						printf ("received %s\n", buffer);
>> +					}
>> +					if (strncmp (buffer, "235", 3) != 0) {
>> +						result = STATE_CRITICAL;
>> +						error_msg = "invalid response received after authpass";
>> +						break;
>> +					}
>> +					break;
>> +				} while (0);
>> +			} else {
>> +				result = STATE_CRITICAL;
>> +				error_msg = "only authtype LOGIN is supported";
>>  			}
>> +		}
>> +		
>> +		time (&end_time);
>>  -			else {
>> -
>> -				time (&end_time);
>> -
>> -				result = STATE_OK;
>> -
>> -				if (check_critical_time == TRUE
>> -						&& (end_time - start_time) > critical_time) result =
>> -						STATE_CRITICAL;
>> -				else if (check_warning_time == TRUE
>> -								 && (end_time - start_time) > warning_time) result =
>> -						STATE_WARNING;
>> -
>> -				if (verbose == TRUE)
>> -					printf ("SMTP %s - %d sec. response time, %s\n",
>> -									state_text (result), (int) (end_time - start_time), buffer);
>> -				else
>> -					printf ("SMTP %s - %d second response time\n", state_text  
>> (result),
>> -									(int) (end_time - start_time));
>> +		if (check_critical_time == TRUE
>> +				&& (end_time - start_time) > critical_time) result =
>> +				STATE_CRITICAL;
>> +		else if (check_warning_time == TRUE
>> +						 && (end_time - start_time) > warning_time) result =
>> +				STATE_WARNING;
>> +
>> +		if (verbose == TRUE)
>> +			if (error_msg == NULL) {
>> +				printf ("SMTP %s - %d sec. response time, %s\n",
>> +		        		state_text (result), (int) (end_time - start_time),  
>> buffer);
>> +			} else {
>> +				printf ("SMTP %s - %s, %d sec. response time, %s\n",
>> +		        		state_text (result), error_msg, (int) (end_time -  
>> start_time), buffer);
>> +			}
>> +		else
>> +			if (error_msg == NULL) {
>> +				printf ("SMTP %s - %d second response time\n",
>> +		        		state_text (result), (int) (end_time - start_time));
>> +			} else {
>> +				printf ("SMTP %s - %s, %d second response time\n",
>> +		        		state_text (result), error_msg, (int) (end_time -  
>> start_time));
>>  			}
>> -		}
>>   		/* close the connection */
>>  @@ -211,6 +370,9 @@
>>  		{"warning", required_argument, 0, 'w'},
>>  		{"port", required_argument, 0, 'p'},
>>  		{"from", required_argument, 0, 'f'},
>> +		{"authtype", required_argument, 0, 'A'},
>> +		{"authuser", required_argument, 0, 'U'},
>> +		{"authpass", required_argument, 0, 'P'},
>>  		{"verbose", no_argument, 0, 'v'},
>>  		{"version", no_argument, 0, 'V'},
>>  		{"help", no_argument, 0, 'h'},
>> @@ -233,10 +395,10 @@
>>  	while (1) {
>>  #ifdef HAVE_GETOPT_H
>>  		c =
>> -			getopt_long (argc, argv, "+hVvt:p:f:e:c:w:H:", long_options,
>> +			getopt_long (argc, argv, "+hVvt:p:f:e:c:w:H:A:U:P:", long_options,
>>  									 &option_index);
>>  #else
>> -		c = getopt (argc, argv, "+?hVvt:p:f:e:c:w:H:");
>> +		c = getopt (argc, argv, "+?hVvt:p:f:e:c:w:H:A:U:P:");
>>  #endif
>>  		if (c == -1 || c == EOF)
>>  			break;
>> @@ -261,6 +423,15 @@
>>  		case 'f':									/* from argument */
>>  			from_arg = optarg;
>>  			break;
>> +		case 'A':
>> +			authtype = optarg;
>> +			break;
>> +		case 'U':
>> +			authuser = optarg;
>> +			break;
>> +		case 'P':
>> +			authpass = optarg;
>> +			break;
>>  		case 'e':									/* server expect string on 220  */
>>  			server_expect = optarg;
>>  			break;
>> @@ -355,6 +526,12 @@
>>  		 "   String to expect in first line of server response (default:  
>> %s)\n"
>>  		 " -f, --from=STRING\n"
>>  		 "   from address to include in MAIL command (default NULL,  
>> Exchange2000 requires one)\n"
>> +		 " -A, --authtype=STRING\n"
>> +		 "   SMTP AUTH type to check (default none, only LOGIN  
>> supported)\n"
>> +		 " -U, --authuser=STRING\n"
>> +		 "   SMTP AUTH username\n"
>> +		 " -P, --authpass=STRING\n"
>> +		 "   SMTP AUTH password\n"
>>  		 " -w, --warning=INTEGER\n"
>>  		 "   Seconds necessary to result in a warning status\n"
>>  		 " -c, --critical=INTEGER\n"
>> @@ -379,7 +556,7 @@
>>  print_usage (void)
>>  {
>>  	printf
>> -		("Usage: %s -H host [-e expect] [-p port] [-f from addr] [-w warn]  
>> [-c crit] [-t timeout] [-v]\n"
>> +		("Usage: %s -H host [-e expect] [-p port] [-f from addr] [-A  
>> authtype -U authuser -P authpass] [-w warn] [-c crit] [-t timeout]  
>> [-v]\n"
>>  		 "       %s --help\n"
>>  		 "       %s --version\n", progname, progname, progname);
>>  }
>> --- /tmp/nagios-plugins-1.3.0/plugins/check_time.c	2003-02-15  
>> 23:48:46.000000000 +1100
>> +++ nagios-plugins-1.3.0/plugins/check_time.c	2003-06-06  
>> 10:43:32.000000000 +1000
>> @@ -61,7 +61,7 @@
>>  int check_critical_diff = FALSE;
>>  int server_port = TIME_PORT;
>>  char *server_address = NULL;
>> -
>> +int use_udp = FALSE;
>>   int process_arguments (int, char **);
>>  void print_usage (void);
>> @@ -85,7 +85,13 @@
>>  	time (&start_time);
>>   	/* try to connect to the host at the given port number */
>> -	if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) {
>> +	if (use_udp) {
>> +		result = my_udp_connect (server_address, server_port, &sd);
>> +	} else {
>> +		result = my_tcp_connect (server_address, server_port, &sd);
>> +	}
>> +
>> +	if (result != STATE_OK) {
>>  		if (check_critical_time == TRUE)
>>  			result = STATE_CRITICAL;
>>  		else if (check_warning_time == TRUE)
>> @@ -94,7 +100,21 @@
>>  			result = STATE_UNKNOWN;
>>  		terminate (result,
>>  		           "TIME UNKNOWN - could not connect to server %s, port  
>> %d\n",
>> -		           server_address, server_port);
>> +	        	   server_address, server_port);
>> +	}
>> +
>> +	if (use_udp) {
>> +		if (send (sd, "", 0, 0) < 0) {
>> +			if (check_critical_time == TRUE)
>> +				result = STATE_CRITICAL;
>> +			else if (check_warning_time == TRUE)
>> +				result = STATE_WARNING;
>> +			else
>> +				result = STATE_UNKNOWN;
>> +			terminate (result,
>> +			           "TIME UNKNOWN - could not send UDP request to server  
>> %s, port %d\n",
>> +	        		   server_address, server_port);
>> +		}
>>  	}
>>   	/* watch for the connection string */
>> @@ -170,6 +190,7 @@
>>  		{"timeout", required_argument, 0, 't'},
>>  		{"version", no_argument, 0, 'V'},
>>  		{"help", no_argument, 0, 'h'},
>> +		{"udp", no_argument, 0, 'u'},
>>  		{0, 0, 0, 0}
>>  	};
>>  #endif
>> @@ -193,10 +214,10 @@
>>  	while (1) {
>>  #ifdef HAVE_GETOPT_H
>>  		c =
>> -			getopt_long (argc, argv, "hVH:w:c:W:C:p:t:", long_options,
>> +			getopt_long (argc, argv, "hVH:w:c:W:C:p:t:u", long_options,
>>  									 &option_index);
>>  #else
>> -		c = getopt (argc, argv, "hVH:w:c:W:C:p:t:");
>> +		c = getopt (argc, argv, "hVH:w:c:W:C:p:t:u");
>>  #endif
>>   		if (c == -1 || c == EOF)
>> @@ -275,6 +296,9 @@
>>  				usage ("Timeout interval must be a nonnegative integer\n");
>>  			socket_timeout = atoi (optarg);
>>  			break;
>> +		case 'u':
>> +		/* udp */
>> +			use_udp = TRUE;
>>  		}
>>  	}
>>  @@ -338,6 +362,8 @@
>>  		 "    Seconds before connection times out (default: %d)\n"
>>  		 " -p, --port=INTEGER\n"
>>  		 "    Port number (default: %d)\n"
>> +		 " -u, --udp\n"
>> +		 "    Use UDP to connect, not TCP\n"
>>  		 " -h, --help\n"
>>  		 "    Print detailed help screen\n"
>>  		 " -V, --version\n"
>> --- nagios-plugins-1.3.0/plugins/check_udp.c	2003-02-19  
>> 09:24:35.000000000 +1100
>> +++ nagios-plugins-r1_3_0-200306050007/plugins/check_udp.c	2003-03-07  
>> 17:40:33.000000000 +1100
>> @@ -6,7 +6,7 @@
>>  * License: GPL
>>  * Copyright (c) 1999 Ethan Galstad (nagios at nagios.org)
>>  *
>> -* Last Modified: $Date: 2003/02/18 22:24:35 $
>> +* Last Modified: $Date: 2003/03/07 06:40:33 $
>>  *
>>  * Command line: CHECK_UDP <host_address> [-p port] [-s send] [-e  
>> expect] \
>>  *			   [-wt warn_time] [-ct crit_time] [-to to_sec]
>> @@ -173,7 +173,7 @@
>>  			print_help ();
>>  			exit (STATE_OK);
>>  		case 'V':									/* version */
>> -			print_revision (progname, "$Revision: 1.4 $");
>> +			print_revision (progname, "$Revision: 1.4.2.1 $");
>>  			exit (STATE_OK);
>>  		case 'v':									/* verbose mode */
>>  			verbose = TRUE;
>> @@ -220,9 +220,9 @@
>>  			usage ("Invalid host name/address\n");
>>  		server_address = argv[c++];
>>  	}
>> -	else {
>> +
>> +	if (server_address == NULL)
>>  		usage ("Host name was not supplied\n");
>> -	}
>>   	return c;
>>  }
>> @@ -246,7 +246,7 @@
>>  void
>>  print_help (void)
>>  {
>> -	print_revision (progname, "$Revision: 1.4 $");
>> +	print_revision (progname, "$Revision: 1.4.2.1 $");
>>  	printf
>>  		("Copyright (c) 1999 Ethan Galstad (nagios at nagios.org)\n\n"
>>  		 "This plugin tests an UDP connection with the specified  
>> host.\n\n");
>> -------------------------------------------------------
>> This SF.Net email is sponsored by: IBM Linux Tutorials
>> Free Linux tutorial presented by Daniel Robbins, President and CEO of
>> GenToo technologies. Learn everything from fundamentals to system
>> administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
>> _______________________________________________
>> Nagios-devel mailing list
>> Nagios-devel at lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/nagios-devel
>
>
>
> -------------------------------------------------------
> This SF.Net email is sponsored by: IBM Linux Tutorials
> Free Linux tutorial presented by Daniel Robbins, President and CEO of
> GenToo technologies. Learn everything from fundamentals to system
> administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
> _______________________________________________
> Nagios-users mailing list
> Nagios-users at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/nagios-users
> ::: Please include Nagios version, plugin version (-v) and OS when  
> reporting any issue. ::: Messages without supporting info will risk  
> being sent to /dev/null



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&op=click




More information about the Users mailing list