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