![]() |
Icinga-core 1.4.0
next gen monitoring
|
00001 /*************************************************************** 00002 * IDO2DB.C - IDO To Database Daemon 00003 * 00004 * Copyright (c) 2005-2008 Ethan Galstad 00005 * Copyright (c) 2009-2011 Icinga Development Team (http://www.icinga.org) 00006 * 00007 **************************************************************/ 00008 00009 /*#define DEBUG_MEMORY 1*/ 00010 00011 #ifdef DEBUG_MEMORY 00012 #include <mcheck.h> 00013 #endif 00014 00015 /* include our project's header files */ 00016 #include "../../../include/config.h" 00017 #include "../include/common.h" 00018 #include "../include/io.h" 00019 #include "../include/utils.h" 00020 #include "../include/protoapi.h" 00021 #include "../include/ido2db.h" 00022 #include "../include/db.h" 00023 #include "../include/dbhandlers.h" 00024 00025 00026 #ifdef HAVE_SSL 00027 #include "../../../include/dh.h" 00028 #endif 00029 00030 extern int use_ssl; 00031 00032 extern int errno; 00033 00034 extern char *ido2db_db_tablenames[IDO2DB_MAX_DBTABLES]; 00035 00036 #ifdef USE_LIBDBI 00037 extern int ido2db_check_dbd_driver(void); 00038 #endif 00039 00040 /* use global dynamic buffer for mutex locks */ 00041 ido_dbuf dbuf; 00042 static pthread_mutex_t ido2db_dbuf_lock; 00043 00044 static void *ido2db_thread_cleanup_exit_handler(void *); 00045 static void *ido2db_thread_worker_exit_handler(void *); 00046 00047 /* 00048 pthread_mutex_lock(&ido2db_dbuf_lock); 00049 pthread_mutex_unlock(&ido2db_dbuf_lock); 00050 */ 00051 00052 #ifdef HAVE_SSL 00053 SSL_METHOD *meth; 00054 SSL_CTX *ctx; 00055 int allow_weak_random_seed = IDO_FALSE; 00056 #endif 00057 00058 char *ido2db_config_file=NULL; 00059 char *lock_file=NULL; 00060 char *ido2db_user=NULL; 00061 char *ido2db_group=NULL; 00062 00063 int ido2db_sd=0; 00064 int ido2db_socket_type=IDO_SINK_UNIXSOCKET; 00065 char *ido2db_socket_name=NULL; 00066 00067 int ido2db_tcp_port=IDO_DEFAULT_TCP_PORT; 00068 int ido2db_use_inetd=IDO_FALSE; 00069 00070 int ido2db_show_version=IDO_FALSE; 00071 int ido2db_show_license=IDO_FALSE; 00072 int ido2db_show_help=IDO_FALSE; 00073 00074 int ido2db_run_foreground=IDO_FALSE; 00075 00076 ido2db_dbconfig ido2db_db_settings; 00077 ido2db_idi thread_idi; 00078 pthread_t thread_pool[IDO2DB_NR_OF_THREADS]; 00079 00080 time_t ido2db_db_last_checkin_time=0L; 00081 00082 char *ido2db_debug_file=NULL; 00083 int ido2db_debug_level=IDO2DB_DEBUGL_NONE; 00084 int ido2db_debug_verbosity=IDO2DB_DEBUGV_BASIC; 00085 FILE *ido2db_debug_file_fp=NULL; 00086 unsigned long ido2db_max_debug_file_size=0L; 00087 00088 int stop_signal_detected=IDO_FALSE; 00089 00090 char *sigs[35]={"EXIT","HUP","INT","QUIT","ILL","TRAP","ABRT","BUS","FPE","KILL","USR1","SEGV","USR2","PIPE","ALRM","TERM","STKFLT","CHLD","CONT","STOP","TSTP","TTIN","TTOU","URG","XCPU","XFSZ","VTALRM","PROF","WINCH","IO","PWR","UNUSED","ZERR","DEBUG",(char *)NULL}; 00091 00092 00093 int ido2db_open_debug_log(void); 00094 int ido2db_close_debug_log(void); 00095 00096 00097 int dummy; /* reduce compiler warnings */ 00098 00099 00100 int main(int argc, char **argv){ 00101 int result=IDO_OK; 00102 00103 #ifdef DEBUG_MEMORY 00104 mtrace(); 00105 #endif 00106 #ifdef HAVE_SSL 00107 DH *dh; 00108 char seedfile[FILENAME_MAX]; 00109 int i,c; 00110 #endif 00111 #ifdef USE_LIBDBI 00112 dbi_driver driver; 00113 int numdrivers; 00114 00115 driver = NULL; 00116 #endif 00117 result=ido2db_process_arguments(argc,argv); 00118 00119 if(result!=IDO_OK || ido2db_show_help==IDO_TRUE || ido2db_show_license==IDO_TRUE || ido2db_show_version==IDO_TRUE){ 00120 00121 if(result!=IDO_OK) 00122 printf("Incorrect command line arguments supplied\n"); 00123 00124 printf("\n"); 00125 printf("%s %s\n",IDO2DB_NAME,IDO2DB_VERSION); 00126 printf("Copyright(c) 2005-2008 Ethan Galstad (nagios@nagios.org)\n"); 00127 printf("Copyright(c) 2009-2011 Icinga Development Team (http://www.icinga.org)\n"); 00128 printf("Last Modified: %s\n",IDO2DB_DATE); 00129 printf("License: GPL v2\n"); 00130 #ifdef HAVE_SSL 00131 printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); 00132 #endif 00133 printf("\n"); 00134 printf("Stores Icinga event and configuration data to a database for later retrieval\n"); 00135 printf("and processing. Clients that are capable of sending data to the IDO2DB daemon\n"); 00136 printf("include the LOG2IDO utility and IDOMOD event broker module.\n"); 00137 printf("\n"); 00138 printf("Usage: %s -c <config_file> [-i] [-f]\n",argv[0]); 00139 printf("\n"); 00140 printf("-i = Run under INETD/XINETD.\n"); 00141 printf("-f = Don't daemonize, run in foreground.\n"); 00142 printf("\n"); 00143 exit(1); 00144 } 00145 00146 /* initialize variables */ 00147 ido2db_initialize_variables(); 00148 00149 /* process config file */ 00150 if(ido2db_process_config_file(ido2db_config_file)!=IDO_OK){ 00151 printf("Error processing config file '%s'.\n",ido2db_config_file); 00152 exit(1); 00153 } 00154 00155 /* print starting info to syslog */ 00156 syslog(LOG_USER | LOG_INFO, "%s %s (%s) Copyright (c) 2005-2008 Ethan Galstad (nagios@nagios.org), Copyright (c) 2009-2011 Icinga Development Team (http://www.icinga.org))", IDO2DB_NAME, IDO2DB_VERSION, IDO2DB_DATE); 00157 syslog(LOG_USER | LOG_INFO, "%s %s starting... (PID=%d)\n", IDO2DB_NAME, IDO2DB_VERSION, (int)getpid() ); 00158 00159 if (ido2db_socket_type==IDO_SINK_UNIXSOCKET && use_ssl == IDO_TRUE){ 00160 printf("SSL is not allowed on socket_type=unix\n"); 00161 exit(1); 00162 } 00163 00164 #ifdef HAVE_SSL 00165 /* initialize SSL */ 00166 if(use_ssl==IDO_TRUE){ 00167 SSL_library_init(); 00168 SSLeay_add_ssl_algorithms(); 00169 meth=SSLv23_server_method(); 00170 SSL_load_error_strings(); 00171 00172 /* use week random seed if necessary */ 00173 if(allow_weak_random_seed && (RAND_status()==0)){ 00174 00175 if(RAND_file_name(seedfile,sizeof(seedfile)-1)) 00176 if(RAND_load_file(seedfile,-1)) 00177 RAND_write_file(seedfile); 00178 00179 if(RAND_status()==0){ 00180 syslog(LOG_ERR,"Warning: SSL/TLS uses a weak random seed which is highly discouraged"); 00181 srand(time(NULL)); 00182 for(i=0;i<500 && RAND_status()==0;i++){ 00183 for(c=0;c<sizeof(seedfile);c+=sizeof(int)){ 00184 *((int *)(seedfile+c))=rand(); 00185 } 00186 RAND_seed(seedfile,sizeof(seedfile)); 00187 } 00188 } 00189 } 00190 if((ctx=SSL_CTX_new(meth))==NULL){ 00191 syslog(LOG_ERR,"Error: could not create SSL context.\n"); 00192 exit(1); 00193 } 00194 00195 /* ADDED 01/19/2004 */ 00196 /* use only TLSv1 protocol */ 00197 SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); 00198 00199 /* use anonymous DH ciphers */ 00200 SSL_CTX_set_cipher_list(ctx,"ADH"); 00201 dh=get_dh512(); 00202 SSL_CTX_set_tmp_dh(ctx,dh); 00203 DH_free(dh); 00204 syslog(LOG_INFO,"INFO: SSL/TLS initialized. All network traffic will be encrypted."); 00205 } 00206 else{ 00207 syslog(LOG_INFO,"INFO: SSL/TLS NOT initialized. Network encryption DISABLED."); 00208 } 00209 /*Fin Hack SSL*/ 00210 #endif 00211 00212 /* make sure we're good to go */ 00213 if(ido2db_check_init_reqs()!=IDO_OK){ 00214 printf("One or more required parameters is missing or incorrect.\n"); 00215 exit(1); 00216 } 00217 00218 /* make sure we support the db option chosen... */ 00219 00220 /******************************/ 00221 #ifdef USE_LIBDBI /* everything else will be libdbi */ 00222 if(ido2db_check_dbd_driver()==IDO_FALSE){ 00223 printf("Support for the specified database server is either not yet supported, or was not found on your system.\n"); 00224 00225 numdrivers = dbi_initialize(NULL); 00226 00227 fprintf(stderr, "%d drivers available: ", numdrivers); 00228 while ((driver = dbi_driver_list(driver)) != NULL) { 00229 00230 fprintf(stderr, "%s ", dbi_driver_get_name(driver)); 00231 } 00232 fprintf(stderr, "\n"); 00233 00234 #ifdef HAVE_SSL 00235 if(use_ssl==IDO_TRUE) 00236 SSL_CTX_free(ctx); 00237 #endif 00238 00239 exit(1); 00240 } 00241 00242 /* 2009-10-16 Michael Friedrich: libdbi Oracle driver is not yet working, remains broken */ 00243 if(ido2db_db_settings.server_type==IDO2DB_DBSERVER_ORACLE) { 00244 printf("Support for libdbi Oracle driver is not yet working.\n"); 00245 exit(1); 00246 } 00247 #endif 00248 00249 /******************************/ 00250 #ifdef USE_PGSQL /* pgsql */ 00251 00252 /* we don't have a driver check here */ 00253 #endif 00254 00255 /******************************/ 00256 #ifdef USE_ORACLE /* Oracle ocilib specific */ 00257 00258 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db with ocilib() driver check\n"); 00259 if(OCI_GetOCIRuntimeVersion == OCI_UNKNOWN) { 00260 printf("Unknown ocilib runtime version detected. Exiting...\n"); 00261 00262 #ifdef HAVE_SSL 00263 if(use_ssl==IDO_TRUE) 00264 SSL_CTX_free(ctx); 00265 #endif 00266 00267 exit(1); 00268 } 00269 00270 #endif /* Oracle ocilib specific */ 00271 /******************************/ 00272 00273 /* initialize signal handling */ 00274 signal(SIGQUIT,ido2db_parent_sighandler); 00275 signal(SIGTERM,ido2db_parent_sighandler); 00276 signal(SIGINT,ido2db_parent_sighandler); 00277 signal(SIGSEGV,ido2db_parent_sighandler); 00278 signal(SIGFPE,ido2db_parent_sighandler); 00279 signal(SIGCHLD,ido2db_parent_sighandler); 00280 00281 /* drop privileges */ 00282 ido2db_drop_privileges(ido2db_user,ido2db_group); 00283 00284 /* open debug log */ 00285 ido2db_open_debug_log(); 00286 00287 /* if we're running under inetd... */ 00288 if(ido2db_use_inetd==IDO_TRUE){ 00289 00290 /* redirect STDERR to /dev/null */ 00291 close(2); 00292 open("/dev/null",O_WRONLY); 00293 00294 /* handle the connection */ 00295 ido2db_handle_client_connection(0); 00296 } 00297 00298 /* standalone daemon... */ 00299 else{ 00300 00301 /* create socket and wait for clients to connect */ 00302 if(ido2db_wait_for_connections()==IDO_ERROR) 00303 return 1; 00304 } 00305 00306 /* tell the log we're done */ 00307 syslog(LOG_USER | LOG_INFO, "Successfully shutdown... (PID=%d)\n",(int)getpid()); 00308 00309 /* close debug log */ 00310 ido2db_close_debug_log(); 00311 00312 /* free memory */ 00313 ido2db_free_program_memory(); 00314 00315 #ifdef HAVE_SSL 00316 if(use_ssl==IDO_TRUE) 00317 SSL_CTX_free(ctx); 00318 #endif 00319 00320 return 0; 00321 } 00322 00323 00324 /* process command line arguments */ 00325 int ido2db_process_arguments(int argc, char **argv){ 00326 char optchars[32]; 00327 int c=1; 00328 00329 #ifdef HAVE_GETOPT_H 00330 int option_index=0; 00331 static struct option long_options[]={ 00332 {"configfile", required_argument, 0, 'c'}, 00333 {"inetd", no_argument, 0, 'i'}, 00334 {"foreground", no_argument, 0, 'f'}, 00335 {"help", no_argument, 0, 'h'}, 00336 {"license", no_argument, 0, 'l'}, 00337 {"version", no_argument, 0, 'V'}, 00338 {0, 0, 0, 0} 00339 }; 00340 #endif 00341 00342 /* no options were supplied */ 00343 if(argc<2){ 00344 ido2db_show_help=IDO_TRUE; 00345 return IDO_OK; 00346 } 00347 00348 snprintf(optchars,sizeof(optchars),"c:ifhlV"); 00349 00350 while(1){ 00351 #ifdef HAVE_GETOPT_H 00352 c=getopt_long(argc,argv,optchars,long_options,&option_index); 00353 #else 00354 c=getopt(argc,argv,optchars); 00355 #endif 00356 if(c==-1 || c==EOF) 00357 break; 00358 00359 /* process all arguments */ 00360 switch(c){ 00361 00362 case '?': 00363 case 'h': 00364 ido2db_show_help=IDO_TRUE; 00365 break; 00366 case 'V': 00367 ido2db_show_version=IDO_TRUE; 00368 break; 00369 case 'l': 00370 ido2db_show_license=IDO_TRUE; 00371 break; 00372 case 'c': 00373 ido2db_config_file=strdup(optarg); 00374 break; 00375 case 'i': 00376 ido2db_use_inetd=IDO_TRUE; 00377 break; 00378 case 'f': 00379 ido2db_run_foreground=IDO_TRUE; 00380 break; 00381 default: 00382 return IDO_ERROR; 00383 break; 00384 } 00385 } 00386 00387 /* make sure required args were supplied */ 00388 if((ido2db_config_file==NULL) && ido2db_show_help==IDO_FALSE && ido2db_show_version==IDO_FALSE && ido2db_show_license==IDO_FALSE) 00389 return IDO_ERROR; 00390 00391 return IDO_OK; 00392 } 00393 00394 00395 00396 /****************************************************************************/ 00397 /* CONFIG FUNCTIONS */ 00398 /****************************************************************************/ 00399 00400 /* process all config vars in a file */ 00401 int ido2db_process_config_file(char *filename){ 00402 ido_mmapfile *thefile=NULL; 00403 char *buf=NULL; 00404 int result=IDO_OK; 00405 00406 /* open the file */ 00407 if((thefile=ido_mmap_fopen(filename))==NULL){ 00408 syslog(LOG_ERR, "Error: Unable to open configuration file %s: %s\n", filename, strerror(errno)); 00409 return IDO_ERROR; 00410 } 00411 00412 /* process each line of the file */ 00413 while((buf=ido_mmap_fgets(thefile))){ 00414 00415 /* skip comments */ 00416 if(buf[0]=='#'){ 00417 free(buf); 00418 continue; 00419 } 00420 00421 /* skip blank lines */ 00422 if(!strcmp(buf,"")){ 00423 free(buf); 00424 continue; 00425 } 00426 00427 /* process the variable */ 00428 result=ido2db_process_config_var(buf); 00429 00430 /* free memory */ 00431 free(buf); 00432 00433 if(result!=IDO_OK) 00434 break; 00435 } 00436 00437 /* close the file */ 00438 ido_mmap_fclose(thefile); 00439 00440 return result; 00441 } 00442 00443 00444 /* process a single module config variable */ 00445 int ido2db_process_config_var(char *arg){ 00446 char *var=NULL; 00447 char *val=NULL; 00448 00449 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_process_config_var() start\n"); 00450 00451 /* split var/val */ 00452 var=strtok(arg,"="); 00453 val=strtok(NULL,"\n"); 00454 00455 /* skip incomplete var/val pairs */ 00456 if(var==NULL || val==NULL) 00457 return IDO_OK; 00458 00459 /* process the variable... */ 00460 00461 if(!strcmp(var,"lock_file")){ 00462 if((lock_file=strdup(val))==NULL) 00463 return IDO_ERROR; 00464 } 00465 else if(!strcmp(var,"socket_type")){ 00466 if(!strcmp(val,"tcp")) 00467 ido2db_socket_type=IDO_SINK_TCPSOCKET; 00468 else 00469 ido2db_socket_type=IDO_SINK_UNIXSOCKET; 00470 } 00471 else if(!strcmp(var,"socket_name")){ 00472 if((ido2db_socket_name=strdup(val))==NULL) 00473 return IDO_ERROR; 00474 } 00475 else if(!strcmp(var,"tcp_port")){ 00476 ido2db_tcp_port=atoi(val); 00477 } 00478 else if(!strcmp(var,"db_servertype")){ 00479 if(!strcmp(val,"mysql")) { 00480 ido2db_db_settings.server_type=IDO2DB_DBSERVER_MYSQL; 00481 ido2db_db_settings.dbserver=strdup(val); 00482 } else if(!strcmp(val,"pgsql")) { 00483 ido2db_db_settings.server_type=IDO2DB_DBSERVER_PGSQL; 00484 ido2db_db_settings.dbserver=strdup(val); 00485 } else if(!strcmp(val,"db2")) { 00486 ido2db_db_settings.server_type=IDO2DB_DBSERVER_DB2; 00487 ido2db_db_settings.dbserver=strdup(val); 00488 } else if(!strcmp(val,"firebird")) { 00489 ido2db_db_settings.server_type=IDO2DB_DBSERVER_FIREBIRD; 00490 ido2db_db_settings.dbserver=strdup(val); 00491 } else if(!strcmp(val,"freetds")) { 00492 ido2db_db_settings.server_type=IDO2DB_DBSERVER_FREETDS; 00493 ido2db_db_settings.dbserver=strdup(val); 00494 } else if(!strcmp(val,"ingres")) { 00495 ido2db_db_settings.server_type=IDO2DB_DBSERVER_INGRES; 00496 ido2db_db_settings.dbserver=strdup(val); 00497 } else if(!strcmp(val,"msql")) { 00498 ido2db_db_settings.server_type=IDO2DB_DBSERVER_MSQL; 00499 ido2db_db_settings.dbserver=strdup(val); 00500 } else if(!strcmp(val,"oracle")) { 00501 ido2db_db_settings.server_type=IDO2DB_DBSERVER_ORACLE; 00502 ido2db_db_settings.dbserver=strdup(val); 00503 } else if(!strcmp(val,"sqlite")) { 00504 ido2db_db_settings.server_type=IDO2DB_DBSERVER_SQLITE; 00505 ido2db_db_settings.dbserver=strdup(val); 00506 } else if(!strcmp(val,"sqlite3")) { 00507 ido2db_db_settings.server_type=IDO2DB_DBSERVER_SQLITE3; 00508 ido2db_db_settings.dbserver=strdup(val); 00509 } else 00510 return IDO_ERROR; 00511 } 00512 else if(!strcmp(var,"db_host")){ 00513 if((ido2db_db_settings.host=strdup(val))==NULL) 00514 return IDO_ERROR; 00515 } 00516 else if(!strcmp(var,"db_port")){ 00517 ido2db_db_settings.port=atoi(val); 00518 } 00519 else if(!strcmp(var,"db_user")){ 00520 if((ido2db_db_settings.username=strdup(val))==NULL) 00521 return IDO_ERROR; 00522 } 00523 else if(!strcmp(var,"db_pass")){ 00524 if((ido2db_db_settings.password=strdup(val))==NULL) 00525 return IDO_ERROR; 00526 } 00527 else if(!strcmp(var,"db_name")){ 00528 if((ido2db_db_settings.dbname=strdup(val))==NULL) 00529 return IDO_ERROR; 00530 } 00531 else if(!strcmp(var,"db_prefix")){ 00532 if((ido2db_db_settings.dbprefix=strdup(val))==NULL) 00533 return IDO_ERROR; 00534 } 00535 else if(!strcmp(var,"db_socket")){ 00536 if((ido2db_db_settings.dbsocket=strdup(val))==NULL) 00537 return IDO_ERROR; 00538 } 00539 else if(!strcmp(var,"max_timedevents_age")) 00540 ido2db_db_settings.max_timedevents_age=strtoul(val,NULL,0)*60; 00541 else if(!strcmp(var,"max_systemcommands_age")) 00542 ido2db_db_settings.max_systemcommands_age=strtoul(val,NULL,0)*60; 00543 else if(!strcmp(var,"max_servicechecks_age")) 00544 ido2db_db_settings.max_servicechecks_age=strtoul(val,NULL,0)*60; 00545 else if(!strcmp(var,"max_hostchecks_age")) 00546 ido2db_db_settings.max_hostchecks_age=strtoul(val,NULL,0)*60; 00547 else if(!strcmp(var,"max_eventhandlers_age")) 00548 ido2db_db_settings.max_eventhandlers_age=strtoul(val,NULL,0)*60; 00549 else if(!strcmp(var,"max_externalcommands_age")) 00550 ido2db_db_settings.max_externalcommands_age=strtoul(val,NULL,0)*60; 00551 else if(!strcmp(var,"max_logentries_age")) 00552 ido2db_db_settings.max_logentries_age=strtoul(val,NULL,0)*60; 00553 else if(!strcmp(var,"max_acknowledgements_age")) 00554 ido2db_db_settings.max_acknowledgements_age=strtoul(val,NULL,0)*60; 00555 00556 else if(!strcmp(var,"trim_db_interval")) 00557 ido2db_db_settings.trim_db_interval=strtoul(val,NULL,0); 00558 00559 else if(!strcmp(var,"housekeeping_thread_startup_delay")) 00560 ido2db_db_settings.housekeeping_thread_startup_delay=strtoul(val,NULL,0); 00561 00562 else if((!strcmp(var,"ido2db_user"))||(!strcmp(var,"ido2db_user"))) 00563 ido2db_user=strdup(val); 00564 else if((!strcmp(var,"ido2db_group"))||(!strcmp(var,"ido2db_group"))) 00565 ido2db_group=strdup(val); 00566 00567 else if(!strcmp(var,"debug_file")){ 00568 if((ido2db_debug_file=strdup(val))==NULL) 00569 return IDO_ERROR; 00570 } 00571 else if(!strcmp(var,"debug_level")) 00572 ido2db_debug_level=atoi(val); 00573 else if(!strcmp(var,"debug_verbosity")) 00574 ido2db_debug_verbosity=atoi(val); 00575 else if(!strcmp(var,"max_debug_file_size")) 00576 ido2db_max_debug_file_size=strtoul(val,NULL,0); 00577 else if(!strcmp(var,"use_ssl")){ 00578 if (strlen(val) == 1) { 00579 if (isdigit((int)val[strlen(val)-1]) != IDO_FALSE) 00580 use_ssl = atoi(val); 00581 else 00582 use_ssl = 0; 00583 } 00584 } 00585 else if(!strcmp(var, "clean_realtime_tables_on_core_startup")) { 00586 if(strlen(val)!=1||val[0]<'0'||val[0]>'1'){ 00587 return IDO_ERROR; 00588 } 00589 ido2db_db_settings.clean_realtime_tables_on_core_startup=(atoi(val)>0)?IDO_TRUE:IDO_FALSE; 00590 } 00591 else if(!strcmp(var, "clean_config_tables_on_core_startup")) { 00592 if(strlen(val)!=1||val[0]<'0'||val[0]>'1'){ 00593 return IDO_ERROR; 00594 } 00595 ido2db_db_settings.clean_config_tables_on_core_startup=(atoi(val)>0)?IDO_TRUE:IDO_FALSE; 00596 } 00597 00598 else if(!strcmp(var,"oci_errors_to_syslog")){ 00599 ido2db_db_settings.oci_errors_to_syslog=(atoi(val)>0)?IDO_TRUE:IDO_FALSE; 00600 } 00601 00602 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_process_config_var() end\n"); 00603 00604 return IDO_OK; 00605 } 00606 00607 00608 /* initialize variables */ 00609 int ido2db_initialize_variables(void){ 00610 00611 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_initialize_variables() start\n"); 00612 00613 ido2db_db_settings.server_type=IDO2DB_DBSERVER_NONE; 00614 ido2db_db_settings.host=NULL; 00615 ido2db_db_settings.port=0; 00616 ido2db_db_settings.username=NULL; 00617 ido2db_db_settings.password=NULL; 00618 ido2db_db_settings.dbname=NULL; 00619 ido2db_db_settings.dbprefix=NULL; 00620 ido2db_db_settings.dbsocket=NULL; 00621 ido2db_db_settings.max_timedevents_age=0L; 00622 ido2db_db_settings.max_systemcommands_age=0L; 00623 ido2db_db_settings.max_servicechecks_age=0L; 00624 ido2db_db_settings.max_hostchecks_age=0L; 00625 ido2db_db_settings.max_eventhandlers_age=0L; 00626 ido2db_db_settings.max_externalcommands_age=0L; 00627 ido2db_db_settings.max_logentries_age=0L; 00628 ido2db_db_settings.max_acknowledgements_age=0L; 00629 ido2db_db_settings.trim_db_interval=(unsigned long)DEFAULT_TRIM_DB_INTERVAL; /* set the default if missing in ido2db.cfg */ 00630 ido2db_db_settings.housekeeping_thread_startup_delay=(unsigned long)DEFAULT_HOUSEKEEPING_THREAD_STARTUP_DELAY; /* set the default if missing in ido2db.cfg */ 00631 ido2db_db_settings.clean_realtime_tables_on_core_startup=IDO_TRUE; /* default is cleaning on startup */ 00632 ido2db_db_settings.clean_config_tables_on_core_startup=IDO_TRUE; 00633 ido2db_db_settings.oci_errors_to_syslog=DEFAULT_OCI_ERRORS_TO_SYSLOG; 00634 00635 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_initialize_variables() end\n"); 00636 return IDO_OK; 00637 } 00638 00639 00640 00641 /****************************************************************************/ 00642 /* CLEANUP FUNCTIONS */ 00643 /****************************************************************************/ 00644 00645 /* free program memory */ 00646 int ido2db_free_program_memory(void){ 00647 00648 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_free_program_memory() start\n"); 00649 00650 if(ido2db_config_file){ 00651 free(ido2db_config_file); 00652 ido2db_config_file=NULL; 00653 } 00654 if(ido2db_user){ 00655 free(ido2db_user); 00656 ido2db_user=NULL; 00657 } 00658 if(ido2db_group){ 00659 free(ido2db_group); 00660 ido2db_group=NULL; 00661 } 00662 if(ido2db_socket_name){ 00663 free(ido2db_socket_name); 00664 ido2db_socket_name=NULL; 00665 } 00666 if(ido2db_db_settings.host){ 00667 free(ido2db_db_settings.host); 00668 ido2db_db_settings.host=NULL; 00669 } 00670 if(ido2db_db_settings.username){ 00671 free(ido2db_db_settings.username); 00672 ido2db_db_settings.username=NULL; 00673 } 00674 if(ido2db_db_settings.password){ 00675 free(ido2db_db_settings.password); 00676 ido2db_db_settings.password=NULL; 00677 } 00678 if(ido2db_db_settings.dbname){ 00679 free(ido2db_db_settings.dbname); 00680 ido2db_db_settings.dbname=NULL; 00681 } 00682 if(ido2db_db_settings.dbprefix){ 00683 free(ido2db_db_settings.dbprefix); 00684 ido2db_db_settings.dbprefix=NULL; 00685 } 00686 if(ido2db_db_settings.dbsocket){ 00687 free(ido2db_db_settings.dbsocket); 00688 ido2db_db_settings.dbsocket=NULL; 00689 } 00690 if(ido2db_debug_file){ 00691 free(ido2db_debug_file); 00692 ido2db_debug_file=NULL; 00693 } 00694 00695 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_free_program_memory() end\n"); 00696 return IDO_OK; 00697 } 00698 00699 00700 00701 /****************************************************************************/ 00702 /* UTILITY FUNCTIONS */ 00703 /****************************************************************************/ 00704 00705 int ido2db_check_init_reqs(void){ 00706 00707 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_check_init_reqs() start\n"); 00708 00709 if(ido2db_socket_type==IDO_SINK_UNIXSOCKET){ 00710 if(ido2db_socket_name==NULL){ 00711 printf("No socket name specified.\n"); 00712 return IDO_ERROR; 00713 } 00714 } 00715 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_check_init_reqs() end\n"); 00716 return IDO_OK; 00717 } 00718 00719 00720 00721 /* drops privileges */ 00722 int ido2db_drop_privileges(char *user, char *group){ 00723 uid_t uid=-1; 00724 gid_t gid=-1; 00725 struct group *grp; 00726 struct passwd *pw; 00727 00728 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_drop_privileges() start\n"); 00729 00730 /* set effective group ID */ 00731 if(group!=NULL){ 00732 00733 /* see if this is a group name */ 00734 if(strspn(group,"0123456789")<strlen(group)){ 00735 grp=(struct group *)getgrnam(group); 00736 if(grp!=NULL) 00737 gid=(gid_t)(grp->gr_gid); 00738 else 00739 syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group); 00740 endgrent(); 00741 } 00742 00743 /* else we were passed the GID */ 00744 else 00745 gid=(gid_t)atoi(group); 00746 00747 /* set effective group ID if other than current EGID */ 00748 if(gid!=getegid()){ 00749 00750 if(setgid(gid)==-1) 00751 syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid); 00752 } 00753 } 00754 00755 00756 /* set effective user ID */ 00757 if(user!=NULL){ 00758 00759 /* see if this is a user name */ 00760 if(strspn(user,"0123456789")<strlen(user)){ 00761 pw=(struct passwd *)getpwnam(user); 00762 if(pw!=NULL) 00763 uid=(uid_t)(pw->pw_uid); 00764 else 00765 syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user); 00766 endpwent(); 00767 } 00768 00769 /* else we were passed the UID */ 00770 else 00771 uid=(uid_t)atoi(user); 00772 00773 /* set effective user ID if other than current EUID */ 00774 if(uid!=geteuid()){ 00775 00776 #ifdef HAVE_INITGROUPS 00777 /* initialize supplementary groups */ 00778 if(initgroups(user,gid)==-1){ 00779 if(errno==EPERM) 00780 syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()"); 00781 else{ 00782 syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()"); 00783 return IDO_ERROR; 00784 } 00785 } 00786 #endif 00787 00788 if(setuid(uid)==-1) 00789 syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid); 00790 } 00791 } 00792 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_drop_privileges() end\n"); 00793 return IDO_OK; 00794 } 00795 00796 00797 int ido2db_daemonize(void){ 00798 pid_t pid=-1; 00799 /* int pidno=0; */ 00800 int lockfile=0; 00801 struct flock lock; 00802 int val=0; 00803 char buf[256]; 00804 char *msg=NULL; 00805 00806 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() start\n"); 00807 00808 umask(S_IWGRP|S_IWOTH); 00809 00810 /* get a lock on the lockfile */ 00811 if(lock_file){ 00812 lockfile=open(lock_file,O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); 00813 if(lockfile<0){ 00814 if(asprintf(&msg,"Failed to obtain lock on file %s: %s\n", lock_file, strerror(errno))==-1) 00815 msg=NULL; 00816 perror(msg); 00817 ido2db_cleanup_socket(); 00818 return IDO_ERROR; 00819 } 00820 00821 /* see if we can read the contents of the lockfile */ 00822 if((val=read(lockfile,buf,(size_t)10))<0){ 00823 if(asprintf(&msg,"Lockfile exists but cannot be read")==-1) 00824 msg=NULL; 00825 perror(msg); 00826 ido2db_cleanup_socket(); 00827 return IDO_ERROR; 00828 } 00829 00830 /* place a file lock on the lock file */ 00831 lock.l_type=F_WRLCK; 00832 lock.l_start=0; 00833 lock.l_whence=SEEK_SET; 00834 lock.l_len=0; 00835 if(fcntl(lockfile,F_SETLK,&lock)<0){ 00836 if(errno==EACCES || errno==EAGAIN){ 00837 fcntl(lockfile,F_GETLK,&lock); 00838 if(asprintf(&msg,"Lockfile '%s' looks like its already held by another instance (%d). Bailing out...",lock_file,(int)lock.l_pid)==-1) 00839 msg=NULL; 00840 } 00841 else { 00842 if(asprintf(&msg,"Cannot lock lockfile '%s': %s. Bailing out...",lock_file,strerror(errno))==-1) 00843 msg=NULL; 00844 } 00845 perror(msg); 00846 ido2db_cleanup_socket(); 00847 return IDO_ERROR; 00848 } 00849 } 00850 00851 /* fork */ 00852 if((pid=fork())<0){ 00853 perror("Fork error"); 00854 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() parent fork error\n"); 00855 ido2db_cleanup_socket(); 00856 return IDO_ERROR; 00857 } 00858 00859 /* parent process goes away... */ 00860 else if((int)pid!=0){ 00861 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() parent process goes away\n"); 00862 ido2db_free_program_memory(); 00863 exit(0); 00864 } 00865 00866 /* child forks again... */ 00867 else{ 00868 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() child forks again\n"); 00869 00870 if((pid=fork())<0){ 00871 perror("Fork error"); 00872 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() child fork error\n"); 00873 ido2db_cleanup_socket(); 00874 return IDO_ERROR; 00875 } 00876 00877 /* first child process goes away.. */ 00878 else if((int)pid!=0){ 00879 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() first child process goes away\n"); 00880 ido2db_free_program_memory(); 00881 exit(0); 00882 } 00883 00884 /* grandchild continues... */ 00885 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() grandchild continues and becomes session leader\n"); 00886 /* grandchild becomes session leader... */ 00887 setsid(); 00888 } 00889 00890 if(lock_file){ 00891 /* write PID to lockfile... */ 00892 lseek(lockfile,0,SEEK_SET); 00893 dummy=ftruncate(lockfile,0); 00894 sprintf(buf,"%d\n",(int)getpid()); 00895 dummy=write(lockfile,buf,strlen(buf)); 00896 00897 /* make sure lock file stays open while program is executing... */ 00898 val=fcntl(lockfile,F_GETFD,0); 00899 val|=FD_CLOEXEC; 00900 fcntl(lockfile,F_SETFD,val); 00901 } 00902 00903 /* close existing stdin, stdout, stderr */ 00904 close(0); 00905 if(ido2db_run_foreground == IDO_FALSE) 00906 close(1); 00907 close(2); 00908 00909 /* re-open stdin, stdout, stderr with known values */ 00910 open("/dev/null",O_RDONLY); 00911 if(ido2db_run_foreground == IDO_FALSE) 00912 open("/dev/null",O_WRONLY); 00913 open("/dev/null",O_WRONLY); 00914 00915 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_daemonize() end\n"); 00916 00917 return IDO_OK; 00918 } 00919 00920 00921 int ido2db_cleanup_socket(void){ 00922 00923 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_cleanup_socket() start\n"); 00924 00925 /* we're running under INETD */ 00926 if(ido2db_use_inetd==IDO_TRUE) 00927 return IDO_OK; 00928 00929 /* close the socket */ 00930 shutdown(ido2db_sd,2); 00931 close(ido2db_sd); 00932 00933 /* unlink the file */ 00934 if(ido2db_socket_type==IDO_SINK_UNIXSOCKET) 00935 unlink(ido2db_socket_name); 00936 00937 if(lock_file) 00938 unlink(lock_file); 00939 00940 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_cleanup_socket() end\n"); 00941 return IDO_OK; 00942 } 00943 00944 00945 void ido2db_parent_sighandler(int sig){ 00946 00947 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_parent_sighandler() start\n"); 00948 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "processing signal '%d'\n", sig); 00949 00950 /* not possible as parent */ 00951 /* syslog(LOG_USER | LOG_INFO, "Processing SIG%s...\n", sigs[sig]); */ 00952 00953 switch (sig){ 00954 case SIGTERM: 00955 case SIGINT: 00956 /* forward signal to all members of this group of processes */ 00957 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "forward signal to all members of this group of processes\n"); 00958 kill(0, sig); 00959 break; 00960 case SIGCHLD: 00961 /* cleanup children that exit, so we don't have zombies */ 00962 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "cleanup children that exit, so we don't have zombies\n"); 00963 while(waitpid(-1,NULL,WNOHANG)>0); 00964 return; 00965 00966 default: 00967 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 0, "Caught the Signal '%d' but don't care about this.\n", sig); 00968 } 00969 00970 /* cleanup the socket */ 00971 ido2db_cleanup_socket(); 00972 00973 /* free memory */ 00974 ido2db_free_program_memory(); 00975 00976 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_parent_sighandler() end\n"); 00977 00978 exit(0); 00979 00980 return; 00981 } 00982 00983 00984 void ido2db_child_sighandler(int sig){ 00985 00986 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_child_sighandler() start\n"); 00987 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "Child caught signal '%d' exiting\n", sig); 00988 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_child_sighandler() end\n"); 00989 00990 /* don't run into a race condition */ 00991 //syslog(LOG_USER | LOG_INFO, "Caught SIG%s, cleaning up and exiting...\n", sigs[sig]); 00992 00993 if(ido2db_run_foreground == IDO_TRUE){ 00994 /* cleanup the socket */ 00995 ido2db_cleanup_socket(); 00996 00997 /* free memory */ 00998 ido2db_free_program_memory(); 00999 } 01000 01001 /* terminate threads */ 01002 ido2db_terminate_threads(); 01003 01004 _exit(0); 01005 01006 return; 01007 } 01008 01009 01010 /****************************************************************************/ 01011 /* UTILITY FUNCTIONS */ 01012 /****************************************************************************/ 01013 01014 01015 int ido2db_wait_for_connections(void){ 01016 int sd_flag=1; 01017 int new_sd=0; 01018 pid_t new_pid=-1; 01019 struct sockaddr_un server_address_u; 01020 struct sockaddr_in server_address_i; 01021 struct sockaddr_un client_address_u; 01022 struct sockaddr_in client_address_i; 01023 socklen_t client_address_length; 01024 01025 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_wait_for_connections() start\n"); 01026 01027 /* TCP socket */ 01028 if(ido2db_socket_type==IDO_SINK_TCPSOCKET){ 01029 01030 /* create a socket */ 01031 if(!(ido2db_sd=socket(PF_INET,SOCK_STREAM,0))){ 01032 perror("Cannot create socket"); 01033 return IDO_ERROR; 01034 } 01035 01036 /* set the reuse address flag so we don't get errors when restarting */ 01037 sd_flag=1; 01038 if(setsockopt(ido2db_sd,SOL_SOCKET,SO_REUSEADDR,(char *)&sd_flag,sizeof(sd_flag))<0){ 01039 printf("Could not set reuse address option on socket!\n"); 01040 return IDO_ERROR; 01041 } 01042 01043 /* clear the address */ 01044 bzero((char *)&server_address_i,sizeof(server_address_i)); 01045 server_address_i.sin_family=AF_INET; 01046 server_address_i.sin_addr.s_addr=INADDR_ANY; 01047 server_address_i.sin_port=htons(ido2db_tcp_port); 01048 01049 /* bind the socket */ 01050 if((bind(ido2db_sd,(struct sockaddr *)&server_address_i,sizeof(server_address_i)))){ 01051 close(ido2db_sd); 01052 perror("Could not bind socket"); 01053 return IDO_ERROR; 01054 } 01055 01056 client_address_length=(socklen_t)sizeof(client_address_i); 01057 } 01058 01059 /* UNIX domain socket */ 01060 else{ 01061 01062 /* create a socket */ 01063 if(!(ido2db_sd=socket(AF_UNIX,SOCK_STREAM,0))){ 01064 perror("Cannot create socket"); 01065 return IDO_ERROR; 01066 } 01067 01068 /* copy the socket path */ 01069 strncpy(server_address_u.sun_path,ido2db_socket_name,sizeof(server_address_u.sun_path)); 01070 server_address_u.sun_family=AF_UNIX; 01071 01072 /* bind the socket */ 01073 if((bind(ido2db_sd,(struct sockaddr *)&server_address_u,SUN_LEN(&server_address_u)))){ 01074 close(ido2db_sd); 01075 perror("Could not bind socket"); 01076 return IDO_ERROR; 01077 } 01078 01079 client_address_length=(socklen_t)sizeof(client_address_u); 01080 } 01081 01082 /* listen for connections */ 01083 if((listen(ido2db_sd,1))){ 01084 perror("Cannot listen on socket"); 01085 ido2db_cleanup_socket(); 01086 return IDO_ERROR; 01087 } 01088 01089 01090 /* daemonize */ 01091 if(ido2db_run_foreground == IDO_FALSE) { 01092 if(ido2db_daemonize()!=IDO_OK) 01093 return IDO_ERROR; 01094 syslog(LOG_USER | LOG_INFO, "Finished daemonizing... (New PID=%d)\n",(int)getpid()); 01095 } 01096 01097 /* accept connections... */ 01098 while(1){ 01099 01100 while(1){ 01101 01102 new_sd=accept(ido2db_sd,(ido2db_socket_type==IDO_SINK_TCPSOCKET)?(struct sockaddr *)&client_address_i:(struct sockaddr *)&client_address_u,(socklen_t *)&client_address_length); 01103 01104 01105 /* ToDo: Hendrik 08/12/2009 01106 * If both ends think differently about SSL encryption, data from a idomod will 01107 * be lost forever (likewise on database errors/misconfiguration) 01108 * This seems a good place to output some information from which client 01109 * a possible misconfiguration comes from. 01110 * Logging the ip address together with the idomod instance name might be 01111 * a great hint for further error hunting 01112 */ 01113 01114 if(new_sd>=0) 01115 /* data available */ 01116 syslog(LOG_USER | LOG_INFO, "Client connected, data available.\n"); 01117 break; 01118 if(errno == EINTR) { 01119 /* continue */ 01120 } 01121 else { 01122 perror("Accept error"); 01123 ido2db_cleanup_socket(); 01124 return IDO_ERROR; 01125 } 01126 } 01127 01128 if(ido2db_run_foreground == IDO_FALSE) { 01129 /* fork... */ 01130 new_pid=fork(); 01131 01132 switch(new_pid){ 01133 case -1: 01134 /* parent simply prints an error message and keeps on going... */ 01135 perror("Fork error"); 01136 close(new_sd); 01137 break; 01138 01139 case 0: 01140 /* child processes data... */ 01141 ido2db_handle_client_connection(new_sd); 01142 01143 /* close socket when we're done */ 01144 close(new_sd); 01145 return IDO_OK; 01146 break; 01147 01148 default: 01149 /* parent keeps on going... */ 01150 close(new_sd); 01151 break; 01152 } 01153 } 01154 else{ 01155 /* child processes data... */ 01156 ido2db_handle_client_connection(new_sd); 01157 01158 /* close socket when we're done */ 01159 close(new_sd); 01160 } 01161 01162 #ifdef DEBUG_IDO2DB_EXIT_AFTER_CONNECTION 01163 break; 01164 #endif 01165 } 01166 01167 /* cleanup after ourselves */ 01168 ido2db_cleanup_socket(); 01169 01170 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_wait_for_connections() end\n"); 01171 01172 return IDO_OK; 01173 } 01174 01175 01176 int ido2db_handle_client_connection(int sd){ 01177 int dbuf_chunk=2048; 01178 ido2db_idi idi; 01179 char buf[512]; 01180 int result=0; 01181 int error=IDO_FALSE; 01182 01183 int pthread_ret=0; 01184 sigset_t newmask; 01185 pthread_attr_t attr; 01186 01187 #ifdef HAVE_SSL 01188 SSL *ssl=NULL; 01189 #endif 01190 01191 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_connection() start\n"); 01192 01193 /* open syslog facility */ 01194 /*openlog("ido2db",0,LOG_DAEMON);*/ 01195 01196 syslog(LOG_USER | LOG_INFO, "Handling client connection...\n"); 01197 /* re-open debug log */ 01198 ido2db_close_debug_log(); 01199 ido2db_open_debug_log(); 01200 01201 /* reset signal handling */ 01202 signal(SIGQUIT,ido2db_child_sighandler); 01203 signal(SIGTERM,ido2db_child_sighandler); 01204 signal(SIGINT,ido2db_child_sighandler); 01205 signal(SIGSEGV,ido2db_child_sighandler); 01206 signal(SIGFPE,ido2db_child_sighandler); 01207 01208 /* new thread should block all signals */ 01209 sigfillset(&newmask); 01210 pthread_sigmask(SIG_BLOCK,&newmask,NULL); 01211 01212 /* set stack size */ 01213 pthread_attr_init(&attr); 01214 if(pthread_attr_setstacksize(&attr, IDO2DB_DEFAULT_THREAD_STACK_SIZE)!=0) 01215 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_connection() pthread_attr_setstacksize with %lu error\n", IDO2DB_DEFAULT_THREAD_STACK_SIZE); 01216 01217 /* create cleanup thread */ 01218 if ((pthread_ret = pthread_create(&thread_pool[IDO2DB_THREAD_POOL_CLEANER], &attr, ido2db_thread_cleanup, &idi)) != 0) { 01219 syslog(LOG_ERR,"Could not create thread... exiting with error '%s'\n", strerror(errno)); 01220 exit(EXIT_FAILURE); 01221 } 01222 01223 /* create worker thread */ 01224 if ((pthread_ret = pthread_create(&thread_pool[IDO2DB_THREAD_POOL_WORKER], &attr, ido2db_thread_worker, &idi)) != 0) { 01225 syslog(LOG_ERR,"Could not create thread... exiting with error '%s'\n", strerror(errno)); 01226 exit(EXIT_FAILURE); 01227 } 01228 01229 01230 /* main thread should unblock all signals */ 01231 pthread_sigmask(SIG_UNBLOCK,&newmask,NULL); 01232 pthread_attr_destroy(&attr); 01233 01234 /* initialize input data information */ 01235 ido2db_idi_init(&idi); 01236 01237 /* initialize dynamic buffer (2KB chunk size) */ 01238 ido_dbuf_init(&dbuf,dbuf_chunk); 01239 01240 /* initialize database connection */ 01241 ido2db_db_init(&idi); 01242 01243 /* check if connection to database was successful */ 01244 if(ido2db_db_connect(&idi)==IDO_ERROR) { 01245 if(idi.dbinfo.connected!=IDO_TRUE) { 01246 01247 /* we did not get a db connection and the client should be disconnected */ 01248 syslog(LOG_USER | LOG_INFO,"Error: database connection failed, forced client disconnect...\n"); 01249 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_connection() idi.dbinfo.connected is '%d'\n", idi.dbinfo.connected); 01250 01251 /* terminate threads */ 01252 terminate_worker_thread(); 01253 terminate_cleanup_thread(); 01254 01255 /* free memory allocated to dynamic buffer */ 01256 ido_dbuf_free(&dbuf); 01257 01258 /* reset db credentials */ 01259 ido2db_db_deinit(&idi); 01260 01261 /* free memory */ 01262 ido2db_free_input_memory(&idi); 01263 ido2db_free_connection_memory(&idi); 01264 01265 /* return error signalling that child is terminating */ 01266 return IDO_ERROR; 01267 } 01268 } 01269 01270 #ifdef HAVE_SSL 01271 if(use_ssl==IDO_TRUE){ 01272 if((ssl=SSL_new(ctx))!=NULL){ 01273 01274 SSL_set_fd(ssl,sd); 01275 01276 /* keep attempting the request if needed */ 01277 while(((result=SSL_accept(ssl))!=1) && (SSL_get_error(ssl,result)==SSL_ERROR_WANT_READ)); 01278 01279 if(result!=1){ 01280 syslog(LOG_ERR,"Error: Could not complete SSL handshake. %d\n",SSL_get_error(ssl,result)); 01281 01282 return IDO_ERROR; 01283 } 01284 } 01285 } 01286 #endif 01287 01288 /* read all data from client */ 01289 while(1){ 01290 #ifdef HAVE_SSL 01291 if(use_ssl==IDO_FALSE) 01292 result=read(sd,buf,sizeof(buf)-1); 01293 else{ 01294 result=SSL_read(ssl,buf,sizeof(buf)-1); 01295 if(result==-1 && (SSL_get_error(ssl,result)==SSL_ERROR_WANT_READ)){ 01296 syslog(LOG_ERR,"SSL read error\n"); 01297 } 01298 } 01299 #else 01300 result=read(sd,buf,sizeof(buf)-1); 01301 #endif 01302 01303 /* bail out on hard errors */ 01304 if(result==-1) { 01305 /* EAGAIN and EINTR are soft errors, so try another read() */ 01306 if (errno==EAGAIN || errno==EINTR) 01307 continue; 01308 else { 01309 error=IDO_TRUE; 01310 #ifdef HAVE_SSL 01311 if(ssl){ 01312 SSL_shutdown(ssl); 01313 SSL_free(ssl); 01314 syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n"); 01315 } 01316 #endif 01317 break; 01318 } 01319 } 01320 01321 /* zero bytes read means we lost the connection with the client */ 01322 if(result==0){ 01323 #ifdef HAVE_SSL 01324 if(ssl){ 01325 SSL_shutdown(ssl); 01326 SSL_free(ssl); 01327 syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n"); 01328 } 01329 #endif 01330 01331 /* gracefully back out of current operation... */ 01332 ido2db_db_goodbye(&idi); 01333 01334 break; 01335 } 01336 01337 #ifdef DEBUG_IDO2DB2 01338 printf("BYTESREAD: %d\n",result); 01339 #endif 01340 01341 /* append data we just read to dynamic buffer */ 01342 buf[result]='\x0'; 01343 /* 2011-02-23 MF: lock dynamic buffer with a mutex when writing */ 01344 pthread_mutex_lock(&ido2db_dbuf_lock); 01345 ido_dbuf_strcat(&dbuf,buf); 01346 pthread_mutex_unlock(&ido2db_dbuf_lock); 01347 01348 /* check for completed lines of input */ 01349 /* 2011-02-23 MF: only do that in a worker thread */ 01350 /* 2011-05-02 MF: redo it the old way */ 01351 01352 ido2db_check_for_client_input(&idi); 01353 01354 01355 /* should we disconnect the client? */ 01356 if(idi.disconnect_client==IDO_TRUE){ 01357 01358 /* gracefully back out of current operation... */ 01359 ido2db_db_goodbye(&idi); 01360 01361 break; 01362 } 01363 } 01364 01365 #ifdef DEBUG_IDO2DB2 01366 printf("BYTES: %lu, LINES: %lu\n",idi.bytes_processed,idi.lines_processed); 01367 #endif 01368 01369 /* terminate threads */ 01370 terminate_worker_thread(); 01371 terminate_cleanup_thread(); 01372 01373 /* free memory allocated to dynamic buffer */ 01374 ido_dbuf_free(&dbuf); 01375 01376 /* disconnect from database */ 01377 ido2db_db_disconnect(&idi); 01378 ido2db_db_deinit(&idi); 01379 01380 /* free memory */ 01381 ido2db_free_input_memory(&idi); 01382 ido2db_free_connection_memory(&idi); 01383 01384 /* close syslog facility */ 01385 /*closelog();*/ 01386 01387 if(error==IDO_TRUE) 01388 return IDO_ERROR; 01389 01390 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_connection() end\n"); 01391 01392 return IDO_OK; 01393 } 01394 01395 01396 /* initializes structure for tracking data */ 01397 int ido2db_idi_init(ido2db_idi *idi){ 01398 int x=0; 01399 01400 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_idi_init() start\n"); 01401 01402 if(idi==NULL) 01403 return IDO_ERROR; 01404 01405 idi->disconnect_client=IDO_FALSE; 01406 idi->ignore_client_data=IDO_FALSE; 01407 idi->protocol_version=0; 01408 idi->instance_name=NULL; 01409 idi->buffered_input=NULL; 01410 idi->agent_name=NULL; 01411 idi->agent_version=NULL; 01412 idi->disposition=NULL; 01413 idi->connect_source=NULL; 01414 idi->connect_type=NULL; 01415 idi->current_input_section=IDO2DB_INPUT_SECTION_NONE; 01416 idi->current_input_data=IDO2DB_INPUT_DATA_NONE; 01417 idi->bytes_processed=0L; 01418 idi->lines_processed=0L; 01419 idi->entries_processed=0L; 01420 idi->current_object_config_type=IDO2DB_CONFIGTYPE_ORIGINAL; 01421 idi->data_start_time=0L; 01422 idi->data_end_time=0L; 01423 01424 /* initialize mbuf */ 01425 for(x=0;x<IDO2DB_MAX_MBUF_ITEMS;x++){ 01426 idi->mbuf[x].used_lines=0; 01427 idi->mbuf[x].allocated_lines=0; 01428 idi->mbuf[x].buffer=NULL; 01429 } 01430 01431 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_idi_init() end\n"); 01432 01433 return IDO_OK; 01434 } 01435 01436 01437 /* checks for single lines of input from a client connection */ 01438 /* 2011-02-23 MF: called in worker thread */ 01439 /* 2011-05-02 MF: restructured sequential */ 01440 int ido2db_check_for_client_input(ido2db_idi *idi){ 01441 char *buf=NULL; 01442 register int x; 01443 01444 //ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_check_for_client_input() start\n"); 01445 01446 /* if(&dbuf==NULL) 01447 return IDO_OK;*/ 01448 if(dbuf.buf==NULL) 01449 return IDO_OK; 01450 /* check if buffer full? bail out and tell main to disconnect the client! FIXME */ 01451 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_check_for_client_input() dbuf.size=%lu\n", dbuf.used_size); 01452 01453 //pthread_mutex_lock(&ido2db_dbuf_lock); 01454 01455 //ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_check_for_client_input() ido2db_dbuf_lock start\n"); 01456 01457 #ifdef DEBUG_IDO2DB2 01458 printf("RAWBUF: %s\n",dbuf.buf); 01459 printf(" USED1: %lu, BYTES: %lu, LINES: %lu\n",dbuf->used_size,idi->bytes_processed,idi->lines_processed); 01460 #endif 01461 01462 /* search for complete lines of input */ 01463 for(x=0;dbuf.buf[x]!='\x0';x++){ 01464 01465 /* we found the end of a line */ 01466 if(dbuf.buf[x]=='\n'){ 01467 01468 #ifdef DEBUG_IDO2DB2 01469 printf("BUF[%d]='\\n'\n",x); 01470 #endif 01471 01472 /* handle this line of input */ 01473 dbuf.buf[x]='\x0'; 01474 01475 if((buf=strdup(dbuf.buf))){ 01476 01477 ido2db_handle_client_input(idi,buf); 01478 01479 free(buf); 01480 buf=NULL; 01481 idi->lines_processed++; 01482 idi->bytes_processed+=(x+1); 01483 } 01484 01485 /* shift data back to front of buffer and adjust counters */ 01486 memmove((void *)&dbuf.buf[0],(void *)&dbuf.buf[x+1],(size_t)((int)dbuf.used_size-x-1)); 01487 dbuf.used_size-=(x+1); 01488 dbuf.buf[dbuf.used_size]='\x0'; 01489 x=-1; 01490 #ifdef DEBUG_IDO2DB2 01491 printf(" USED2: %lu, BYTES: %lu, LINES: %lu\n",dbuf.used_size,idi->bytes_processed,idi->lines_processed); 01492 #endif 01493 } 01494 } 01495 01496 //pthread_mutex_unlock(&ido2db_dbuf_lock); 01497 01498 //ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_check_for_client_input() ido2db_dbuf_lock end\n"); 01499 01500 //ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_check_for_client_input() end\n"); 01501 01502 return IDO_OK; 01503 } 01504 01505 01506 /* handles a single line of input from a client connection */ 01507 int ido2db_handle_client_input(ido2db_idi *idi, char *buf){ 01508 char *var=NULL; 01509 char *val=NULL; 01510 unsigned long data_type_long=0L; 01511 int data_type=IDO_DATA_NONE; 01512 int input_type=IDO2DB_INPUT_DATA_NONE; 01513 01514 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_input(instance_name=%s) start\n", idi->instance_name); 01515 01516 #ifdef DEBUG_IDO2DB2 01517 printf("HANDLING: '%s'\n",buf); 01518 #endif 01519 01520 if(buf==NULL || idi==NULL) 01521 return IDO_ERROR; 01522 01523 /* we're ignoring client data because of wrong protocol version, etc... */ 01524 if(idi->ignore_client_data==IDO_TRUE) 01525 return IDO_ERROR; 01526 01527 /* skip empty lines */ 01528 if(buf[0]=='\x0') 01529 return IDO_OK; 01530 01531 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_input() input_section\n"); 01532 01533 switch(idi->current_input_section){ 01534 01535 case IDO2DB_INPUT_SECTION_NONE: 01536 01537 var=strtok(buf,":"); 01538 val=strtok(NULL,"\n"); 01539 01540 if(!strcmp(var,IDO_API_HELLO)){ 01541 01542 idi->current_input_section=IDO2DB_INPUT_SECTION_HEADER; 01543 idi->current_input_data=IDO2DB_INPUT_DATA_NONE; 01544 01545 /* free old connection memory (necessary in some cases) */ 01546 ido2db_free_connection_memory(idi); 01547 } 01548 01549 break; 01550 01551 case IDO2DB_INPUT_SECTION_HEADER: 01552 01553 var=strtok(buf,":"); 01554 val=strtok(NULL,"\n"); 01555 01556 if(!strcmp(var,IDO_API_STARTDATADUMP)){ 01557 01558 /* client is using wrong protocol version, bail out here... */ 01559 if(idi->protocol_version!=IDO_API_PROTOVERSION){ 01560 syslog(LOG_USER|LOG_INFO,"Error: Client protocol version %d is incompatible with server version %d. Disconnecting client...",idi->protocol_version,IDO_API_PROTOVERSION); 01561 idi->disconnect_client=IDO_TRUE; 01562 idi->ignore_client_data=IDO_TRUE; 01563 return IDO_ERROR; 01564 } 01565 01566 idi->current_input_section=IDO2DB_INPUT_SECTION_DATA; 01567 01568 /* save connection info to DB */ 01569 ido2db_db_hello(idi); 01570 01571 } 01572 01573 else if(!strcmp(var,IDO_API_PROTOCOL)) 01574 ido2db_convert_string_to_int((val+1),&idi->protocol_version); 01575 01576 else if(!strcmp(var,IDO_API_INSTANCENAME)) 01577 idi->instance_name=strdup(val+1); 01578 01579 else if(!strcmp(var,IDO_API_AGENT)) 01580 idi->agent_name=strdup(val+1); 01581 01582 else if(!strcmp(var,IDO_API_AGENTVERSION)) 01583 idi->agent_version=strdup(val+1); 01584 01585 else if(!strcmp(var,IDO_API_DISPOSITION)) 01586 idi->disposition=strdup(val+1); 01587 01588 else if(!strcmp(var,IDO_API_CONNECTION)) 01589 idi->connect_source=strdup(val+1); 01590 01591 else if(!strcmp(var,IDO_API_CONNECTTYPE)) 01592 idi->connect_type=strdup(val+1); 01593 01594 else if(!strcmp(var,IDO_API_STARTTIME)) 01595 ido2db_convert_string_to_unsignedlong((val+1),&idi->data_start_time); 01596 01597 break; 01598 01599 case IDO2DB_INPUT_SECTION_FOOTER: 01600 01601 var=strtok(buf,":"); 01602 val=strtok(NULL,"\n"); 01603 01604 /* client is saying goodbye... */ 01605 if(!strcmp(var,IDO_API_GOODBYE)) 01606 idi->current_input_section=IDO2DB_INPUT_SECTION_NONE; 01607 01608 else if(!strcmp(var,IDO_API_ENDTIME)) 01609 ido2db_convert_string_to_unsignedlong((val+1),&idi->data_end_time); 01610 01611 break; 01612 01613 case IDO2DB_INPUT_SECTION_DATA: 01614 01615 if(idi->current_input_data==IDO2DB_INPUT_DATA_NONE){ 01616 01617 var=strtok(buf,":"); 01618 val=strtok(NULL,"\n"); 01619 01620 input_type=atoi(var); 01621 01622 switch(input_type){ 01623 01624 /* we're reached the end of all of the data... */ 01625 case IDO_API_ENDDATADUMP: 01626 idi->current_input_section=IDO2DB_INPUT_SECTION_FOOTER; 01627 idi->current_input_data=IDO2DB_INPUT_DATA_NONE; 01628 break; 01629 01630 /* config dumps */ 01631 case IDO_API_STARTCONFIGDUMP: 01632 idi->current_input_data=IDO2DB_INPUT_DATA_CONFIGDUMPSTART; 01633 break; 01634 case IDO_API_ENDCONFIGDUMP: 01635 idi->current_input_data=IDO2DB_INPUT_DATA_CONFIGDUMPEND; 01636 break; 01637 01638 /* archived data */ 01639 case IDO_API_LOGENTRY: 01640 idi->current_input_data=IDO2DB_INPUT_DATA_LOGENTRY; 01641 break; 01642 01643 /* realtime data */ 01644 case IDO_API_PROCESSDATA: 01645 idi->current_input_data=IDO2DB_INPUT_DATA_PROCESSDATA; 01646 break; 01647 case IDO_API_TIMEDEVENTDATA: 01648 idi->current_input_data=IDO2DB_INPUT_DATA_TIMEDEVENTDATA; 01649 break; 01650 case IDO_API_LOGDATA: 01651 idi->current_input_data=IDO2DB_INPUT_DATA_LOGDATA; 01652 break; 01653 case IDO_API_SYSTEMCOMMANDDATA: 01654 idi->current_input_data=IDO2DB_INPUT_DATA_SYSTEMCOMMANDDATA; 01655 break; 01656 case IDO_API_EVENTHANDLERDATA: 01657 idi->current_input_data=IDO2DB_INPUT_DATA_EVENTHANDLERDATA; 01658 break; 01659 case IDO_API_NOTIFICATIONDATA: 01660 idi->current_input_data=IDO2DB_INPUT_DATA_NOTIFICATIONDATA; 01661 break; 01662 case IDO_API_SERVICECHECKDATA: 01663 idi->current_input_data=IDO2DB_INPUT_DATA_SERVICECHECKDATA; 01664 break; 01665 case IDO_API_HOSTCHECKDATA: 01666 idi->current_input_data=IDO2DB_INPUT_DATA_HOSTCHECKDATA; 01667 break; 01668 case IDO_API_COMMENTDATA: 01669 idi->current_input_data=IDO2DB_INPUT_DATA_COMMENTDATA; 01670 break; 01671 case IDO_API_DOWNTIMEDATA: 01672 idi->current_input_data=IDO2DB_INPUT_DATA_DOWNTIMEDATA; 01673 break; 01674 case IDO_API_FLAPPINGDATA: 01675 idi->current_input_data=IDO2DB_INPUT_DATA_FLAPPINGDATA; 01676 break; 01677 case IDO_API_PROGRAMSTATUSDATA: 01678 idi->current_input_data=IDO2DB_INPUT_DATA_PROGRAMSTATUSDATA; 01679 break; 01680 case IDO_API_HOSTSTATUSDATA: 01681 idi->current_input_data=IDO2DB_INPUT_DATA_HOSTSTATUSDATA; 01682 break; 01683 case IDO_API_SERVICESTATUSDATA: 01684 idi->current_input_data=IDO2DB_INPUT_DATA_SERVICESTATUSDATA; 01685 break; 01686 case IDO_API_CONTACTSTATUSDATA: 01687 idi->current_input_data=IDO2DB_INPUT_DATA_CONTACTSTATUSDATA; 01688 break; 01689 case IDO_API_ADAPTIVEPROGRAMDATA: 01690 idi->current_input_data=IDO2DB_INPUT_DATA_ADAPTIVEPROGRAMDATA; 01691 break; 01692 case IDO_API_ADAPTIVEHOSTDATA: 01693 idi->current_input_data=IDO2DB_INPUT_DATA_ADAPTIVEHOSTDATA; 01694 break; 01695 case IDO_API_ADAPTIVESERVICEDATA: 01696 idi->current_input_data=IDO2DB_INPUT_DATA_ADAPTIVESERVICEDATA; 01697 break; 01698 case IDO_API_ADAPTIVECONTACTDATA: 01699 idi->current_input_data=IDO2DB_INPUT_DATA_ADAPTIVECONTACTDATA; 01700 break; 01701 case IDO_API_EXTERNALCOMMANDDATA: 01702 idi->current_input_data=IDO2DB_INPUT_DATA_EXTERNALCOMMANDDATA; 01703 break; 01704 case IDO_API_AGGREGATEDSTATUSDATA: 01705 idi->current_input_data=IDO2DB_INPUT_DATA_AGGREGATEDSTATUSDATA; 01706 break; 01707 case IDO_API_RETENTIONDATA: 01708 idi->current_input_data=IDO2DB_INPUT_DATA_RETENTIONDATA; 01709 break; 01710 case IDO_API_CONTACTNOTIFICATIONDATA: 01711 idi->current_input_data=IDO2DB_INPUT_DATA_CONTACTNOTIFICATIONDATA; 01712 break; 01713 case IDO_API_CONTACTNOTIFICATIONMETHODDATA: 01714 idi->current_input_data=IDO2DB_INPUT_DATA_CONTACTNOTIFICATIONMETHODDATA; 01715 break; 01716 case IDO_API_ACKNOWLEDGEMENTDATA: 01717 idi->current_input_data=IDO2DB_INPUT_DATA_ACKNOWLEDGEMENTDATA; 01718 break; 01719 case IDO_API_STATECHANGEDATA: 01720 idi->current_input_data=IDO2DB_INPUT_DATA_STATECHANGEDATA; 01721 break; 01722 01723 /* config variables */ 01724 case IDO_API_MAINCONFIGFILEVARIABLES: 01725 idi->current_input_data=IDO2DB_INPUT_DATA_MAINCONFIGFILEVARIABLES; 01726 break; 01727 case IDO_API_RESOURCECONFIGFILEVARIABLES: 01728 idi->current_input_data=IDO2DB_INPUT_DATA_RESOURCECONFIGFILEVARIABLES; 01729 break; 01730 case IDO_API_CONFIGVARIABLES: 01731 idi->current_input_data=IDO2DB_INPUT_DATA_CONFIGVARIABLES; 01732 break; 01733 case IDO_API_RUNTIMEVARIABLES: 01734 idi->current_input_data=IDO2DB_INPUT_DATA_RUNTIMEVARIABLES; 01735 break; 01736 01737 /* object configuration */ 01738 case IDO_API_HOSTDEFINITION: 01739 idi->current_input_data=IDO2DB_INPUT_DATA_HOSTDEFINITION; 01740 break; 01741 case IDO_API_HOSTGROUPDEFINITION: 01742 idi->current_input_data=IDO2DB_INPUT_DATA_HOSTGROUPDEFINITION; 01743 break; 01744 case IDO_API_SERVICEDEFINITION: 01745 idi->current_input_data=IDO2DB_INPUT_DATA_SERVICEDEFINITION; 01746 break; 01747 case IDO_API_SERVICEGROUPDEFINITION: 01748 idi->current_input_data=IDO2DB_INPUT_DATA_SERVICEGROUPDEFINITION; 01749 break; 01750 case IDO_API_HOSTDEPENDENCYDEFINITION: 01751 idi->current_input_data=IDO2DB_INPUT_DATA_HOSTDEPENDENCYDEFINITION; 01752 break; 01753 case IDO_API_SERVICEDEPENDENCYDEFINITION: 01754 idi->current_input_data=IDO2DB_INPUT_DATA_SERVICEDEPENDENCYDEFINITION; 01755 break; 01756 case IDO_API_HOSTESCALATIONDEFINITION: 01757 idi->current_input_data=IDO2DB_INPUT_DATA_HOSTESCALATIONDEFINITION; 01758 break; 01759 case IDO_API_SERVICEESCALATIONDEFINITION: 01760 idi->current_input_data=IDO2DB_INPUT_DATA_SERVICEESCALATIONDEFINITION; 01761 break; 01762 case IDO_API_COMMANDDEFINITION: 01763 idi->current_input_data=IDO2DB_INPUT_DATA_COMMANDDEFINITION; 01764 break; 01765 case IDO_API_TIMEPERIODDEFINITION: 01766 idi->current_input_data=IDO2DB_INPUT_DATA_TIMEPERIODDEFINITION; 01767 break; 01768 case IDO_API_CONTACTDEFINITION: 01769 idi->current_input_data=IDO2DB_INPUT_DATA_CONTACTDEFINITION; 01770 break; 01771 case IDO_API_CONTACTGROUPDEFINITION: 01772 idi->current_input_data=IDO2DB_INPUT_DATA_CONTACTGROUPDEFINITION; 01773 break; 01774 case IDO_API_HOSTEXTINFODEFINITION: 01775 /* deprecated - merged with host definitions */ 01776 case IDO_API_SERVICEEXTINFODEFINITION: 01777 /* deprecated - merged with service definitions */ 01778 default: 01779 break; 01780 } 01781 01782 /* initialize input data */ 01783 ido2db_start_input_data(idi); 01784 } 01785 01786 /* we are processing some type of data already... */ 01787 else{ 01788 01789 var=strtok(buf,"="); 01790 val=strtok(NULL,"\n"); 01791 01792 /* get the data type */ 01793 data_type_long=strtoul(var,NULL,0); 01794 01795 /* there was an error with the data type - throw it out */ 01796 if(data_type_long==ULONG_MAX && errno==ERANGE) 01797 break; 01798 01799 data_type=(int)data_type_long; 01800 01801 /* the current data section is ending... */ 01802 if(data_type==IDO_API_ENDDATA){ 01803 01804 /* finish current data processing */ 01805 ido2db_end_input_data(idi); 01806 01807 idi->current_input_data=IDO2DB_INPUT_DATA_NONE; 01808 } 01809 01810 /* add data for already existing data type... */ 01811 else{ 01812 01813 /* the data type is out of range - throw it out */ 01814 if(data_type>IDO_MAX_DATA_TYPES){ 01815 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_input() line: %lu, type: %d, VAL: %s\n",idi->lines_processed,data_type,val); 01816 #ifdef DEBUG_IDO2DB2 01817 printf("## DISCARD! LINE: %lu, TYPE: %d, VAL: %s\n",idi->lines_processed,data_type,val); 01818 #endif 01819 break; 01820 } 01821 01822 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_input() line: %lu, type: %d, VAL: %s\n",idi->lines_processed,data_type,val); 01823 #ifdef DEBUG_IDO2DB2 01824 printf("LINE: %lu, TYPE: %d, VAL:%s\n",idi->lines_processed,data_type,val); 01825 #endif 01826 ido2db_add_input_data_item(idi,data_type,val); 01827 } 01828 } 01829 01830 break; 01831 01832 default: 01833 break; 01834 } 01835 01836 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_handle_client_input() end\n"); 01837 return IDO_OK; 01838 } 01839 01840 01841 int ido2db_start_input_data(ido2db_idi *idi){ 01842 int x; 01843 01844 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_start_input_data() start\n"); 01845 01846 if(idi==NULL) 01847 return IDO_ERROR; 01848 01849 /* sometimes ido2db_end_input_data() isn't called, so free memory if we find it */ 01850 ido2db_free_input_memory(idi); 01851 01852 /* allocate memory for holding buffered input */ 01853 if((idi->buffered_input=(char **)malloc(sizeof(char *)*IDO_MAX_DATA_TYPES))==NULL) 01854 return IDO_ERROR; 01855 01856 /* initialize buffered input slots */ 01857 for(x=0;x<IDO_MAX_DATA_TYPES;x++) 01858 idi->buffered_input[x]=NULL; 01859 01860 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_start_input_data() end\n"); 01861 01862 return IDO_OK; 01863 } 01864 01865 01866 int ido2db_add_input_data_item(ido2db_idi *idi, int type, char *buf){ 01867 char *newbuf=NULL; 01868 int mbuf_used=IDO_TRUE; 01869 01870 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_add_input_data_item() start\n"); 01871 01872 if(idi==NULL) 01873 return IDO_ERROR; 01874 01875 /* escape data if necessary */ 01876 switch(type){ 01877 01878 case IDO_DATA_ACKAUTHOR: 01879 case IDO_DATA_ACKDATA: 01880 case IDO_DATA_AUTHORNAME: 01881 case IDO_DATA_CHECKCOMMAND: 01882 case IDO_DATA_COMMANDARGS: 01883 case IDO_DATA_COMMANDLINE: 01884 case IDO_DATA_COMMANDSTRING: 01885 case IDO_DATA_COMMENT: 01886 case IDO_DATA_EVENTHANDLER: 01887 case IDO_DATA_GLOBALHOSTEVENTHANDLER: 01888 case IDO_DATA_GLOBALSERVICEEVENTHANDLER: 01889 case IDO_DATA_HOST: 01890 case IDO_DATA_LOGENTRY: 01891 case IDO_DATA_OUTPUT: 01892 case IDO_DATA_LONGOUTPUT: 01893 case IDO_DATA_PERFDATA: 01894 case IDO_DATA_SERVICE: 01895 case IDO_DATA_PROGRAMNAME: 01896 case IDO_DATA_PROGRAMVERSION: 01897 case IDO_DATA_PROGRAMDATE: 01898 01899 case IDO_DATA_COMMANDNAME: 01900 case IDO_DATA_CONTACTADDRESS: 01901 case IDO_DATA_CONTACTALIAS: 01902 case IDO_DATA_CONTACTGROUP: 01903 case IDO_DATA_CONTACTGROUPALIAS: 01904 case IDO_DATA_CONTACTGROUPMEMBER: 01905 case IDO_DATA_CONTACTGROUPNAME: 01906 case IDO_DATA_CONTACTNAME: 01907 case IDO_DATA_DEPENDENTHOSTNAME: 01908 case IDO_DATA_DEPENDENTSERVICEDESCRIPTION: 01909 case IDO_DATA_DISPLAYNAME: 01910 case IDO_DATA_EMAILADDRESS: 01911 case IDO_DATA_HOSTADDRESS: 01912 case IDO_DATA_HOSTADDRESS6: 01913 case IDO_DATA_HOSTALIAS: 01914 case IDO_DATA_HOSTCHECKCOMMAND: 01915 case IDO_DATA_HOSTCHECKPERIOD: 01916 case IDO_DATA_HOSTEVENTHANDLER: 01917 case IDO_DATA_HOSTFAILUREPREDICTIONOPTIONS: 01918 case IDO_DATA_HOSTGROUPALIAS: 01919 case IDO_DATA_HOSTGROUPMEMBER: 01920 case IDO_DATA_HOSTGROUPNAME: 01921 case IDO_DATA_HOSTNAME: 01922 case IDO_DATA_HOSTNOTIFICATIONCOMMAND: 01923 case IDO_DATA_HOSTNOTIFICATIONPERIOD: 01924 case IDO_DATA_PAGERADDRESS: 01925 case IDO_DATA_PARENTHOST: 01926 case IDO_DATA_SERVICECHECKCOMMAND: 01927 case IDO_DATA_SERVICECHECKPERIOD: 01928 case IDO_DATA_SERVICEDESCRIPTION: 01929 case IDO_DATA_SERVICEEVENTHANDLER: 01930 case IDO_DATA_SERVICEFAILUREPREDICTIONOPTIONS: 01931 case IDO_DATA_SERVICEGROUPALIAS: 01932 case IDO_DATA_SERVICEGROUPMEMBER: 01933 case IDO_DATA_SERVICEGROUPNAME: 01934 case IDO_DATA_SERVICENOTIFICATIONCOMMAND: 01935 case IDO_DATA_SERVICENOTIFICATIONPERIOD: 01936 case IDO_DATA_TIMEPERIODALIAS: 01937 case IDO_DATA_TIMEPERIODNAME: 01938 case IDO_DATA_TIMERANGE: 01939 01940 case IDO_DATA_ACTIONURL: 01941 case IDO_DATA_ICONIMAGE: 01942 case IDO_DATA_ICONIMAGEALT: 01943 case IDO_DATA_NOTES: 01944 case IDO_DATA_NOTESURL: 01945 case IDO_DATA_CUSTOMVARIABLE: 01946 case IDO_DATA_CONTACT: 01947 01948 /* strings are escaped when they arrive */ 01949 if(buf==NULL) 01950 newbuf=strdup(""); 01951 else 01952 newbuf=strdup(buf); 01953 ido_unescape_buffer(newbuf); 01954 break; 01955 01956 default: 01957 01958 /* data hasn't been escaped */ 01959 if(buf==NULL) 01960 newbuf=strdup(""); 01961 else 01962 newbuf=strdup(buf); 01963 break; 01964 } 01965 01966 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_add_input_data_item(%s)\n", newbuf); 01967 01968 /* check for errors */ 01969 if(newbuf==NULL){ 01970 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_add_input_data_item() allocation error\n"); 01971 #ifdef DEBUG_IDO2DB 01972 printf("ALLOCATION ERROR\n"); 01973 #endif 01974 return IDO_ERROR; 01975 } 01976 01977 /* store the buffered data */ 01978 switch(type){ 01979 01980 /* special case for data items that may appear multiple times */ 01981 case IDO_DATA_CONTACTGROUP: 01982 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_CONTACTGROUP,newbuf); 01983 break; 01984 case IDO_DATA_CONTACTGROUPMEMBER: 01985 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_CONTACTGROUPMEMBER,newbuf); 01986 break; 01987 case IDO_DATA_SERVICEGROUPMEMBER: 01988 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_SERVICEGROUPMEMBER,newbuf); 01989 break; 01990 case IDO_DATA_HOSTGROUPMEMBER: 01991 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_HOSTGROUPMEMBER,newbuf); 01992 break; 01993 case IDO_DATA_SERVICENOTIFICATIONCOMMAND: 01994 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_SERVICENOTIFICATIONCOMMAND,newbuf); 01995 break; 01996 case IDO_DATA_HOSTNOTIFICATIONCOMMAND: 01997 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_HOSTNOTIFICATIONCOMMAND,newbuf); 01998 break; 01999 case IDO_DATA_CONTACTADDRESS: 02000 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_CONTACTADDRESS,newbuf); 02001 break; 02002 case IDO_DATA_TIMERANGE: 02003 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_TIMERANGE,newbuf); 02004 break; 02005 case IDO_DATA_PARENTHOST: 02006 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_PARENTHOST,newbuf); 02007 break; 02008 case IDO_DATA_CONFIGFILEVARIABLE: 02009 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_CONFIGFILEVARIABLE,newbuf); 02010 break; 02011 case IDO_DATA_CONFIGVARIABLE: 02012 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_CONFIGVARIABLE,newbuf); 02013 break; 02014 case IDO_DATA_RUNTIMEVARIABLE: 02015 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_RUNTIMEVARIABLE,newbuf); 02016 break; 02017 case IDO_DATA_CUSTOMVARIABLE: 02018 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_CUSTOMVARIABLE,newbuf); 02019 break; 02020 case IDO_DATA_CONTACT: 02021 ido2db_add_input_data_mbuf(idi,type,IDO2DB_MBUF_CONTACT,newbuf); 02022 break; 02023 02024 /* NORMAL DATA */ 02025 /* normal data items appear only once per data type */ 02026 default: 02027 02028 mbuf_used=IDO_FALSE; 02029 02030 /* if there was already a matching item, discard the old one */ 02031 if(idi->buffered_input[type]!=NULL){ 02032 free(idi->buffered_input[type]); 02033 idi->buffered_input[type]=NULL; 02034 } 02035 02036 /* save buffered item */ 02037 idi->buffered_input[type]=newbuf; 02038 } 02039 02040 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_start_input_data() end\n"); 02041 return IDO_OK; 02042 } 02043 02044 02045 02046 int ido2db_add_input_data_mbuf(ido2db_idi *idi, int type, int mbuf_slot, char *buf){ 02047 int allocation_chunk=80; 02048 char **newbuffer=NULL; 02049 02050 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_add_input_data_mbuf() start\n"); 02051 02052 if(idi==NULL || buf==NULL) 02053 return IDO_ERROR; 02054 02055 if(mbuf_slot>=IDO2DB_MAX_MBUF_ITEMS) 02056 return IDO_ERROR; 02057 02058 /* create buffer */ 02059 if(idi->mbuf[mbuf_slot].buffer==NULL){ 02060 #ifdef IDO2DB_DEBUG_MBUF 02061 mbuf_bytes_allocated+=sizeof(char *)*allocation_chunk; 02062 printf("MBUF INITIAL ALLOCATION (MBUF = %lu bytes)\n",mbuf_bytes_allocated); 02063 #endif 02064 idi->mbuf[mbuf_slot].buffer=(char **)malloc(sizeof(char *)*allocation_chunk); 02065 idi->mbuf[mbuf_slot].allocated_lines+=allocation_chunk; 02066 } 02067 02068 /* expand buffer */ 02069 if(idi->mbuf[mbuf_slot].used_lines==idi->mbuf[mbuf_slot].allocated_lines){ 02070 newbuffer=(char **)realloc(idi->mbuf[mbuf_slot].buffer,sizeof(char *)*(idi->mbuf[mbuf_slot].allocated_lines+allocation_chunk)); 02071 if(newbuffer==NULL) 02072 return IDO_ERROR; 02073 #ifdef IDO2DB_DEBUG_MBUF 02074 mbuf_bytes_allocated+=sizeof(char *)*allocation_chunk; 02075 printf("MBUF RESIZED (MBUF = %lu bytes)\n",mbuf_bytes_allocated); 02076 #endif 02077 idi->mbuf[mbuf_slot].buffer=newbuffer; 02078 idi->mbuf[mbuf_slot].allocated_lines+=allocation_chunk; 02079 } 02080 02081 /* store the data */ 02082 if(idi->mbuf[mbuf_slot].buffer){ 02083 idi->mbuf[mbuf_slot].buffer[idi->mbuf[mbuf_slot].used_lines]=buf; 02084 idi->mbuf[mbuf_slot].used_lines++; 02085 } 02086 else 02087 return IDO_ERROR; 02088 02089 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_add_input_data_mbuf() end\n"); 02090 return IDO_OK; 02091 } 02092 02093 02094 02095 int ido2db_end_input_data(ido2db_idi *idi){ 02096 int result=IDO_OK; 02097 02098 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_end_input_data() start\n"); 02099 02100 if(idi==NULL) 02101 return IDO_ERROR; 02102 02103 /* update db stats occassionally */ 02104 if(ido2db_db_last_checkin_time<(time(NULL)-60)) 02105 ido2db_db_checkin(idi); 02106 02107 #ifdef DEBUG_IDO2DB2 02108 printf("HANDLING TYPE: %d\n",idi->current_input_data); 02109 #endif 02110 02111 switch(idi->current_input_data){ 02112 02113 /* archived log entries */ 02114 case IDO2DB_INPUT_DATA_LOGENTRY: 02115 result=ido2db_handle_logentry(idi); 02116 break; 02117 02118 /* realtime Icinga data */ 02119 case IDO2DB_INPUT_DATA_PROCESSDATA: 02120 result=ido2db_handle_processdata(idi); 02121 break; 02122 case IDO2DB_INPUT_DATA_TIMEDEVENTDATA: 02123 result=ido2db_handle_timedeventdata(idi); 02124 break; 02125 case IDO2DB_INPUT_DATA_LOGDATA: 02126 result=ido2db_handle_logdata(idi); 02127 break; 02128 case IDO2DB_INPUT_DATA_SYSTEMCOMMANDDATA: 02129 result=ido2db_handle_systemcommanddata(idi); 02130 break; 02131 case IDO2DB_INPUT_DATA_EVENTHANDLERDATA: 02132 result=ido2db_handle_eventhandlerdata(idi); 02133 break; 02134 case IDO2DB_INPUT_DATA_NOTIFICATIONDATA: 02135 result=ido2db_handle_notificationdata(idi); 02136 break; 02137 case IDO2DB_INPUT_DATA_SERVICECHECKDATA: 02138 result=ido2db_handle_servicecheckdata(idi); 02139 break; 02140 case IDO2DB_INPUT_DATA_HOSTCHECKDATA: 02141 result=ido2db_handle_hostcheckdata(idi); 02142 break; 02143 case IDO2DB_INPUT_DATA_COMMENTDATA: 02144 result=ido2db_handle_commentdata(idi); 02145 break; 02146 case IDO2DB_INPUT_DATA_DOWNTIMEDATA: 02147 result=ido2db_handle_downtimedata(idi); 02148 break; 02149 case IDO2DB_INPUT_DATA_FLAPPINGDATA: 02150 result=ido2db_handle_flappingdata(idi); 02151 break; 02152 case IDO2DB_INPUT_DATA_PROGRAMSTATUSDATA: 02153 result=ido2db_handle_programstatusdata(idi); 02154 break; 02155 case IDO2DB_INPUT_DATA_HOSTSTATUSDATA: 02156 result=ido2db_handle_hoststatusdata(idi); 02157 break; 02158 case IDO2DB_INPUT_DATA_SERVICESTATUSDATA: 02159 result=ido2db_handle_servicestatusdata(idi); 02160 break; 02161 case IDO2DB_INPUT_DATA_CONTACTSTATUSDATA: 02162 result=ido2db_handle_contactstatusdata(idi); 02163 break; 02164 case IDO2DB_INPUT_DATA_ADAPTIVEPROGRAMDATA: 02165 result=ido2db_handle_adaptiveprogramdata(idi); 02166 break; 02167 case IDO2DB_INPUT_DATA_ADAPTIVEHOSTDATA: 02168 result=ido2db_handle_adaptivehostdata(idi); 02169 break; 02170 case IDO2DB_INPUT_DATA_ADAPTIVESERVICEDATA: 02171 result=ido2db_handle_adaptiveservicedata(idi); 02172 break; 02173 case IDO2DB_INPUT_DATA_ADAPTIVECONTACTDATA: 02174 result=ido2db_handle_adaptivecontactdata(idi); 02175 break; 02176 case IDO2DB_INPUT_DATA_EXTERNALCOMMANDDATA: 02177 result=ido2db_handle_externalcommanddata(idi); 02178 break; 02179 case IDO2DB_INPUT_DATA_AGGREGATEDSTATUSDATA: 02180 result=ido2db_handle_aggregatedstatusdata(idi); 02181 break; 02182 case IDO2DB_INPUT_DATA_RETENTIONDATA: 02183 result=ido2db_handle_retentiondata(idi); 02184 break; 02185 case IDO2DB_INPUT_DATA_CONTACTNOTIFICATIONDATA: 02186 result=ido2db_handle_contactnotificationdata(idi); 02187 break; 02188 case IDO2DB_INPUT_DATA_CONTACTNOTIFICATIONMETHODDATA: 02189 result=ido2db_handle_contactnotificationmethoddata(idi); 02190 break; 02191 case IDO2DB_INPUT_DATA_ACKNOWLEDGEMENTDATA: 02192 result=ido2db_handle_acknowledgementdata(idi); 02193 break; 02194 case IDO2DB_INPUT_DATA_STATECHANGEDATA: 02195 result=ido2db_handle_statechangedata(idi); 02196 break; 02197 02198 /* config file and variable dumps */ 02199 case IDO2DB_INPUT_DATA_MAINCONFIGFILEVARIABLES: 02200 result=ido2db_handle_configfilevariables(idi,0); 02201 break; 02202 case IDO2DB_INPUT_DATA_RESOURCECONFIGFILEVARIABLES: 02203 result=ido2db_handle_configfilevariables(idi,1); 02204 break; 02205 case IDO2DB_INPUT_DATA_CONFIGVARIABLES: 02206 result=ido2db_handle_configvariables(idi); 02207 break; 02208 case IDO2DB_INPUT_DATA_RUNTIMEVARIABLES: 02209 result=ido2db_handle_runtimevariables(idi); 02210 break; 02211 case IDO2DB_INPUT_DATA_CONFIGDUMPSTART: 02212 result=ido2db_handle_configdumpstart(idi); 02213 break; 02214 case IDO2DB_INPUT_DATA_CONFIGDUMPEND: 02215 result=ido2db_handle_configdumpend(idi); 02216 break; 02217 02218 /* config definitions */ 02219 case IDO2DB_INPUT_DATA_HOSTDEFINITION: 02220 result=ido2db_handle_hostdefinition(idi); 02221 break; 02222 case IDO2DB_INPUT_DATA_HOSTGROUPDEFINITION: 02223 result=ido2db_handle_hostgroupdefinition(idi); 02224 break; 02225 case IDO2DB_INPUT_DATA_SERVICEDEFINITION: 02226 result=ido2db_handle_servicedefinition(idi); 02227 break; 02228 case IDO2DB_INPUT_DATA_SERVICEGROUPDEFINITION: 02229 result=ido2db_handle_servicegroupdefinition(idi); 02230 break; 02231 case IDO2DB_INPUT_DATA_HOSTDEPENDENCYDEFINITION: 02232 result=ido2db_handle_hostdependencydefinition(idi); 02233 break; 02234 case IDO2DB_INPUT_DATA_SERVICEDEPENDENCYDEFINITION: 02235 result=ido2db_handle_servicedependencydefinition(idi); 02236 break; 02237 case IDO2DB_INPUT_DATA_HOSTESCALATIONDEFINITION: 02238 result=ido2db_handle_hostescalationdefinition(idi); 02239 break; 02240 case IDO2DB_INPUT_DATA_SERVICEESCALATIONDEFINITION: 02241 result=ido2db_handle_serviceescalationdefinition(idi); 02242 break; 02243 case IDO2DB_INPUT_DATA_COMMANDDEFINITION: 02244 result=ido2db_handle_commanddefinition(idi); 02245 break; 02246 case IDO2DB_INPUT_DATA_TIMEPERIODDEFINITION: 02247 result=ido2db_handle_timeperiodefinition(idi); 02248 break; 02249 case IDO2DB_INPUT_DATA_CONTACTDEFINITION: 02250 result=ido2db_handle_contactdefinition(idi); 02251 break; 02252 case IDO2DB_INPUT_DATA_CONTACTGROUPDEFINITION: 02253 result=ido2db_handle_contactgroupdefinition(idi); 02254 break; 02255 case IDO2DB_INPUT_DATA_HOSTEXTINFODEFINITION: 02256 /* deprecated - merged with host definitions */ 02257 break; 02258 case IDO2DB_INPUT_DATA_SERVICEEXTINFODEFINITION: 02259 /* deprecated - merged with service definitions */ 02260 break; 02261 02262 default: 02263 break; 02264 } 02265 02266 /* free input memory */ 02267 ido2db_free_input_memory(idi); 02268 02269 /* adjust items processed */ 02270 idi->entries_processed++; 02271 02272 /* perform periodic maintenance... */ 02273 //ido2db_db_perform_maintenance(idi); 02274 02275 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_end_input_data() end\n"); 02276 return result; 02277 } 02278 02279 02280 /* free memory allocated to data input */ 02281 int ido2db_free_input_memory(ido2db_idi *idi){ 02282 register int x=0; 02283 register int y=0; 02284 02285 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_free_input_memory() start\n"); 02286 02287 if(idi==NULL) 02288 return IDO_ERROR; 02289 02290 /* free memory allocated to single-instance data buffers */ 02291 if(idi->buffered_input){ 02292 02293 for(x=0;x<IDO_MAX_DATA_TYPES;x++){ 02294 if(idi->buffered_input[x]) 02295 free(idi->buffered_input[x]); 02296 idi->buffered_input[x]=NULL; 02297 } 02298 02299 free(idi->buffered_input); 02300 idi->buffered_input=NULL; 02301 } 02302 02303 /* free memory allocated to multi-instance data buffers */ 02304 if(idi->mbuf){ 02305 for(x=0;x<IDO2DB_MAX_MBUF_ITEMS;x++){ 02306 if(idi->mbuf[x].buffer){ 02307 for(y=0;y<idi->mbuf[x].used_lines;y++){ 02308 if(idi->mbuf[x].buffer[y]){ 02309 free(idi->mbuf[x].buffer[y]); 02310 idi->mbuf[x].buffer[y]=NULL; 02311 } 02312 } 02313 free(idi->mbuf[x].buffer); 02314 idi->mbuf[x].buffer=NULL; 02315 } 02316 idi->mbuf[x].used_lines=0; 02317 idi->mbuf[x].allocated_lines=0; 02318 } 02319 } 02320 02321 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_free_input_memory() end\n"); 02322 return IDO_OK; 02323 } 02324 02325 02326 /* free memory allocated to connection */ 02327 int ido2db_free_connection_memory(ido2db_idi *idi){ 02328 02329 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_free_connection_memory() start\n"); 02330 02331 if(idi->instance_name){ 02332 free(idi->instance_name); 02333 idi->instance_name=NULL; 02334 } 02335 if(idi->agent_name){ 02336 free(idi->agent_name); 02337 idi->agent_name=NULL; 02338 } 02339 if(idi->agent_version){ 02340 free(idi->agent_version); 02341 idi->agent_version=NULL; 02342 } 02343 if(idi->disposition){ 02344 free(idi->disposition); 02345 idi->disposition=NULL; 02346 } 02347 if(idi->connect_source){ 02348 free(idi->connect_source); 02349 idi->connect_source=NULL; 02350 } 02351 if(idi->connect_type){ 02352 free(idi->connect_type); 02353 idi->connect_type=NULL; 02354 } 02355 02356 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_free_connection_memory() end\n"); 02357 return IDO_OK; 02358 } 02359 02360 02361 02362 /****************************************************************************/ 02363 /* DATA TYPE CONVERTION ROUTINES */ 02364 /****************************************************************************/ 02365 02366 int ido2db_convert_standard_data_elements(ido2db_idi *idi, int *type, int *flags, int *attr, struct timeval *tstamp){ 02367 int result1=IDO_OK; 02368 int result2=IDO_OK; 02369 int result3=IDO_OK; 02370 int result4=IDO_OK; 02371 02372 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_standard_data_elements() start\n"); 02373 02374 result1=ido2db_convert_string_to_int(idi->buffered_input[IDO_DATA_TYPE],type); 02375 result2=ido2db_convert_string_to_int(idi->buffered_input[IDO_DATA_FLAGS],flags); 02376 result3=ido2db_convert_string_to_int(idi->buffered_input[IDO_DATA_ATTRIBUTES],attr); 02377 result4=ido2db_convert_string_to_timeval(idi->buffered_input[IDO_DATA_TIMESTAMP],tstamp); 02378 02379 if(result1==IDO_ERROR || result2==IDO_ERROR || result3==IDO_ERROR || result4==IDO_ERROR) 02380 return IDO_ERROR; 02381 02382 02383 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_standard_data_elements() end\n"); 02384 return IDO_OK; 02385 } 02386 02387 02388 int ido2db_convert_string_to_int(char *buf, int *i){ 02389 02390 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_int(%s) start\n", buf); 02391 02392 if(buf==NULL) 02393 return IDO_ERROR; 02394 02395 *i=atoi(buf); 02396 02397 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_int(%d) end\n", i); 02398 return IDO_OK; 02399 } 02400 02401 02402 int ido2db_convert_string_to_float(char *buf, float *f){ 02403 char *endptr=NULL; 02404 02405 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_float(%s) start\n", buf); 02406 02407 if(buf==NULL) 02408 return IDO_ERROR; 02409 02410 #ifdef HAVE_STRTOF 02411 *f=strtof(buf,&endptr); 02412 #else 02413 /* Solaris 8 doesn't have strtof() */ 02414 *f=(float)strtod(buf,&endptr); 02415 #endif 02416 02417 if(*f==0 && (endptr==buf || errno==ERANGE)) 02418 return IDO_ERROR; 02419 if(errno==ERANGE) 02420 return IDO_ERROR; 02421 02422 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_float(%f) end\n", f); 02423 return IDO_OK; 02424 } 02425 02426 02427 int ido2db_convert_string_to_double(char *buf, double *d){ 02428 char *endptr=NULL; 02429 02430 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_double(%s) start\n", buf); 02431 if(buf==NULL) 02432 return IDO_ERROR; 02433 02434 *d=strtod(buf,&endptr); 02435 02436 if(*d==0 && (endptr==buf || errno==ERANGE)) 02437 return IDO_ERROR; 02438 if(errno==ERANGE) 02439 return IDO_ERROR; 02440 02441 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_double(%lf) end\n", d); 02442 return IDO_OK; 02443 } 02444 02445 02446 int ido2db_convert_string_to_long(char *buf, long *l){ 02447 char *endptr=NULL; 02448 02449 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_long(%s) start\n", buf); 02450 02451 if(buf==NULL) 02452 return IDO_ERROR; 02453 02454 *l=strtol(buf,&endptr,0); 02455 02456 if(*l==LONG_MAX && errno==ERANGE) 02457 return IDO_ERROR; 02458 if(*l==0L && endptr==buf) 02459 return IDO_ERROR; 02460 02461 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_long(%l) end\n", l); 02462 return IDO_OK; 02463 } 02464 02465 02466 int ido2db_convert_string_to_unsignedlong(char *buf, unsigned long *ul){ 02467 char *endptr=NULL; 02468 02469 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_unsignedlong(%s) start\n", buf); 02470 02471 if(buf==NULL) 02472 return IDO_ERROR; 02473 02474 *ul=strtoul(buf,&endptr,0); 02475 if(*ul==ULONG_MAX && errno==ERANGE) 02476 return IDO_ERROR; 02477 if(*ul==0L && endptr==buf) 02478 return IDO_ERROR; 02479 02480 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_unsignedlong(%lu) end\n", ul); 02481 return IDO_OK; 02482 } 02483 02484 02485 int ido2db_convert_string_to_timeval(char *buf, struct timeval *tv){ 02486 char *newbuf=NULL; 02487 char *ptr=NULL; 02488 int result=IDO_OK; 02489 02490 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_timeval(%s) start\n", buf); 02491 02492 if(buf==NULL) 02493 return IDO_ERROR; 02494 02495 tv->tv_sec=(time_t)0L; 02496 tv->tv_usec=(suseconds_t)0L; 02497 02498 if((newbuf=strdup(buf))==NULL) 02499 return IDO_ERROR; 02500 02501 ptr=strtok(newbuf,"."); 02502 if((result=ido2db_convert_string_to_unsignedlong(ptr,(unsigned long *)&tv->tv_sec))==IDO_OK){ 02503 ptr=strtok(NULL,"\n"); 02504 result=ido2db_convert_string_to_unsignedlong(ptr,(unsigned long *)&tv->tv_usec); 02505 } 02506 02507 free(newbuf); 02508 02509 if(result==IDO_ERROR) 02510 return IDO_ERROR; 02511 02512 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_convert_string_to_timeval() end\n"); 02513 return IDO_OK; 02514 } 02515 02516 02517 02518 /****************************************************************************/ 02519 /* LOGGING ROUTINES */ 02520 /****************************************************************************/ 02521 02522 /* opens the debug log for writing */ 02523 int ido2db_open_debug_log(void){ 02524 02525 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_open_debug_log() start\n"); 02526 02527 /* don't do anything if we're not debugging */ 02528 if(ido2db_debug_level==IDO2DB_DEBUGL_NONE) 02529 return IDO_OK; 02530 02531 if((ido2db_debug_file_fp=fopen(ido2db_debug_file,"a+"))==NULL) { 02532 syslog(LOG_ERR, "Warning: Could not open debug file '%s' - '%s'", ido2db_debug_file, strerror(errno)); 02533 return IDO_ERROR; 02534 } 02535 02536 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_open_debug_log() end\n"); 02537 02538 return IDO_OK; 02539 } 02540 02541 02542 /* closes the debug log */ 02543 int ido2db_close_debug_log(void){ 02544 02545 if(ido2db_debug_file_fp!=NULL) 02546 fclose(ido2db_debug_file_fp); 02547 02548 ido2db_debug_file_fp=NULL; 02549 02550 return IDO_OK; 02551 } 02552 02553 02554 /* write to the debug log */ 02555 int ido2db_log_debug_info(int level, int verbosity, const char *fmt, ...){ 02556 va_list ap; 02557 char *temp_path=NULL; 02558 struct timeval current_time; 02559 02560 if(!(ido2db_debug_level==IDO2DB_DEBUGL_ALL || (level & ido2db_debug_level))) 02561 return IDO_OK; 02562 02563 if(verbosity>ido2db_debug_verbosity) 02564 return IDO_OK; 02565 02566 if(ido2db_debug_file_fp==NULL) 02567 return IDO_ERROR; 02568 02569 /* write the timestamp */ 02570 gettimeofday(¤t_time,NULL); 02571 fprintf(ido2db_debug_file_fp,"[%lu.%06lu] [%03d.%d] [pid=%lu] ",current_time.tv_sec,current_time.tv_usec,level,verbosity,(unsigned long)getpid()); 02572 02573 /* write the data */ 02574 va_start(ap,fmt); 02575 vfprintf(ido2db_debug_file_fp,fmt,ap); 02576 va_end(ap); 02577 02578 /* flush, so we don't have problems tailing or when fork()ing */ 02579 fflush(ido2db_debug_file_fp); 02580 02581 /* if file has grown beyond max, rotate it */ 02582 if((unsigned long)ftell(ido2db_debug_file_fp)>ido2db_max_debug_file_size && ido2db_max_debug_file_size>0L){ 02583 02584 /* close the file */ 02585 ido2db_close_debug_log(); 02586 02587 /* rotate the log file */ 02588 if(asprintf(&temp_path,"%s.old",ido2db_debug_file)==-1) 02589 temp_path=NULL; 02590 02591 if(temp_path){ 02592 02593 /* unlink the old debug file */ 02594 unlink(temp_path); 02595 02596 /* rotate the debug file */ 02597 my_rename(ido2db_debug_file,temp_path); 02598 02599 /* free memory */ 02600 my_free(temp_path); 02601 } 02602 02603 /* open a new file */ 02604 ido2db_open_debug_log(); 02605 } 02606 02607 return IDO_OK; 02608 } 02609 02610 02611 /******************************************************************** 02612 * 02613 * working on dbuf - this is the function for the buffer reading thread 02614 * 02615 ********************************************************************/ 02616 02617 void * ido2db_thread_worker(void *data) { 02618 02619 ido2db_idi *idi = (ido2db_idi*) data; 02620 02621 struct timespec delay; 02622 delay.tv_sec = 5; 02623 delay.tv_nsec = 500000; 02624 nanosleep(&delay, NULL); 02625 delay.tv_sec = 0; 02626 02627 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_worker() start\n"); 02628 02629 /* specify cleanup routine */ 02630 pthread_cleanup_push((void *) &ido2db_thread_worker_exit_handler, NULL); 02631 02632 /* set cancellation info */ 02633 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); 02634 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); 02635 02636 while(1){ 02637 02638 /* should we shutdown? */ 02639 pthread_testcancel(); 02640 02641 /* sleep a bit */ 02642 nanosleep(&delay, NULL); 02643 02644 if(idi->disconnect_client==IDO_TRUE){ 02645 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_worker(): origin idi said we should disconnect the client\n"); 02646 break; 02647 } 02648 02649 /* check for client input */ 02650 //ido2db_check_for_client_input(idi); 02651 02652 /* sleep a bit */ 02653 nanosleep(&delay, NULL); 02654 02655 /* should we shutdown? */ 02656 pthread_testcancel(); 02657 } 02658 02659 pthread_cleanup_pop(0); 02660 02661 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_worker() end\n"); 02662 02663 pthread_exit((void *) pthread_self()); 02664 } 02665 02666 /* ****************************************************************** 02667 * 02668 * exit_handler_mem is called as thread canceling 02669 * 02670 * ******************************************************************/ 02671 02672 static void *ido2db_thread_worker_exit_handler(void * arg) { 02673 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_worker() cleanup_exit_handler...\n"); 02674 return 0; 02675 02676 } 02677 02678 02679 /******************************************************************** 02680 * 02681 * housekeeping - this is the function for the db trimming thread 02682 * 02683 ********************************************************************/ 02684 02685 void * ido2db_thread_cleanup(void *data) { 02686 02687 ido2db_idi *idi = (ido2db_idi*) data; 02688 02689 struct timespec delay; 02690 delay.tv_sec = 0; 02691 delay.tv_nsec = 500; 02692 02693 /* it might happen that db connection comes to fast after main thread so sleep a while */ 02694 //delay.tv_sec = 60; 02695 /* allowed to be set in config */ 02696 delay.tv_sec = ido2db_db_settings.housekeeping_thread_startup_delay; 02697 02698 /* the minimum is the default, otherwise overwrite */ 02699 if(delay.tv_sec<DEFAULT_HOUSEKEEPING_THREAD_STARTUP_DELAY) 02700 delay.tv_sec=DEFAULT_HOUSEKEEPING_THREAD_STARTUP_DELAY; 02701 02702 nanosleep(&delay, NULL); 02703 02704 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_cleanup() start\n"); 02705 02706 /* initialize input data information */ 02707 ido2db_idi_init(&thread_idi); 02708 02709 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_cleanup() initialize thread db connection\n"); 02710 02711 /* initialize database connection */ 02712 ido2db_db_init(&thread_idi); 02713 02714 if(ido2db_db_connect(&thread_idi)==IDO_ERROR){ 02715 02716 /* tell main process to disconnect */ 02717 idi->disconnect_client=IDO_TRUE; 02718 02719 /* cleanup the thread */ 02720 ido2db_db_deinit(&thread_idi); 02721 02722 /* free memory */ 02723 ido2db_free_input_memory(&thread_idi); 02724 ido2db_free_connection_memory(&thread_idi); 02725 02726 return (void*)IDO_ERROR; 02727 } 02728 02729 /* specify cleanup routine */ 02730 pthread_cleanup_push((void *) &ido2db_thread_cleanup_exit_handler, NULL); 02731 02732 delay.tv_sec = 0; 02733 delay.tv_nsec = 500; 02734 02735 /* keep on looping for an instance name from main thread */ 02736 while(idi->instance_name==NULL) { 02737 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_cleanup() nanosleeping cause missing instance_name...\n"); 02738 nanosleep(&delay, NULL); 02739 } 02740 02741 02742 /* copy needed idi information */ 02743 thread_idi.instance_name = idi->instance_name; 02744 thread_idi.agent_name = "IDO2DB Trimming Thread"; 02745 thread_idi.agent_version = idi->agent_version; 02746 thread_idi.disposition = idi->disposition; 02747 thread_idi.connect_source = idi->connect_source; 02748 thread_idi.connect_type = idi->connect_type; 02749 02750 delay.tv_sec = 5; 02751 02752 /* save connection info to DB */ 02753 while(ido2db_thread_db_hello(&thread_idi) == IDO_ERROR) { 02754 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_cleanup() no instance found, sleeping...\n"); 02755 nanosleep(&delay, NULL); 02756 } 02757 02758 while(1){ 02759 02760 /* should we shutdown? */ 02761 pthread_testcancel(); 02762 02763 if(idi->disconnect_client==IDO_TRUE){ 02764 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_cleanup(): origin idi said we should disconnect the client\n"); 02765 break; 02766 } 02767 02768 /* Perfom DB Maintenance */ 02769 ido2db_db_perform_maintenance(&thread_idi); 02770 02771 /* should we shutdown? */ 02772 pthread_testcancel(); 02773 02774 sleep(thread_idi.dbinfo.trim_db_interval+1); 02775 } 02776 02777 /* gracefully back out of current operation... */ 02778 ido2db_db_goodbye(&thread_idi); 02779 02780 /* disconnect from database */ 02781 ido2db_db_disconnect(&thread_idi); 02782 ido2db_db_deinit(&thread_idi); 02783 02784 /* free memory */ 02785 ido2db_free_input_memory(&thread_idi); 02786 ido2db_free_connection_memory(&thread_idi); 02787 02788 pthread_cleanup_pop(0); 02789 02790 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_cleanup() end\n"); 02791 02792 pthread_exit((void *) pthread_self()); 02793 } 02794 02795 /* ****************************************************************** 02796 * 02797 * exit_handler_mem is called as thread canceling 02798 * 02799 * ******************************************************************/ 02800 02801 static void *ido2db_thread_cleanup_exit_handler(void * arg) { 02802 ido2db_log_debug_info(IDO2DB_DEBUGL_PROCESSINFO, 2, "ido2db_thread_cleanup() cleanup_exit_handler...\n"); 02803 return 0; 02804 02805 } 02806 02807 int ido2db_terminate_threads(void){ 02808 02809 int result; 02810 02811 /* from cleaner thread */ 02812 ido2db_db_disconnect(&thread_idi); 02813 ido2db_db_deinit(&thread_idi); 02814 02815 /* terminate each thread on its own */ 02816 result=terminate_worker_thread(); 02817 result=terminate_cleanup_thread(); 02818 02819 return IDO_OK; 02820 } 02821 02822 int terminate_worker_thread(void){ 02823 02824 int result; 02825 02826 result=pthread_cancel(thread_pool[IDO2DB_THREAD_POOL_WORKER]); 02827 /* wait for the worker thread to exit */ 02828 if(result==0){ 02829 result=pthread_join(thread_pool[IDO2DB_THREAD_POOL_WORKER],NULL); 02830 } /* else only clean memory */ 02831 02832 return IDO_OK; 02833 02834 } 02835 02836 int terminate_cleanup_thread(void){ 02837 02838 int result; 02839 02840 result=pthread_cancel(thread_pool[IDO2DB_THREAD_POOL_CLEANER]); 02841 /* wait for the cleaner thread to exit */ 02842 if(result==0){ 02843 result=pthread_join(thread_pool[IDO2DB_THREAD_POOL_CLEANER],NULL); 02844 } /* else only clean memory */ 02845 02846 return IDO_OK; 02847 02848 } 02849 02850 02851