1 /* (C) 2006-2010 by folkert@vanheusden.com GPLv2 applies */
2
3 #include <stdio.h>
4 #include <time.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stddef.h>
12 #include <errno.h>
13 #include <sys/select.h>
14 #include <signal.h>
15 #include <sys/ioctl.h>
16 #include <ctype.h>
17
18 extern "C" {
19 #include "error.h"
20 }
21 #include "utils.h"
22 #include "br.h"
23 #include "pl.h"
24
25 static struct v2_0_config v2_0_config_elements[] = {
26 {"acknowledgement_type", STATS_OFFSET(acknowledgement_type), VARTYPE_INT},
27 {"active_checks_enabled", STATS_OFFSET(active_checks_enabled), VARTYPE_INT},
28 {"author", STATS_OFFSET(author), VARTYPE_PCHAR},
29 {"check_command", STATS_OFFSET(check_command), VARTYPE_PCHAR},
30 {"check_execution_time", STATS_OFFSET(check_execution_time), VARTYPE_DOUBLE},
31 {"check_interval", STATS_OFFSET(check_interval), VARTYPE_DOUBLE},
32 {"check_latency", STATS_OFFSET(check_latency), VARTYPE_DOUBLE},
33 {"check_options", STATS_OFFSET(check_options), VARTYPE_INT},
34 {"check_period", STATS_OFFSET(check_period), VARTYPE_PCHAR},
35 {"check_type", STATS_OFFSET(check_type), VARTYPE_INT},
36 {"comment", STATS_OFFSET(comment), VARTYPE_PCHAR},
37 {"comment_data", STATS_OFFSET(comment_data), VARTYPE_PCHAR},
38 {"comment_id", STATS_OFFSET(comment_id), VARTYPE_INT},
39 {"current_attempt", STATS_OFFSET(current_attempt), VARTYPE_INT},
40 {"current_event_id", STATS_OFFSET(current_event_id), VARTYPE_INT},
41 {"current_notification_id", STATS_OFFSET(current_notification_id), VARTYPE_INT},
42 {"current_notification_number", STATS_OFFSET(current_notification_number), VARTYPE_DOUBLE},
43 {"current_problem_id", STATS_OFFSET(current_problem_id), VARTYPE_INT},
44 {"current_state", STATS_OFFSET(current_state), VARTYPE_INT},
45 {"downtime_id", STATS_OFFSET(downtime_id), VARTYPE_INT},
46 {"duration", STATS_OFFSET(duration), VARTYPE_INT},
47 {"end_time", STATS_OFFSET(end_time), VARTYPE_TIMET},
48 {"entry_time", STATS_OFFSET(entry_time), VARTYPE_TIMET},
49 {"entry_type", STATS_OFFSET(entry_type), VARTYPE_INT},
50 {"event_handler", STATS_OFFSET(event_handler), VARTYPE_INT},
51 {"event_handler_enabled", STATS_OFFSET(event_handler_enabled), VARTYPE_INT},
52 {"expire_time", STATS_OFFSET(expire_time), VARTYPE_TIMET},
53 {"expires", STATS_OFFSET(expires), VARTYPE_INT},
54 {"failure_prediction_enabled", STATS_OFFSET(failure_prediction_enabled), VARTYPE_INT},
55 {"fixed", STATS_OFFSET(fixed), VARTYPE_INT},
56 {"flap_detection_enabled", STATS_OFFSET(flap_detection_enabled), VARTYPE_INT},
57 {"has_been_checked", STATS_OFFSET(has_been_checked), VARTYPE_INT},
58 {"host_name", STATS_OFFSET(host_name), VARTYPE_PCHAR},
59 {"host_notification_period", STATS_OFFSET(host_notification_period), VARTYPE_PCHAR},
60 {"is_flapping", STATS_OFFSET(is_flapping), VARTYPE_INT},
61 {"last_check", STATS_OFFSET(last_check), VARTYPE_TIMET},
62 {"last_event_id", STATS_OFFSET(last_event_id), VARTYPE_INT},
63 {"last_hard_state", STATS_OFFSET(last_hard_state), VARTYPE_INT},
64 {"last_hard_state_change", STATS_OFFSET(last_hard_state_change), VARTYPE_INT},
65 {"last_notification", STATS_OFFSET(last_notification), VARTYPE_INT},
66 {"last_problem_id", STATS_OFFSET(last_problem_id), VARTYPE_INT},
67 {"last_state_change", STATS_OFFSET(last_state_change), VARTYPE_TIMET},
68 {"last_time_critical", STATS_OFFSET(last_time_critical), VARTYPE_INT},
69 {"last_time_down", STATS_OFFSET(last_time_down), VARTYPE_INT},
70 {"last_time_ok", STATS_OFFSET(last_time_ok), VARTYPE_INT},
71 {"last_time_unknown", STATS_OFFSET(last_time_unknown), VARTYPE_INT},
72 {"last_time_unreachable", STATS_OFFSET(last_time_unreachable), VARTYPE_INT},
73 {"last_time_up", STATS_OFFSET(last_time_up), VARTYPE_INT},
74 {"last_time_warning", STATS_OFFSET(last_time_warning), VARTYPE_INT},
75 {"last_update", STATS_OFFSET(last_update), VARTYPE_TIMET},
76 {"long_plugin_output", STATS_OFFSET(long_plugin_output), VARTYPE_PCHAR},
77 {"max_attempts", STATS_OFFSET(max_attempts), VARTYPE_INT},
78 {"modified_attributes", STATS_OFFSET(modified_attributes), VARTYPE_INT},
79 {"next_check", STATS_OFFSET(next_check), VARTYPE_TIMET},
80 {"next_comment_id", STATS_OFFSET(next_comment_id), VARTYPE_INT},
81 {"next_notification", STATS_OFFSET(next_notification), VARTYPE_INT},
82 {"no_more_notifications", STATS_OFFSET(no_more_notifications), VARTYPE_INT},
83 {"notification_period", STATS_OFFSET(notification_period), VARTYPE_PCHAR},
84 {"notifications_enabled", STATS_OFFSET(notifications_enabled), VARTYPE_INT},
85 {"obsess", STATS_OFFSET(obsess), VARTYPE_INT},
86 {"obsess_over_host", STATS_OFFSET(obsess_over_host), VARTYPE_INT},
87 {"obsess_over_service", STATS_OFFSET(obsess_over_service), VARTYPE_INT},
88 {"passive_checks_enabled", STATS_OFFSET(passive_checks_enabled), VARTYPE_INT},
89 {"percent_state_change", STATS_OFFSET(percent_state_change), VARTYPE_DOUBLE},
90 {"performance_data", STATS_OFFSET(performance_data), VARTYPE_PCHAR},
91 {"persistent", STATS_OFFSET(persistent), VARTYPE_INT},
92 {"plugin_output", STATS_OFFSET(plugin_output), VARTYPE_PCHAR},
93 {"problem_has_been_acknowledged", STATS_OFFSET(problem_has_been_acknowledged), VARTYPE_INT},
94 {"process_performance_data", STATS_OFFSET(process_performance_data), VARTYPE_INT},
95 {"retry_interval", STATS_OFFSET(retry_interval), VARTYPE_DOUBLE},
96 {"scheduled_downtime_depth", STATS_OFFSET(scheduled_downtime_depth), VARTYPE_DOUBLE},
97 {"service_description", STATS_OFFSET(service_description), VARTYPE_PCHAR},
98 {"should_be_scheduled", STATS_OFFSET(should_be_scheduled), VARTYPE_INT},
99 {"source", STATS_OFFSET(source), VARTYPE_INT},
100 {"start_time", STATS_OFFSET(start_time), VARTYPE_TIMET},
101 {"state_type", STATS_OFFSET(state_type), VARTYPE_INT},
102 {"triggered_by", STATS_OFFSET(triggered_by), VARTYPE_INT},
103 {"type", STATS_OFFSET(type), VARTYPE_INT}
104 };
105
106 /*
107 service {
108 host_name=ap
109 service_description=HTTP
110 modified_attributes=0
111 check_command=check_tcp!80
112 event_handler=
113 has_been_checked=1
114 should_be_scheduled=1
115 check_execution_time=0.009
116 check_latency=0.712
117 current_state=0
118 last_hard_state=0
119 current_attempt=1
120 max_attempts=3
121 state_type=1
122 last_state_change=1128634047
123 last_hard_state_change=1128633828
124 last_time_ok=1129101510
125 last_time_warning=0
126 last_time_unknown=1128633828
127 last_time_critical=1126954624
128 plugin_output=TCP OK - 0.001 second response time on port 80
129 performance_data=time=0.001121s;0.000000;0.000000;0.000000;10.000000
130 last_check=1129101510
131 next_check=1129101630
132 check_type=0
133 current_notification_number=0
134 last_notification=0
135 next_notification=0
136 no_more_notifications=0
137 notifications_enabled=1
138 active_checks_enabled=1
139 passive_checks_enabled=1
140 event_handler_enabled=1
141 problem_has_been_acknowledged=0
142 acknowledgement_type=0
143 flap_detection_enabled=1
144 failure_prediction_enabled=1
145 process_performance_data=1
146 obsess_over_service=1
147 last_update=1129101556
148 is_flapping=0
149 percent_state_change=0.00
150 scheduled_downtime_depth=0
151 }
152
153 host {
154 host_name=ap
155 modified_attributes=0
156 check_command=check-host-alive
157 event_handler=
158 has_been_checked=1
159 should_be_scheduled=0
160 check_execution_time=0.012
161 check_latency=0.000
162 current_state=0
163 last_hard_state=0
164 check_type=0
165 plugin_output=PING OK - Packet loss = 0%, RTA = 1.54 ms
166 performance_data=
167 last_check=1128863442
168 next_check=0
169 current_attempt=1
170 max_attempts=10
171 state_type=1
172 last_state_change=1128634057
173 last_hard_state_change=1128634057
174 last_time_up=1128863442
175 last_time_down=1128633868
176 last_time_unreachable=0
177 last_notification=1128634057
178 next_notification=0
179 no_more_notifications=0
180 current_notification_number=0
181 notifications_enabled=1
182 problem_has_been_acknowledged=0
183 acknowledgement_type=0
184 active_checks_enabled=1
185 passive_checks_enabled=1
186 event_handler_enabled=1
187 flap_detection_enabled=1
188 failure_prediction_enabled=1
189 process_performance_data=1
190 obsess_over_host=1
191 last_update=1129101556
192 is_flapping=0
193 percent_state_change=0.00
194 scheduled_downtime_depth=0
195 }
196 */
197
v2_0_find_entry_type(char * field_name)198 int v2_0_find_entry_type(char *field_name)
199 {
200 int left = 0;
201 int right = (sizeof(v2_0_config_elements) / sizeof(struct v2_0_config)) - 1;
202
203 while(left <= right)
204 {
205 int mid = (left + right) / 2;
206 int compare = strcmp(field_name, v2_0_config_elements[mid].str);
207
208 if (compare > 0)
209 left = mid + 1;
210 else if (compare < 0)
211 right = mid - 1;
212 else
213 return mid;
214 }
215
216 return -1;
217 }
218
parse_2_0_statuslog(int fd,struct stats ** pstats,int * n_stats)219 void parse_2_0_statuslog(int fd, struct stats **pstats, int *n_stats)
220 {
221 int n_alloc = 0;
222 int type = TYPE_IGNORE;
223
224 /* start up buffered reader */
225 buffered_reader bf(fd);
226
227 *pstats = NULL;
228 *n_stats = 0;
229
230 for(;;)
231 {
232 char *line = bf.read_line();
233 if (!line)
234 break;
235
236 if (strchr(line, '{'))
237 {
238 /* init */
239 type = TYPE_IGNORE;
240
241 if (*n_stats == n_alloc)
242 {
243 if (n_alloc)
244 n_alloc *= 2;
245 else
246 n_alloc = 128;
247
248 *pstats = (struct stats *)myrealloc(*pstats, n_alloc * sizeof(struct stats), "stats array");
249 if (!*pstats)
250 error_exit("Error allocating memory");
251
252 memset(&(*pstats)[*n_stats], 0x00, sizeof(struct stats) * (n_alloc - *n_stats));
253 }
254 else
255 {
256 memset(&(*pstats)[*n_stats], 0x00, sizeof(struct stats));
257 }
258
259
260 if (strncmp(line, "host", 4) == 0)
261 {
262 type = TYPE_HOST;
263 }
264 else if (strncmp(line, "service", 7) == 0)
265 {
266 type = TYPE_SERVICE;
267 }
268 else
269 {
270 type = TYPE_IGNORE;
271 }
272 }
273 else if (type != TYPE_IGNORE)
274 {
275 char *cmd = line, *is;
276 while(*cmd == ' ' || *cmd == '\t') cmd++;
277
278 is = strchr(cmd, '=');
279 if (is == NULL)
280 {
281 if (strchr(cmd, '}') != NULL) /* end of definition, store in array */
282 {
283 if (type == TYPE_HOST && (*pstats)[*n_stats].current_state == 1) /* HOSTS: 0=ok, 1=down, 2=unreachable */
284 (*pstats)[*n_stats].current_state = 2;
285 (*pstats)[*n_stats].type = type;
286 (*n_stats)++;
287 }
288 }
289 else
290 {
291 int index;
292 char *record = (char *)(&(*pstats)[*n_stats]);
293 char *par = is + 1;
294 *is = 0x00;
295
296 if ((index = v2_0_find_entry_type(cmd)) != -1)
297 {
298 switch(v2_0_config_elements[index].type)
299 {
300 case VARTYPE_PCHAR:
301 *((char **)(&record[v2_0_config_elements[index].offset])) = mystrdup(par);
302 break;
303 case VARTYPE_INT:
304 *((int *)(&record[v2_0_config_elements[index].offset])) = atoi(par);
305 break;
306 case VARTYPE_TIMET:
307 *((time_t *)(&record[v2_0_config_elements[index].offset])) = atol(par);
308 break;
309 case VARTYPE_DOUBLE:
310 *((double *)(&record[v2_0_config_elements[index].offset])) = atof(par);
311 break;
312 }
313 }
314 else
315 {
316 /*printf("{%s} ???\n", cmd);*/
317 }
318 }
319 }
320
321 /* this one does not use myfree() as the buffered reader does not
322 * use mymalloc() and friends
323 */
324 free(line);
325 }
326 }
327
split_1_0_line(char * line,char ** out)328 int split_1_0_line(char *line, char **out)
329 {
330 int out_index = 0;
331
332 memset(out, 0x00, sizeof(char *) * V1_0_MAX_ELEMENTS);
333
334 for(;out_index < V1_0_MAX_ELEMENTS;)
335 {
336 out[out_index++] = line;
337
338 line = strchr(line, ';');
339
340 if (!line)
341 break;
342
343 *line = 0x00; /* replace ';' with 0x00 */
344 line++;
345 }
346
347 return out_index;
348 }
349
parse_1_0_statuslog(int fd,struct stats ** pstats,int * n_stats)350 void parse_1_0_statuslog(int fd, struct stats **pstats, int *n_stats)
351 {
352 /* start up buffered reader */
353 buffered_reader bf(fd);
354
355 *pstats = NULL;
356 *n_stats = 0;
357
358 for(;;)
359 {
360 int type = TYPE_IGNORE;
361 char *host_name = NULL;
362 int current_state = -1;
363 char *service_description = NULL;
364 char *plugin_output = NULL;
365 time_t last_state_change = 0;
366 char active_checks_enabled = 0;
367 char passive_checks_enabled = 0;
368 char notifications_enabled = 0;
369 char problem_has_been_acknowledged = 0;
370 int scheduled_downtime_depth = 0;
371 char state_type = 0;
372 char last_hard_state = 0;
373 int modified_attributes = 0;
374 int event_handler = 0;
375 int has_been_checked = 0;
376 int should_be_scheduled = 0;
377 int current_attempt = 0;
378 int max_attempts = 0;
379 int last_hard_state_change = 0;
380 int last_time_ok = 0;
381 int last_time_warning = 0;
382 int last_time_unknown = 0;
383 int last_time_critical = 0;
384 time_t last_check = 0;
385 time_t next_check = 0;
386 int check_type = 0;
387 int current_notification_number = 0;
388 int last_notification = 0;
389 int next_notification = 0;
390 int no_more_notifications = 0;
391 int event_handler_enabled = 0;
392 int acknowledgement_type = 0;
393 int flap_detection_enabled = 0;
394 int failure_prediction_enabled = 0;
395 int process_performance_data = 0;
396 int obsess_over_service = 0;
397 time_t last_update = 0;
398 int is_flapping = 0;
399 double percent_state_change = 0;
400 double check_execution_time = 0;
401 double check_latency = 0;
402 char * performance_data = NULL;
403 char * check_command = NULL;
404 int last_time_up = 0;
405 int last_time_down = 0;
406 int last_time_unreachable = 0;
407
408 char *dummy;
409 char *elements[V1_0_MAX_ELEMENTS];
410 int n_elem;
411 char *line = bf.read_line();
412 if (!line)
413 break;
414
415 if (line[0] == '#')
416 goto skip_line;
417
418 n_elem = split_1_0_line(line, elements);
419
420 *pstats = (struct stats *)myrealloc(*pstats, ((*n_stats) + 1) * sizeof(struct stats), "stats array");
421 if (!*pstats)
422 error_exit("Error allocating memory");
423
424 memset(&(*pstats)[*n_stats], 0x00, sizeof(struct stats));
425
426 /*
427 [Time of last update] HOST;
428 Host Name (string);
429 Status (OK/DOWN/UNREACHABLE);
430 Last Check Time (long time);
431 Last State Change (long time);
432 Acknowledged (0/1);
433 Time Up (long time);
434 Time Down (long time);
435 Time Unreachable (long time);
436 Last Notification Time (long time);
437 Current Notification Number (#);
438 Notifications Enabled (0/1);
439 Event Handlers Enabled (0/1);
440 Checks Enabled (0/1);
441 Flap Detection Enabled (0/1);
442 Host is Flapping (0/1);
443 Percent State Change (###.##);
444 Scheduled downtime depth (#);
445 Failure Prediction Enabled (0/1);
446 Process Performance Data(0/1);
447 Plugin Output (string)
448 */
449
450 /*
451 [Time of last update] SERVICE;
452 Host Name (string);
453 Service Description (string);
454 Status (OK/WARNING/CRITICAL/UNKNOWN);
455 Retry number (#/#);
456 State Type (SOFT/HARD);
457 Last check time (long time);
458 Next check time (long time);
459 Check type (ACTIVE/PASSIVE);
460 Checks enabled (0/1);
461 Accept Passive Checks (0/1);
462 Event Handlers Enabled (0/1);
463 Last state change (long time);
464 Problem acknowledged (0/1);
465 Last Hard State (OK/WARNING/CRITICAL/UNKNOWN);
466 Time OK (long time);
467 Time Unknown (long time);
468 Time Warning (long time);
469 Time Critical (long time);
470 Last Notification Time (long time);
471 Current Notification Number (#);
472 Notifications Enabled (0/1);
473 Latency (#);
474 Execution Time (#);
475 Flap Detection Enabled (0/1);
476 Service is Flapping (0/1);
477 Percent State Change (###.##);
478 Scheduled Downtime Depth (#);
479 Failure Prediction Enabled (0/1);
480 Process Performance Date (0/1);
481 Obsess Over Service (0/1);
482 Plugin Output (string)
483 */
484
485 dummy = strchr(elements[0], ' ');
486 if (!dummy)
487 goto skip_line;
488 dummy++;
489 if (strcmp(dummy, "HOST") == 0)
490 type = TYPE_HOST;
491 else if (strcmp(dummy, "SERVICE") == 0)
492 type = TYPE_SERVICE;
493 else if (strcmp(dummy, "PROGRAM") == 0)
494 goto skip_line;
495 else
496 goto skip_line;
497
498 last_update = atol(elements[0] + 1);
499
500 if (type == TYPE_HOST)
501 {
502 if (n_elem != 21)
503 goto skip_line;
504
505 host_name = mystrdup(elements[1]);
506 if (strcmp(elements[2], "UP") == 0)
507 current_state = 0;
508 else
509 current_state = 2;
510 last_check = atol(elements[3]);
511 last_state_change = atol(elements[4]);
512 problem_has_been_acknowledged = atoi(elements[5]);
513 last_time_up = atol(elements[6]);
514 last_time_down = atol(elements[7]);
515 last_time_unreachable = atol(elements[8]);
516 last_notification = atol(elements[9]);
517 current_notification_number = atoi(elements[10]);
518 notifications_enabled = atoi(elements[11]);
519 event_handler_enabled = atoi(elements[12]);
520 active_checks_enabled = atoi(elements[13]); /* in 2.0 it has been split up in passive and active */
521 flap_detection_enabled = atoi(elements[14]);
522 is_flapping = atoi(elements[15]);
523 percent_state_change = atof(elements[16]);
524 scheduled_downtime_depth = atoi(elements[17]);
525 failure_prediction_enabled = atoi(elements[18]);
526 /* process_performance_data = atoi(elements[19]); */
527 plugin_output = mystrdup(elements[20]);
528 }
529 else if (type == TYPE_SERVICE)
530 {
531 if (n_elem != 32)
532 goto skip_line;
533 host_name = mystrdup(elements[1]);
534 service_description = mystrdup(elements[2]);
535 if (strcmp(elements[3], "OK") == 0)
536 current_state = 0;
537 else if (strcmp(elements[3], "WARNING") == 0)
538 current_state = 1;
539 else if (strcmp(elements[3], "CRITICAL") == 0)
540 current_state = 2;
541 else if (strcmp(elements[3], "UNKNOWN") == 0 || strcmp(elements[3], "PENDING") == 0)
542 current_state = 3;
543 /* retry_number = atoi(elements[4]); */
544 if (strcmp(elements[5], "SOFT") == 0)
545 state_type = 0;
546 else
547 state_type = 1;
548 last_check = atol(elements[6]);
549 next_check = atol(elements[7]);
550 if (strcmp(elements[8], "ACTIVE") == 0)
551 check_type = 1;
552 else
553 check_type = 0;
554 active_checks_enabled = atoi(elements[9]);
555 /* accept_passive_checks = atoi(elements[10]); */
556 event_handler_enabled = atoi(elements[11]);
557 last_state_change = atol(elements[12]);
558 problem_has_been_acknowledged = atoi(elements[13]);
559 if (strcmp(elements[14], "OK") == 0)
560 last_hard_state = 0;
561 else if (strcmp(elements[14], "WARNING") == 0)
562 last_hard_state = 1;
563 else if (strcmp(elements[14], "CRITICAL") == 0)
564 last_hard_state = 2;
565 else if (strcmp(elements[14], "UNKNOWN") == 0)
566 last_hard_state = 3;
567 last_time_ok = atol(elements[15]);
568 last_time_unknown = atol(elements[16]);
569 last_time_warning = atol(elements[17]);
570 last_time_critical = atol(elements[18]);
571 last_notification = atol(elements[19]);
572 current_notification_number = atoi(elements[20]);
573 notifications_enabled = atoi(elements[21]);
574 check_latency = atof(elements[22]);
575 check_execution_time = atof(elements[23]);
576 flap_detection_enabled = atoi(elements[24]);
577 is_flapping = atoi(elements[25]);
578 percent_state_change = atof(elements[26]);
579 scheduled_downtime_depth = atoi(elements[27]);
580 failure_prediction_enabled = atoi(elements[28]);
581 /* process_performance_date = atoi(elements[29]); */
582 obsess_over_service = atoi(elements[30]);
583 plugin_output = mystrdup(elements[31]);
584 }
585 else
586 error_exit("internal error: type %d unexpected\n", type);
587
588 (*pstats)[*n_stats].type = type;
589 (*pstats)[*n_stats].host_name = host_name?host_name:mystrdup("");
590 if (type == TYPE_HOST && current_state == 1) /* HOSTS: 0=ok, 1=down, 2=unreachable */
591 current_state = 2;
592 (*pstats)[*n_stats].current_state = current_state;
593 (*pstats)[*n_stats].service_description = service_description?service_description:mystrdup("");
594 (*pstats)[*n_stats].plugin_output = plugin_output?plugin_output:mystrdup("");
595 (*pstats)[*n_stats].last_state_change = last_state_change;
596 (*pstats)[*n_stats].active_checks_enabled = active_checks_enabled;
597 (*pstats)[*n_stats].passive_checks_enabled = passive_checks_enabled;
598 (*pstats)[*n_stats].notifications_enabled = notifications_enabled;
599 (*pstats)[*n_stats].problem_has_been_acknowledged = problem_has_been_acknowledged;
600 (*pstats)[*n_stats].scheduled_downtime_depth = scheduled_downtime_depth;
601 (*pstats)[*n_stats].state_type = state_type;
602 (*pstats)[*n_stats].last_hard_state = last_hard_state;
603 (*pstats)[*n_stats].modified_attributes = modified_attributes;
604 (*pstats)[*n_stats].event_handler = event_handler;
605 (*pstats)[*n_stats].has_been_checked = has_been_checked;
606 (*pstats)[*n_stats].should_be_scheduled = should_be_scheduled;
607 (*pstats)[*n_stats].current_attempt = current_attempt;
608 (*pstats)[*n_stats].max_attempts = max_attempts;
609 (*pstats)[*n_stats].last_hard_state_change = last_hard_state_change;
610 (*pstats)[*n_stats].last_time_ok = last_time_ok;
611 (*pstats)[*n_stats].last_time_warning = last_time_warning;
612 (*pstats)[*n_stats].last_time_unknown = last_time_unknown;
613 (*pstats)[*n_stats].last_time_critical = last_time_critical;
614 (*pstats)[*n_stats].last_check = last_check;
615 (*pstats)[*n_stats].next_check = next_check;
616 (*pstats)[*n_stats].check_type = check_type;
617 (*pstats)[*n_stats].current_notification_number = current_notification_number;
618 (*pstats)[*n_stats].last_notification = last_notification;
619 (*pstats)[*n_stats].next_notification = next_notification;
620 (*pstats)[*n_stats].no_more_notifications = no_more_notifications;
621 (*pstats)[*n_stats].event_handler_enabled = event_handler_enabled;
622 (*pstats)[*n_stats].acknowledgement_type = acknowledgement_type;
623 (*pstats)[*n_stats].flap_detection_enabled = flap_detection_enabled;
624 (*pstats)[*n_stats].failure_prediction_enabled = failure_prediction_enabled;
625 (*pstats)[*n_stats].process_performance_data = process_performance_data;
626 (*pstats)[*n_stats].obsess_over_service = obsess_over_service;
627 (*pstats)[*n_stats].last_update = last_update;
628 (*pstats)[*n_stats].is_flapping = is_flapping;
629 (*pstats)[*n_stats].percent_state_change = percent_state_change;
630 (*pstats)[*n_stats].check_execution_time = check_execution_time;
631 (*pstats)[*n_stats].check_latency = check_latency;
632 (*pstats)[*n_stats].performance_data = performance_data;
633 (*pstats)[*n_stats].check_command = check_command;
634 (*pstats)[*n_stats].last_time_up = last_time_up;
635 (*pstats)[*n_stats].last_time_down = last_time_down;
636 (*pstats)[*n_stats].last_time_unreachable = last_time_unreachable;
637 (*n_stats)++;
638
639 skip_line:
640 free(line);
641 }
642
643 close(fd);
644 }
645
free_stats_array(struct stats * pstats,int n_stats)646 void free_stats_array(struct stats *pstats, int n_stats)
647 {
648 if (pstats)
649 {
650 for(int loop=0; loop<n_stats; loop++)
651 {
652 myfree((void *)pstats[loop].host_name, "entry hostname");
653 myfree((void *)pstats[loop].service_description, "entry servicedescription");
654 myfree((void *)pstats[loop].plugin_output, "entry plugin output");
655 myfree((void *)pstats[loop].performance_data, "entry performance data");
656 myfree((void *)pstats[loop].check_command, "entry check command");
657 myfree((void *)pstats[loop].author, "entry author");
658 myfree((void *)pstats[loop].check_period, "entry check_period");
659 myfree((void *)pstats[loop].comment_data, "entry comment data");
660 myfree((void *)pstats[loop].host_notification_period, "entry host notification period");
661 myfree((void *)pstats[loop].long_plugin_output, "entry long plugin output");
662 myfree((void *)pstats[loop].notification_period, "entry notification period");
663 myfree((void *)pstats[loop].service_notification_period, "entry service notification period");
664 }
665
666 myfree((void *)pstats, "stats array");
667 }
668 }
669
sort_compare_func(const void * a,const void * b)670 int sort_compare_func(const void *a, const void *b)
671 {
672 struct stats *p1 = (struct stats *)a;
673 struct stats *p2 = (struct stats *)b;
674
675 if (p1 -> current_state < p2 -> current_state)
676 return 1;
677 else if (p1 -> current_state == p2 -> current_state)
678 {
679 if (p1 -> last_state_change < p2 -> last_state_change)
680 return 1;
681
682 return p2 -> last_state_change - p1 -> last_state_change;
683 }
684
685 return -1;
686 }
687
sort_stats_array(struct stats * pstats,int n_stats)688 void sort_stats_array(struct stats *pstats, int n_stats)
689 {
690 if (n_stats > 1)
691 qsort(pstats, n_stats, sizeof(struct stats), sort_compare_func);
692 }
693
host_is_down(struct stats * pstats,int n_stats,char * host_name)694 int host_is_down(struct stats *pstats, int n_stats, char *host_name)
695 {
696 for(int loop=0; loop<n_stats; loop++)
697 {
698 if (pstats[loop].type == TYPE_SERVICE)
699 continue;
700
701 if (pstats[loop].current_state == 1 || // down
702 pstats[loop].current_state == 2) // unreachable
703 {
704 if (pstats[loop].host_name != NULL && strcmp(pstats[loop].host_name, host_name) == 0)
705 return loop;
706 }
707 }
708
709 return -1;
710 }
711
should_i_show_entry(struct stats * pstats,int n_stats,int cur_index,char list_all_problems,char always_notify,char also_acknowledged,char hide_ok)712 int should_i_show_entry(struct stats *pstats, int n_stats, int cur_index, char list_all_problems, char always_notify, char also_acknowledged, char hide_ok)
713 {
714 if (pstats[cur_index].state_type != 1)
715 return 0;
716
717 if (!list_all_problems)
718 {
719 if (pstats[cur_index].type != TYPE_HOST && host_is_down(pstats, n_stats, pstats[cur_index].host_name) != -1)
720 return 0;
721
722 if (pstats[cur_index].active_checks_enabled == 0 &&
723 pstats[cur_index].passive_checks_enabled == 0)
724 return 0;
725
726 if (pstats[cur_index].scheduled_downtime_depth != 0)
727 return 0;
728 }
729
730 if (!always_notify && pstats[cur_index].notifications_enabled == 0)
731 return 0;
732
733 if (!also_acknowledged && pstats[cur_index].problem_has_been_acknowledged == 1)
734 return 0;
735
736 if (pstats[cur_index].current_state == 0 && hide_ok)
737 return 0;
738
739 if (pstats[cur_index].current_state < 0 || pstats[cur_index].current_state > 3)
740 error_exit("internal error: state %d not known", pstats[cur_index].current_state);
741
742 return 1;
743 }
744
find_index_by_host_and_service(struct stats * pstats,int n_stats,char * host_name,char * service_description)745 int find_index_by_host_and_service(struct stats *pstats, int n_stats, char *host_name, char *service_description)
746 {
747 int loop;
748 static int last = 0;
749
750 if (service_description)
751 {
752 for(loop=0; loop<n_stats; loop++)
753 {
754 int index = (last + loop) % n_stats;
755 if (pstats[index].host_name != NULL && strcmp(pstats[index].host_name, host_name) == 0 &&
756 pstats[index].service_description != NULL && strcmp(pstats[index].service_description, service_description) == 0)
757 {
758 last = index;
759 return index;
760 }
761 }
762 }
763 else
764 {
765 for(loop=0; loop<n_stats; loop++)
766 {
767 int index = (last + loop) % n_stats;
768 if (pstats[index].service_description == NULL && pstats[index].host_name != NULL && strcmp(pstats[index].host_name, host_name) == 0)
769 {
770 last = index;
771 return index;
772 }
773 }
774 }
775
776 return -1;
777 }
778
check_an_age(char ** message,char * descr,time_t now,time_t check_time,int max_diff,char * what)779 int check_an_age(char **message, char *descr, time_t now, time_t check_time, int max_diff, char *what)
780 {
781 char buffer[4096] = { 0 };
782 int cur_diff = (now - check_time);
783
784 *message = 0x00;
785
786 if (cur_diff > max_diff)
787 {
788 char *time_str = ctime(&check_time);
789 char *dummy = strchr(time_str, '\n');
790 *dummy = 0x00;
791
792 snprintf(buffer, sizeof(buffer), "limit reached of \"%s\" for %s: %d seconds (last check: %s (%d), max diff: %d)", descr, what?what:"?", cur_diff, time_str, (int)check_time, max_diff);
793
794 *message = strdup(buffer);
795
796 return -1;
797 }
798
799 return 0;
800 }
801
check_max_age_last_check(struct stats * pstats,int n_stats,int max_time_last_host_update,int max_time_oldest_host_update,int max_time_last_host_check,int max_time_oldest_host_check,int max_time_last_service_check,int max_time_oldest_service_check,int max_time_oldest_next_service_check,char ** message)802 int check_max_age_last_check(struct stats *pstats, int n_stats, int max_time_last_host_update, int max_time_oldest_host_update, int max_time_last_host_check, int max_time_oldest_host_check, int max_time_last_service_check, int max_time_oldest_service_check, int max_time_oldest_next_service_check, char **message)
803 {
804 time_t now = time(NULL);
805 int index;
806 time_t most_recent_host_update = 0;
807 time_t most_recent_host_check = 0;
808 time_t most_recent_last_service_check = 0;
809 time_t oldest_next_service_check = now;
810
811 for(index=0; index<n_stats; index++)
812 {
813 if (pstats[index].type == TYPE_HOST)
814 {
815 if (pstats[index].last_update != 0 && pstats[index].active_checks_enabled != 0)
816 {
817 most_recent_host_update = max(most_recent_host_update, pstats[index].last_update);
818
819 if (check_an_age(message, "oldest host update", now, pstats[index].last_update, max_time_oldest_host_update, pstats[index].host_name) == -1)
820 return -1;
821 }
822
823 if (pstats[index].last_check != 0 && pstats[index].active_checks_enabled != 0)
824 {
825 most_recent_host_check = max(most_recent_host_check, pstats[index].last_check);
826
827 // if (check_an_age(message, "oldest host check", now, pstats[index].last_check, max_time_oldest_host_check, pstats[index].host_name) == -1)
828 // return -1;
829 }
830 }
831 else if (pstats[index].type == TYPE_SERVICE)
832 {
833 if (pstats[index].last_check != 0)
834 {
835 char buffer[4096];
836
837 snprintf(buffer, sizeof(buffer), "%s@%s", pstats[index].service_description, pstats[index].host_name);
838
839 most_recent_last_service_check = max(most_recent_last_service_check, pstats[index].last_check);
840
841 if (check_an_age(message, "oldest service check", now, pstats[index].last_check, max_time_oldest_service_check, buffer) == -1)
842 return -1;
843 }
844
845 if (pstats[index].next_check != 0)
846 {
847 oldest_next_service_check = min(oldest_next_service_check, pstats[index].next_check);
848 }
849 }
850 }
851
852 if (check_an_age(message, "most recent host update", now, most_recent_host_update, max_time_last_host_update, NULL) == -1)
853 return -1;
854
855 // if (check_an_age(message, "most recent host check", now, most_recent_host_check, max_time_last_host_check, NULL) == -1)
856 // return -1;
857
858 if (check_an_age(message, "most recent last service check", now, most_recent_last_service_check, max_time_last_service_check, NULL) == -1)
859 return -1;
860
861 if (check_an_age(message, "oldest next sevice check", now, oldest_next_service_check, max_time_oldest_next_service_check, NULL) == -1)
862 return -1;
863
864 return 0;
865 }
866
calc_stats_stats(struct stats * pstats,int n_stats,char list_all_problems,char always_notify,char also_acknowledged,char hide_ok,int * n_critical,int * n_warning,int * n_ok,int * n_up,int * n_down,int * n_unreachable,int * n_pending)867 void calc_stats_stats(struct stats *pstats, int n_stats, char list_all_problems, char always_notify, char also_acknowledged, char hide_ok, int *n_critical, int *n_warning, int *n_ok, int *n_up, int *n_down, int *n_unreachable, int *n_pending)
868 {
869 *n_critical = *n_warning = *n_ok = 0;
870 *n_up = *n_down = *n_unreachable = *n_pending = 0;
871
872 for(int loop=0; loop<n_stats; loop++)
873 {
874 if (pstats[loop].type == TYPE_HOST)
875 {
876 if (pstats[loop].current_state == 0)
877 (*n_up)++;
878 else if (pstats[loop].current_state == 1)
879 (*n_down)++;
880 else if (pstats[loop].current_state == 2)
881 (*n_unreachable)++;
882 else if (pstats[loop].current_state == 3)
883 (*n_pending)++;
884 }
885 else if (pstats[loop].type == TYPE_SERVICE)
886 {
887 if (pstats[loop].current_state == 0)
888 (*n_ok)++;
889 else if (pstats[loop].current_state == 1)
890 (*n_warning)++;
891 else if (pstats[loop].current_state == 2)
892 (*n_critical)++;
893 }
894 else
895 error_exit("calc_stats_stats: internal error (%d)", pstats[loop].type);
896 }
897 }
898