/***************************************************************************** * * STATUSDATA.C - External status data for Nagios CGIs * * Copyright (c) 2000-2005 Ethan Galstad (nagios@nagios.org) * Last Modified: 07-25-2005 * * License: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************************************/ /*********** COMMON HEADER FILES ***********/ #include "../include/config.h" #include "../include/common.h" #include "../include/objects.h" #include "../include/statusdata.h" #ifdef NSCORE #include "../include/nagios.h" #include "../include/broker.h" #endif #ifdef NSCGI #include "../include/cgiutils.h" #endif /**** IMPLEMENTATION SPECIFIC HEADER FILES ****/ #ifdef USE_XSDDEFAULT #include "../xdata/xsddefault.h" /* default routines */ #endif #ifdef NSCORE extern int aggregate_status_updates; #endif #ifdef NSCGI hoststatus *hoststatus_list=NULL; hoststatus *hoststatus_list_tail=NULL; servicestatus *servicestatus_list=NULL; servicestatus *servicestatus_list_tail=NULL; hoststatus **hoststatus_hashlist=NULL; servicestatus **servicestatus_hashlist=NULL; #endif #ifdef NSCORE /******************************************************************/ /****************** TOP-LEVEL OUTPUT FUNCTIONS ********************/ /******************************************************************/ /* initializes status data at program start */ int initialize_status_data(char *config_file){ int result=OK; /**** IMPLEMENTATION-SPECIFIC CALLS ****/ #ifdef USE_XSDDEFAULT result=xsddefault_initialize_status_data(config_file); #endif return result; } /* update all status data (aggregated dump) */ int update_all_status_data(void){ int result; #ifdef USE_EVENT_BROKER /* send data to event broker */ broker_aggregated_status_data(NEBTYPE_AGGREGATEDSTATUS_STARTDUMP,NEBFLAG_NONE,NEBATTR_NONE,NULL); #endif /**** IMPLEMENTATION-SPECIFIC CALLS ****/ #ifdef USE_XSDDEFAULT result=xsddefault_save_status_data(); #endif #ifdef USE_EVENT_BROKER /* send data to event broker */ broker_aggregated_status_data(NEBTYPE_AGGREGATEDSTATUS_ENDDUMP,NEBFLAG_NONE,NEBATTR_NONE,NULL); #endif if(result!=OK) return ERROR; return OK; } /* cleans up status data before program termination */ int cleanup_status_data(char *config_file,int delete_status_data){ int result=OK; /**** IMPLEMENTATION-SPECIFIC CALLS ****/ #ifdef USE_XSDDEFAULT result=xsddefault_cleanup_status_data(config_file,delete_status_data); #endif return result; } /* updates program status info */ int update_program_status(int aggregated_dump){ #ifdef USE_EVENT_BROKER /* send data to event broker (non-aggregated dumps only) */ if(aggregated_dump==FALSE) broker_program_status(NEBTYPE_PROGRAMSTATUS_UPDATE,NEBFLAG_NONE,NEBATTR_NONE,NULL); #endif /* currently a noop if aggregated updates is TRUE */ /* update all status data if we're not aggregating updates */ if(aggregate_status_updates==FALSE) update_all_status_data(); return OK; } /* updates host status info */ int update_host_status(host *hst,int aggregated_dump){ #ifdef USE_EVENT_BROKER /* send data to event broker (non-aggregated dumps only) */ if(aggregated_dump==FALSE) broker_host_status(NEBTYPE_HOSTSTATUS_UPDATE,NEBFLAG_NONE,NEBATTR_NONE,hst,NULL); #endif /* currently a noop if aggregated updates is TRUE */ /* update all status data if we're not aggregating updates */ if(aggregate_status_updates==FALSE) update_all_status_data(); return OK; } /* updates service status info */ int update_service_status(service *svc,int aggregated_dump){ #ifdef USE_EVENT_BROKER /* send data to event broker (non-aggregated dumps only) */ if(aggregated_dump==FALSE) broker_service_status(NEBTYPE_SERVICESTATUS_UPDATE,NEBFLAG_NONE,NEBATTR_NONE,svc,NULL); #endif /* currently a noop if aggregated updates is TRUE */ /* update all status data if we're not aggregating updates */ if(aggregate_status_updates==FALSE) update_all_status_data(); return OK; } #endif #ifdef NSCGI /******************************************************************/ /******************* TOP-LEVEL INPUT FUNCTIONS ********************/ /******************************************************************/ /* reads in all status data */ int read_status_data(char *config_file,int options){ int result=OK; /**** IMPLEMENTATION-SPECIFIC CALLS ****/ #ifdef USE_XSDDEFAULT result=xsddefault_read_status_data(config_file,options); #endif #ifdef USE_XSDDB result=xsddb_read_status_data(config_file,options); #endif return result; } /******************************************************************/ /****************** CHAINED HASH FUNCTIONS ************************/ /******************************************************************/ /* adds hoststatus to hash list in memory */ int add_hoststatus_to_hashlist(hoststatus *new_hoststatus){ hoststatus *temp_hoststatus, *lastpointer; int hashslot; /* initialize hash list */ if(hoststatus_hashlist==NULL){ int i; hoststatus_hashlist=(hoststatus **)malloc(sizeof(hoststatus *)*HOSTSTATUS_HASHSLOTS); if(hoststatus_hashlist==NULL) return 0; for(i=0;ihost_name,HOSTSTATUS_HASHSLOTS); lastpointer=NULL; for(temp_hoststatus=hoststatus_hashlist[hashslot];temp_hoststatus && compare_hashdata1(temp_hoststatus->host_name,new_hoststatus->host_name)<0;temp_hoststatus=temp_hoststatus->nexthash) lastpointer=temp_hoststatus; if(!temp_hoststatus || (compare_hashdata1(temp_hoststatus->host_name,new_hoststatus->host_name)!=0)){ if(lastpointer) lastpointer->nexthash=new_hoststatus; else hoststatus_hashlist[hashslot]=new_hoststatus; new_hoststatus->nexthash=temp_hoststatus; return 1; } /* else already exists */ return 0; } int add_servicestatus_to_hashlist(servicestatus *new_servicestatus){ servicestatus *temp_servicestatus, *lastpointer; int hashslot; /* initialize hash list */ if(servicestatus_hashlist==NULL){ int i; servicestatus_hashlist=(servicestatus **)malloc(sizeof(servicestatus *)*SERVICESTATUS_HASHSLOTS); if(servicestatus_hashlist==NULL) return 0; for(i=0;i< SERVICESTATUS_HASHSLOTS;i++) servicestatus_hashlist[i]=NULL; } if(!new_servicestatus) return 0; hashslot=hashfunc2(new_servicestatus->host_name,new_servicestatus->description,SERVICESTATUS_HASHSLOTS); lastpointer=NULL; for(temp_servicestatus=servicestatus_hashlist[hashslot];temp_servicestatus && compare_hashdata2(temp_servicestatus->host_name,temp_servicestatus->description,new_servicestatus->host_name,new_servicestatus->description)<0;temp_servicestatus=temp_servicestatus->nexthash) lastpointer=temp_servicestatus; if(!temp_servicestatus || (compare_hashdata2(temp_servicestatus->host_name,temp_servicestatus->description,new_servicestatus->host_name,new_servicestatus->description)!=0)){ if(lastpointer) lastpointer->nexthash=new_servicestatus; else servicestatus_hashlist[hashslot]=new_servicestatus; new_servicestatus->nexthash=temp_servicestatus; return 1; } /* else already exists */ return 0; } /******************************************************************/ /********************** ADDITION FUNCTIONS ************************/ /******************************************************************/ /* adds a host status entry to the list in memory */ int add_host_status(hoststatus *new_hoststatus){ char temp_buffer[MAX_INPUT_BUFFER]; char date_string[MAX_DATETIME_LENGTH]; /* make sure we have what we need */ if(new_hoststatus==NULL) return ERROR; if(new_hoststatus->host_name==NULL) return ERROR; /* massage host status a bit */ if(new_hoststatus!=NULL){ switch(new_hoststatus->status){ case 0: new_hoststatus->status=HOST_UP; break; case 1: new_hoststatus->status=HOST_DOWN; break; case 2: new_hoststatus->status=HOST_UNREACHABLE; break; default: new_hoststatus->status=HOST_UP; break; } if(new_hoststatus->has_been_checked==FALSE){ new_hoststatus->status=HOST_PENDING; free(new_hoststatus->plugin_output); if(new_hoststatus->should_be_scheduled==TRUE){ get_time_string(&new_hoststatus->next_check,date_string,sizeof(date_string),LONG_DATE_TIME); snprintf(temp_buffer,sizeof(temp_buffer)-1,"Host check scheduled for %s",date_string); temp_buffer[sizeof(temp_buffer)-1]='\x0'; new_hoststatus->plugin_output=strdup(temp_buffer); } else new_hoststatus->plugin_output=strdup("Host has not been checked yet"); } } new_hoststatus->next=NULL; new_hoststatus->nexthash=NULL; /* add new hoststatus to hoststatus chained hash list */ if(!add_hoststatus_to_hashlist(new_hoststatus)) return ERROR; /* object cache file is already sorted, so just add new items to end of list */ if(hoststatus_list==NULL){ hoststatus_list=new_hoststatus; hoststatus_list_tail=new_hoststatus; } else{ hoststatus_list_tail->next=new_hoststatus; hoststatus_list_tail=new_hoststatus; } return OK; } /* adds a service status entry to the list in memory */ int add_service_status(servicestatus *new_svcstatus){ char temp_buffer[MAX_INPUT_BUFFER]; char date_string[MAX_DATETIME_LENGTH]; /* make sure we have what we need */ if(new_svcstatus==NULL) return ERROR; if(new_svcstatus->host_name==NULL || new_svcstatus->description==NULL) return ERROR; /* massage service status a bit */ if(new_svcstatus!=NULL){ switch(new_svcstatus->status){ case 0: new_svcstatus->status=SERVICE_OK; break; case 1: new_svcstatus->status=SERVICE_WARNING; break; case 2: new_svcstatus->status=SERVICE_CRITICAL; break; case 3: new_svcstatus->status=SERVICE_UNKNOWN; break; default: new_svcstatus->status=SERVICE_OK; break; } if(new_svcstatus->has_been_checked==FALSE){ new_svcstatus->status=SERVICE_PENDING; free(new_svcstatus->plugin_output); if(new_svcstatus->should_be_scheduled==TRUE){ get_time_string(&new_svcstatus->next_check,date_string,sizeof(date_string),LONG_DATE_TIME); snprintf(temp_buffer,sizeof(temp_buffer)-1,"Service check scheduled for %s",date_string); temp_buffer[sizeof(temp_buffer)-1]='\x0'; new_svcstatus->plugin_output=strdup(temp_buffer); } else new_svcstatus->plugin_output=strdup("Service is not scheduled to be checked..."); } } new_svcstatus->next=NULL; new_svcstatus->nexthash=NULL; /* add new servicestatus to servicestatus chained hash list */ if(!add_servicestatus_to_hashlist(new_svcstatus)) return ERROR; /* object cache file is already sorted, so just add new items to end of list */ if(servicestatus_list==NULL){ servicestatus_list=new_svcstatus; servicestatus_list_tail=new_svcstatus; } else{ servicestatus_list_tail->next=new_svcstatus; servicestatus_list_tail=new_svcstatus; } return OK; } /******************************************************************/ /*********************** CLEANUP FUNCTIONS ************************/ /******************************************************************/ /* free all memory for status data */ void free_status_data(void){ hoststatus *this_hoststatus; hoststatus *next_hoststatus; servicestatus *this_svcstatus; servicestatus *next_svcstatus; /* free memory for the host status list */ for(this_hoststatus=hoststatus_list;this_hoststatus!=NULL;this_hoststatus=next_hoststatus){ next_hoststatus=this_hoststatus->next; free(this_hoststatus->host_name); free(this_hoststatus->plugin_output); free(this_hoststatus->perf_data); free(this_hoststatus); } /* free memory for the service status list */ for(this_svcstatus=servicestatus_list;this_svcstatus!=NULL;this_svcstatus=next_svcstatus){ next_svcstatus=this_svcstatus->next; free(this_svcstatus->host_name); free(this_svcstatus->description); free(this_svcstatus->plugin_output); free(this_svcstatus->perf_data); free(this_svcstatus); } /* free hash lists reset list pointers */ free(hoststatus_hashlist); free(servicestatus_hashlist); hoststatus_hashlist=NULL; servicestatus_hashlist=NULL; hoststatus_list=NULL; servicestatus_list=NULL; return; } /******************************************************************/ /************************ SEARCH FUNCTIONS ************************/ /******************************************************************/ /* find a host status entry */ hoststatus *find_hoststatus(char *host_name){ hoststatus *temp_hoststatus; if(host_name==NULL || hoststatus_hashlist==NULL) return NULL; for(temp_hoststatus=hoststatus_hashlist[hashfunc1(host_name,HOSTSTATUS_HASHSLOTS)];temp_hoststatus && compare_hashdata1(temp_hoststatus->host_name,host_name)<0;temp_hoststatus=temp_hoststatus->nexthash); if(temp_hoststatus && (compare_hashdata1(temp_hoststatus->host_name,host_name)==0)) return temp_hoststatus; return NULL; } /* find a service status entry */ servicestatus *find_servicestatus(char *host_name,char *svc_desc){ servicestatus *temp_servicestatus; if(host_name==NULL || svc_desc==NULL || servicestatus_hashlist==NULL) return NULL; for(temp_servicestatus=servicestatus_hashlist[hashfunc2(host_name,svc_desc,SERVICESTATUS_HASHSLOTS)];temp_servicestatus && compare_hashdata2(temp_servicestatus->host_name,temp_servicestatus->description,host_name,svc_desc)<0;temp_servicestatus=temp_servicestatus->nexthash); if(temp_servicestatus && (compare_hashdata2(temp_servicestatus->host_name,temp_servicestatus->description,host_name,svc_desc)==0)) return temp_servicestatus; return NULL; } /******************************************************************/ /*********************** UTILITY FUNCTIONS ************************/ /******************************************************************/ /* gets the total number of services of a certain state for a specific host */ int get_servicestatus_count(char *host_name, int type){ servicestatus *temp_status; int count=0; if(host_name==NULL) return 0; for(temp_status=servicestatus_list;temp_status!=NULL;temp_status=temp_status->next){ if(temp_status->status & type){ if(!strcmp(host_name,temp_status->host_name)) count++; } } return count; } #endif