1 // +------------------------------------------------------------------+
2 // |             ____ _               _        __  __ _  __           |
3 // |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
4 // |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
5 // |           | |___| | | |  __/ (__|   <    | |  | | . \            |
6 // |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
7 // |                                                                  |
8 // | Copyright Mathias Kettner 2014             mk@mathias-kettner.de |
9 // +------------------------------------------------------------------+
10 //
11 // This file is part of Check_MK.
12 // The official homepage is at http://mathias-kettner.de/check_mk.
13 //
14 // check_mk is free software;  you can redistribute it and/or modify it
15 // under the  terms of the  GNU General Public License  as published by
16 // the Free Software Foundation in version 2.  check_mk is  distributed
17 // in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
18 // out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
19 // PARTICULAR PURPOSE. See the  GNU General Public License for more de-
20 // ails.  You should have  received  a copy of the  GNU  General Public
21 // License along with GNU Make; see the file  COPYING.  If  not,  write
22 // to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
23 // Boston, MA 02110-1301 USA.
24 
25 // IWYU pragma: no_include <bits/socket_type.h>
26 #include "config.h"
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <pthread.h>
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/select.h>
35 #include <sys/socket.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>  // IWYU pragma: keep
38 #include <sys/un.h>
39 #include <time.h>
40 #include <unistd.h>
41 #include "auth.h"
42 #include "data_encoding.h"
43 #include "global_counters.h"
44 #include "livestatus.h"
45 #include "logger.h"
46 #include "nagios.h"
47 #include "store_c.h"
48 #include "strutil.h"
49 #include "waittriggers.h"
50 
51 #ifndef AF_LOCAL
52 #define AF_LOCAL AF_UNIX
53 #endif
54 #ifndef PF_LOCAL
55 #define PF_LOCAL PF_UNIX
56 #endif
57 
58 // usually - but not always - in sys/un.h
59 #ifndef SUN_LEN
60 #define SUN_LEN(ptr) \
61     ((size_t)(((struct sockaddr_un *)0)->sun_path) + strlen((ptr)->sun_path))
62 #endif
63 
64 NEB_API_VERSION(CURRENT_NEB_API_VERSION)
65 #ifndef NAGIOS4
66 extern int event_broker_options;
67 #else
68 extern unsigned long event_broker_options;
69 #endif  // NAGIOS4
70 extern int enable_environment_macros;
71 extern char *log_file;
72 
73 int g_idle_timeout_msec =
74     300 * 1000; /* maximum idle time for connection in keep alive state */
75 int g_query_timeout_msec = 10 * 1000; /* maximum time for reading a query */
76 
77 int g_num_clientthreads = 10; /* allow 10 concurrent connections per default */
78 int g_num_queued_connections =
79     0; /* current number of queued connections (for statistics) */
80 int g_num_active_connections =
81     0; /* current number of active connections (for statistics) */
82 size_t g_thread_stack_size = 65536; /* stack size of threads */
83 extern int g_disable_statehist_filtering;
84 
85 #define false 0
86 #define true 1
87 
88 void *g_nagios_handle;
89 int g_unix_socket = -1;
90 int g_max_fd_ever = 0;
91 char g_socket_path[4096];
92 char pnp_path_storage[4096];
93 char *g_pnp_path = pnp_path_storage;
94 char g_mk_inventory_path[4096];  // base path of Check_MK inventor files
95 char g_logfile_path[4096];
96 int g_debug_level = 0;
97 int g_should_terminate = false;
98 pthread_t g_mainthread_id;
99 pthread_t *g_clientthread_id;
100 unsigned long g_max_cached_messages = 500000;
101 unsigned long g_max_lines_per_logfile =
102     1000000;  // do never read more than that number of lines from a logfile
103 unsigned long g_max_response_size = 100 * 1024 * 1024;  // limit answer to 10 MB
104 int g_thread_running = 0;
105 int g_thread_pid = 0;
106 int g_service_authorization = AUTH_LOOSE;
107 int g_group_authorization = AUTH_STRICT;
108 int g_data_encoding = ENCODING_UTF8;
109 
110 /* simple statistics data for TableStatus */
111 extern struct host *host_list;
112 extern struct service *service_list;
113 extern scheduled_downtime *scheduled_downtime_list;
114 extern int log_initial_states;
115 
116 int g_num_hosts;
117 int g_num_services;
118 
count_hosts()119 void count_hosts() {
120     g_num_hosts = 0;
121     host *h = (host *)host_list;
122     while (h) {
123         g_num_hosts++;
124         h = h->next;
125     }
126 }
127 
count_services()128 void count_services() {
129     g_num_services = 0;
130     service *s = (service *)service_list;
131     while (s) {
132         g_num_services++;
133         s = s->next;
134     }
135 }
136 
137 void *voidp;
138 
livestatus_count_fork()139 void livestatus_count_fork() { g_counters[COUNTER_FORKS]++; }
140 
livestatus_cleanup_after_fork()141 void livestatus_cleanup_after_fork() {
142     // 4.2.2010: Deactivate the cleanup function. It might cause
143     // more trouble than it tries to avoid. It might lead to a deadlock
144     // with Nagios' fork()-mechanism...
145     // store_deinit();
146     struct stat st;
147 
148     int i;
149     // We need to close our server and client sockets. Otherwise
150     // our connections are inherited to host and service checks.
151     // If we close our client connection in such a situation,
152     // the connection will still be open since and the client will
153     // hang while trying to read further data. And the CLOEXEC is
154     // not atomic :-(
155 
156     // Eventuell sollte man hier anstelle von store_deinit() nicht
157     // darauf verlassen, dass die ClientQueue alle Verbindungen zumacht.
158     // Es sind ja auch Dateideskriptoren offen, die von Threads gehalten
159     // werden und nicht mehr in der Queue sind. Und in store_deinit()
160     // wird mit mutexes rumgemacht....
161     for (i = 3; i < g_max_fd_ever; i++) {
162         if (0 == fstat(i, &st) && S_ISSOCK(st.st_mode)) {
163             close(i);
164         }
165     }
166 }
167 
main_thread(void * data)168 void *main_thread(void *data __attribute__((__unused__))) {
169     g_thread_pid = getpid();
170     while (!g_should_terminate) {
171         do_statistics();
172         if (g_thread_pid != getpid()) {
173             logger(LG_INFO, "I'm not the main process but %d!", getpid());
174             // return;
175         }
176         struct timeval tv;
177         tv.tv_sec = 2;
178         tv.tv_usec = 500 * 1000;
179 
180         fd_set fds;
181         FD_ZERO(&fds);
182         FD_SET(g_unix_socket, &fds);
183         int retval = select(g_unix_socket + 1, &fds, NULL, NULL, &tv);
184         if (retval > 0 && FD_ISSET(g_unix_socket, &fds)) {
185             int cc = accept(g_unix_socket, NULL, NULL);
186             if (cc > g_max_fd_ever) {
187                 g_max_fd_ever = cc;
188             }
189             if (fcntl(cc, F_SETFD, FD_CLOEXEC) < 0) {
190                 logger(LG_INFO, "Cannot set FD_CLOEXEC on client socket: %s",
191                        strerror(errno));
192             }
193             queue_add_connection(cc);  // closes fd
194             g_num_queued_connections++;
195             g_counters[COUNTER_CONNECTIONS]++;
196         }
197     }
198     logger(LG_INFO, "Socket thread has terminated");
199     return voidp;
200 }
201 
client_thread(void * data)202 void *client_thread(void *data __attribute__((__unused__))) {
203     void *output_buffer = create_outputbuffer();
204 
205     while (!g_should_terminate) {
206         int cc = queue_pop_connection();
207         g_num_queued_connections--;
208         g_num_active_connections++;
209         if (cc >= 0) {
210             if (g_debug_level >= 2) {
211                 logger(LG_INFO, "Accepted client connection on fd %d", cc);
212             }
213             void *input_buffer = create_inputbuffer(cc, &g_should_terminate);
214             int keepalive = 1;
215             unsigned requestnr = 1;
216             while (keepalive) {
217                 if (g_debug_level >= 2 && requestnr > 1) {
218                     logger(LG_INFO, "Handling request %d on same connection",
219                            requestnr);
220                 }
221                 keepalive = store_answer_request(input_buffer, output_buffer);
222                 flush_output_buffer(output_buffer, cc, &g_should_terminate);
223                 g_counters[COUNTER_REQUESTS]++;
224                 requestnr++;
225             }
226             delete_inputbuffer(input_buffer);
227             close(cc);
228         }
229         g_num_active_connections--;
230     }
231     delete_outputbuffer(output_buffer);
232     return voidp;
233 }
234 
start_threads()235 void start_threads() {
236     count_hosts();
237     count_services();
238 
239     if (!g_thread_running) {
240         /* start thread that listens on socket */
241         pthread_atfork(livestatus_count_fork, NULL,
242                        livestatus_cleanup_after_fork);
243         pthread_create(&g_mainthread_id, 0, main_thread, (void *)0);
244         if (g_debug_level > 0) {
245             logger(LG_INFO, "Starting %d client threads", g_num_clientthreads);
246         }
247 
248         int t;
249         g_clientthread_id =
250             (pthread_t *)malloc(sizeof(pthread_t) * g_num_clientthreads);
251         pthread_attr_t attr;
252         pthread_attr_init(&attr);
253         size_t defsize;
254         if (g_debug_level >= 2 &&
255             0 == pthread_attr_getstacksize(&attr, &defsize)) {
256             logger(LG_INFO, "Default stack size is %lu", defsize);
257         }
258         if (0 != pthread_attr_setstacksize(&attr, g_thread_stack_size)) {
259             logger(LG_INFO, "Error: Cannot set thread stack size to %lu",
260                    g_thread_stack_size);
261         } else {
262             if (g_debug_level >= 2) {
263                 logger(LG_INFO, "Setting thread stack size to %lu",
264                        g_thread_stack_size);
265             }
266         }
267         for (t = 0; t < g_num_clientthreads; t++) {
268             pthread_create(&g_clientthread_id[t], &attr, client_thread,
269                            (void *)0);
270         }
271 
272         g_thread_running = 1;
273         pthread_attr_destroy(&attr);
274     }
275 }
276 
terminate_threads()277 void terminate_threads() {
278     if (g_thread_running) {
279         g_should_terminate = true;
280         logger(LG_INFO, "Waiting for main to terminate...");
281         pthread_join(g_mainthread_id, NULL);
282         logger(LG_INFO, "Waiting for client threads to terminate...");
283         queue_terminate();
284         int t;
285         for (t = 0; t < g_num_clientthreads; t++) {
286             if (0 != pthread_join(g_clientthread_id[t], NULL)) {
287                 logger(LG_INFO, "Warning: could not join thread no. %d", t);
288             }
289         }
290         if (g_debug_level > 0) {
291             logger(LG_INFO, "Main thread + %d client threads have finished",
292                    g_num_clientthreads);
293         }
294         g_thread_running = 0;
295         g_should_terminate = false;
296     }
297     free(g_clientthread_id);
298 }
299 
open_unix_socket()300 int open_unix_socket() {
301     struct stat st;
302     if (0 == stat(g_socket_path, &st)) {
303         if (0 == unlink(g_socket_path)) {
304             logger(LG_DEBUG, "Removed old left over socket file %s",
305                    g_socket_path);
306         } else {
307             logger(LG_ALERT, "Cannot remove in the way file %s: %s",
308                    g_socket_path, strerror(errno));
309             return false;
310         }
311     }
312 
313     g_unix_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
314     g_max_fd_ever = g_unix_socket;
315     if (g_unix_socket < 0) {
316         logger(LG_CRIT, "Unable to create UNIX socket: %s", strerror(errno));
317         return false;
318     }
319 
320     // Imortant: close on exec -> check plugins must not inherit it!
321     if (fcntl(g_unix_socket, F_SETFD, FD_CLOEXEC) < 0) {
322         logger(LG_INFO, "Cannot set FD_CLOEXEC on socket: %s", strerror(errno));
323     }
324 
325     // Bind it to its address. This creates the file with the name g_socket_path
326     struct sockaddr_un sockaddr;
327     sockaddr.sun_family = AF_LOCAL;
328     strncpy(sockaddr.sun_path, g_socket_path, sizeof(sockaddr.sun_path));
329     if (bind(g_unix_socket, (struct sockaddr *)&sockaddr, SUN_LEN(&sockaddr)) <
330         0) {
331         logger(LG_ERR, "Unable to bind adress %s to UNIX socket: %s",
332                g_socket_path, strerror(errno));
333         close(g_unix_socket);
334         return false;
335     }
336 
337     // Make writable group members (fchmod didn't do nothing for me. Don't know
338     // why!)
339     if (0 != chmod(g_socket_path, 0660)) {
340         logger(LG_ERR, "Cannot chown unix socket at %s to 0660: %s",
341                g_socket_path, strerror(errno));
342         close(g_unix_socket);
343         return false;
344     }
345 
346     if (0 != listen(g_unix_socket, 3 /* backlog */)) {
347         logger(LG_ERR, "Cannot listen to unix socket at %s: %s", g_socket_path,
348                strerror(errno));
349         close(g_unix_socket);
350         return false;
351     }
352 
353     if (g_debug_level > 0) {
354         logger(LG_INFO, "Opened UNIX socket %s\n", g_socket_path);
355     }
356     return true;
357 }
358 
close_unix_socket()359 void close_unix_socket() {
360     unlink(g_socket_path);
361     if (g_unix_socket >= 0) {
362         close(g_unix_socket);
363         g_unix_socket = -1;
364     }
365 }
366 
broker_host(int event_type,void * data)367 int broker_host(int event_type __attribute__((__unused__)),
368                 void *data __attribute__((__unused__))) {
369     g_counters[COUNTER_NEB_CALLBACKS]++;
370     return 0;
371 }
372 
broker_check(int event_type,void * data)373 int broker_check(int event_type, void *data) {
374     int result = NEB_OK;
375     if (event_type == NEBCALLBACK_SERVICE_CHECK_DATA) {
376         nebstruct_service_check_data *c = (nebstruct_service_check_data *)data;
377         if (c->type == NEBTYPE_SERVICECHECK_PROCESSED) {
378             g_counters[COUNTER_SERVICE_CHECKS]++;
379         }
380     } else if (event_type == NEBCALLBACK_HOST_CHECK_DATA) {
381         nebstruct_host_check_data *c = (nebstruct_host_check_data *)data;
382         if (c->type == NEBTYPE_HOSTCHECK_PROCESSED) {
383             g_counters[COUNTER_HOST_CHECKS]++;
384         }
385     }
386     trigger_notify_all(trigger_check());
387     return result;
388 }
389 
broker_comment(int event_type,void * data)390 int broker_comment(int event_type __attribute__((__unused__)), void *data) {
391     nebstruct_comment_data *co = (nebstruct_comment_data *)data;
392     store_register_comment(co);
393     g_counters[COUNTER_NEB_CALLBACKS]++;
394     trigger_notify_all(trigger_comment());
395     return 0;
396 }
397 
broker_downtime(int event_type,void * data)398 int broker_downtime(int event_type __attribute__((__unused__)), void *data) {
399     nebstruct_downtime_data *dt = (nebstruct_downtime_data *)data;
400     store_register_downtime(dt);
401     g_counters[COUNTER_NEB_CALLBACKS]++;
402     trigger_notify_all(trigger_downtime());
403     return 0;
404 }
405 
broker_log(int event_type,void * data)406 int broker_log(int event_type __attribute__((__unused__)),
407                void *data __attribute__((__unused__))) {
408     g_counters[COUNTER_NEB_CALLBACKS]++;
409     g_counters[COUNTER_LOG_MESSAGES]++;
410     trigger_notify_all(trigger_log());
411     return 0;
412 }
413 
broker_command(int event_type,void * data)414 int broker_command(int event_type __attribute__((__unused__)), void *data) {
415     nebstruct_external_command_data *sc =
416         (nebstruct_external_command_data *)data;
417     if (sc->type == NEBTYPE_EXTERNALCOMMAND_START) {
418         g_counters[COUNTER_COMMANDS]++;
419     }
420     g_counters[COUNTER_NEB_CALLBACKS]++;
421     trigger_notify_all(trigger_command());
422     return 0;
423 }
424 
broker_state(int event_type,void * data)425 int broker_state(int event_type __attribute__((__unused__)),
426                  void *data __attribute__((__unused__))) {
427     g_counters[COUNTER_NEB_CALLBACKS]++;
428     trigger_notify_all(trigger_state());
429     return 0;
430 }
431 
broker_program(int event_type,void * data)432 int broker_program(int event_type __attribute__((__unused__)),
433                    void *data __attribute__((__unused__))) {
434     g_counters[COUNTER_NEB_CALLBACKS]++;
435     trigger_notify_all(trigger_program());
436     return 0;
437 }
438 
get_downtime_comment(char * host_name,char * svc_desc)439 char *get_downtime_comment(char *host_name, char *svc_desc) {
440     char *comment;
441     int matches = 0;
442     scheduled_downtime *dt_list = scheduled_downtime_list;
443     while (dt_list != NULL) {
444         if (dt_list->type == HOST_DOWNTIME) {
445             if (strcmp(dt_list->host_name, host_name) == 0) {
446                 matches++;
447                 comment = dt_list->comment;
448             }
449         }
450         if (svc_desc != NULL && dt_list->type == SERVICE_DOWNTIME) {
451             if (strcmp(dt_list->host_name, host_name) == 0 &&
452                 strcmp(dt_list->service_description, svc_desc) == 0) {
453                 matches++;
454                 comment = dt_list->comment;
455             }
456         }
457         dt_list = dt_list->next;
458     }
459     return matches == 0 ? "No comment"
460                         : matches > 1 ? "Multiple Downtime Comments" : comment;
461 }
462 
livestatus_log_initial_states()463 void livestatus_log_initial_states() {
464     // Log DOWNTIME hosts
465     host *h = (host *)host_list;
466     char buffer[8192];
467 
468     while (h) {
469         if (h->scheduled_downtime_depth > 0) {
470             snprintf(buffer, sizeof(buffer),
471                      "HOST DOWNTIME ALERT: %s;STARTED;%s", h->name,
472                      get_downtime_comment(h->name, NULL));
473             write_to_all_logs(buffer, LG_INFO);
474         }
475         h = h->next;
476     }
477     // Log DOWNTIME services
478     service *s = (service *)service_list;
479     while (s) {
480         if (s->scheduled_downtime_depth > 0) {
481             snprintf(buffer, sizeof(buffer),
482                      "SERVICE DOWNTIME ALERT: %s;%s;STARTED;%s", s->host_name,
483                      s->description,
484                      get_downtime_comment(s->host_name, s->description));
485             write_to_all_logs(buffer, LG_INFO);
486         }
487         s = s->next;
488     }
489     // Log TIMERPERIODS
490     log_timeperiods_cache();
491 }
492 
broker_event(int event_type,void * data)493 int broker_event(int event_type __attribute__((__unused__)), void *data) {
494     g_counters[COUNTER_NEB_CALLBACKS]++;
495     struct nebstruct_timed_event_struct *ts =
496         (struct nebstruct_timed_event_struct *)data;
497     if (ts->event_type == EVENT_LOG_ROTATION) {
498         if (g_thread_running == 1) {
499             livestatus_log_initial_states();
500         } else if (log_initial_states == 1) {
501             write_to_all_logs("logging initial states",
502                               LG_INFO);  // initial info during startup
503         }
504     }
505     update_timeperiods_cache(ts->timestamp.tv_sec);
506     return 0;
507 }
508 
broker_process(int event_type,void * data)509 int broker_process(int event_type __attribute__((__unused__)), void *data) {
510     struct nebstruct_process_struct *ps =
511         (struct nebstruct_process_struct *)data;
512     if (ps->type == NEBTYPE_PROCESS_EVENTLOOPSTART) {
513         update_timeperiods_cache(time(0));
514         start_threads();
515     }
516     return 0;
517 }
518 
verify_event_broker_options()519 int verify_event_broker_options() {
520     int errors = 0;
521     if (!(event_broker_options & BROKER_PROGRAM_STATE)) {
522         logger(LG_CRIT,
523                "need BROKER_PROGRAM_STATE (%i) event_broker_option enabled to "
524                "work.",
525                BROKER_PROGRAM_STATE);
526         errors++;
527     }
528     if (!(event_broker_options & BROKER_TIMED_EVENTS)) {
529         logger(LG_CRIT,
530                "need BROKER_TIMED_EVENTS (%i) event_broker_option enabled to "
531                "work.",
532                BROKER_TIMED_EVENTS);
533         errors++;
534     }
535     if (!(event_broker_options & BROKER_SERVICE_CHECKS)) {
536         logger(LG_CRIT,
537                "need BROKER_SERVICE_CHECKS (%i) event_broker_option enabled to "
538                "work.",
539                BROKER_SERVICE_CHECKS);
540         errors++;
541     }
542     if (!(event_broker_options & BROKER_HOST_CHECKS)) {
543         logger(
544             LG_CRIT,
545             "need BROKER_HOST_CHECKS (%i) event_broker_option enabled to work.",
546             BROKER_HOST_CHECKS);
547         errors++;
548     }
549     if (!(event_broker_options & BROKER_LOGGED_DATA)) {
550         logger(
551             LG_CRIT,
552             "need BROKER_LOGGED_DATA (%i) event_broker_option enabled to work.",
553             BROKER_LOGGED_DATA);
554         errors++;
555     }
556     if (!(event_broker_options & BROKER_COMMENT_DATA)) {
557         logger(LG_CRIT,
558                "need BROKER_COMMENT_DATA (%i) event_broker_option enabled to "
559                "work.",
560                BROKER_COMMENT_DATA);
561         errors++;
562     }
563     if (!(event_broker_options & BROKER_DOWNTIME_DATA)) {
564         logger(LG_CRIT,
565                "need BROKER_DOWNTIME_DATA (%i) event_broker_option enabled to "
566                "work.",
567                BROKER_DOWNTIME_DATA);
568         errors++;
569     }
570     if (!(event_broker_options & BROKER_STATUS_DATA)) {
571         logger(
572             LG_CRIT,
573             "need BROKER_STATUS_DATA (%i) event_broker_option enabled to work.",
574             BROKER_STATUS_DATA);
575         errors++;
576     }
577     if (!(event_broker_options & BROKER_ADAPTIVE_DATA)) {
578         logger(LG_CRIT,
579                "need BROKER_ADAPTIVE_DATA (%i) event_broker_option enabled to "
580                "work.",
581                BROKER_ADAPTIVE_DATA);
582         errors++;
583     }
584     if (!(event_broker_options & BROKER_EXTERNALCOMMAND_DATA)) {
585         logger(LG_CRIT,
586                "need BROKER_EXTERNALCOMMAND_DATA (%i) event_broker_option "
587                "enabled to work.",
588                BROKER_EXTERNALCOMMAND_DATA);
589         errors++;
590     }
591     if (!(event_broker_options & BROKER_STATECHANGE_DATA)) {
592         logger(LG_CRIT,
593                "need BROKER_STATECHANGE_DATA (%i) event_broker_option enabled "
594                "to work.",
595                BROKER_STATECHANGE_DATA);
596         errors++;
597     }
598 
599     return errors == 0;
600 }
601 
register_callbacks()602 void register_callbacks() {
603     neb_register_callback(NEBCALLBACK_HOST_STATUS_DATA, g_nagios_handle, 0,
604                           broker_host);  // Needed to start threads
605     neb_register_callback(NEBCALLBACK_COMMENT_DATA, g_nagios_handle, 0,
606                           broker_comment);  // dynamic data
607     neb_register_callback(NEBCALLBACK_DOWNTIME_DATA, g_nagios_handle, 0,
608                           broker_downtime);  // dynamic data
609     neb_register_callback(NEBCALLBACK_SERVICE_CHECK_DATA, g_nagios_handle, 0,
610                           broker_check);  // only for statistics
611     neb_register_callback(NEBCALLBACK_HOST_CHECK_DATA, g_nagios_handle, 0,
612                           broker_check);  // only for statistics
613     neb_register_callback(NEBCALLBACK_LOG_DATA, g_nagios_handle, 0,
614                           broker_log);  // only for trigger 'log'
615     neb_register_callback(NEBCALLBACK_EXTERNAL_COMMAND_DATA, g_nagios_handle, 0,
616                           broker_command);  // only for trigger 'command'
617     neb_register_callback(NEBCALLBACK_STATE_CHANGE_DATA, g_nagios_handle, 0,
618                           broker_state);  // only for trigger 'state'
619     neb_register_callback(NEBCALLBACK_ADAPTIVE_PROGRAM_DATA, g_nagios_handle, 0,
620                           broker_program);  // only for trigger 'program'
621     neb_register_callback(NEBCALLBACK_PROCESS_DATA, g_nagios_handle, 0,
622                           broker_process);  // used for starting threads
623     neb_register_callback(NEBCALLBACK_TIMED_EVENT_DATA, g_nagios_handle, 0,
624                           broker_event);  // used for timeperiods cache
625 }
626 
deregister_callbacks()627 void deregister_callbacks() {
628     neb_deregister_callback(NEBCALLBACK_HOST_STATUS_DATA, broker_host);
629     neb_deregister_callback(NEBCALLBACK_COMMENT_DATA, broker_comment);
630     neb_deregister_callback(NEBCALLBACK_DOWNTIME_DATA, broker_downtime);
631     neb_deregister_callback(NEBCALLBACK_SERVICE_CHECK_DATA, broker_check);
632     neb_deregister_callback(NEBCALLBACK_HOST_CHECK_DATA, broker_check);
633     neb_deregister_callback(NEBCALLBACK_LOG_DATA, broker_log);
634     neb_deregister_callback(NEBCALLBACK_EXTERNAL_COMMAND_DATA, broker_command);
635     neb_deregister_callback(NEBCALLBACK_STATE_CHANGE_DATA, broker_state);
636     neb_deregister_callback(NEBCALLBACK_ADAPTIVE_PROGRAM_DATA, broker_program);
637     neb_deregister_callback(NEBCALLBACK_PROCESS_DATA, broker_program);
638     neb_deregister_callback(NEBCALLBACK_TIMED_EVENT_DATA, broker_event);
639 }
640 
check_path(const char * name,char * path)641 void check_path(const char *name, char *path) {
642     struct stat st;
643     if (0 == stat(path, &st)) {
644         if (0 != access(path, R_OK)) {
645             logger(LG_ERR, "%s '%s' not readable. Please fix permissions.",
646                    name, path);
647             path[0] = 0;  // disable
648         }
649     } else {
650         logger(LG_ERR, "%s '%s' not existing!", name, path);
651         path[0] = 0;  // disable
652     }
653 }
654 
livestatus_parse_arguments(const char * args_orig)655 void livestatus_parse_arguments(const char *args_orig) {
656     /* set default socket path */
657     strncpy(g_socket_path, DEFAULT_SOCKET_PATH, sizeof(g_socket_path));
658 
659     /* set default path to our logfile to be in the same path as nagios.log */
660     strncpy(g_logfile_path, log_file,
661             sizeof(g_logfile_path) - 16 /* len of "livestatus.log" */);
662     char *slash = strrchr(g_logfile_path, '/');
663     if (!slash) {
664         strncpy(g_logfile_path, "/tmp/livestatus.log", 20);
665     } else {
666         strncpy(slash + 1, "livestatus.log", 15);
667     }
668 
669     /* there is no default PNP path */
670     g_pnp_path[0] = 0;
671 
672     if (!args_orig) {
673         return;  // no arguments, use default options
674     }
675 
676     char *args = strdup(args_orig);
677     char *token;
678     while (0 != (token = next_field(&args))) {
679         /* find = */
680         char *part = token;
681         char *left = next_token(&part, '=');
682         char *right = next_token(&part, 0);
683         if (!right) {
684             strncpy(g_socket_path, left, sizeof(g_socket_path));
685         } else {
686             if (!strcmp(left, "debug")) {
687                 g_debug_level = atoi(right);
688                 logger(LG_INFO, "Setting debug level to %d", g_debug_level);
689             } else if (!strcmp(left, "log_file")) {
690                 strncpy(g_logfile_path, right, sizeof(g_logfile_path));
691             } else if (!strcmp(left, "max_cached_messages")) {
692                 g_max_cached_messages = strtoul(right, 0, 10);
693                 logger(LG_INFO,
694                        "Setting max number of cached log messages to %lu",
695                        g_max_cached_messages);
696             } else if (!strcmp(left, "max_lines_per_logfile")) {
697                 g_max_lines_per_logfile = strtoul(right, 0, 10);
698                 logger(LG_INFO, "Setting max number lines per logfile to %lu",
699                        g_max_lines_per_logfile);
700             } else if (!strcmp(left, "thread_stack_size")) {
701                 g_thread_stack_size = strtoul(right, 0, 10);
702                 logger(LG_INFO, "Setting size of thread stacks to %lu",
703                        g_thread_stack_size);
704             } else if (!strcmp(left, "max_response_size")) {
705                 g_max_response_size = strtoul(right, 0, 10);
706                 logger(LG_INFO,
707                        "Setting maximum response size to %lu bytes (%.1f MB)",
708                        g_max_response_size,
709                        g_max_response_size / (1024.0 * 1024.0));
710             } else if (!strcmp(left, "num_client_threads")) {
711                 int c = atoi(right);
712                 if (c <= 0 || c > 1000) {
713                     logger(LG_INFO,
714                            "Error: Cannot set num_client_threads to %d. Must "
715                            "be > 0 and <= 1000",
716                            c);
717                 } else {
718                     logger(LG_INFO, "Setting number of client threads to %d",
719                            c);
720                     g_num_clientthreads = c;
721                 }
722             } else if (!strcmp(left, "query_timeout")) {
723                 int c = atoi(right);
724                 if (c < 0) {
725                     logger(LG_INFO, "Error: query_timeout must be >= 0");
726                 } else {
727                     g_query_timeout_msec = c;
728                     if (c == 0) {
729                         logger(LG_INFO, "Disabled query timeout!");
730                     } else {
731                         logger(LG_INFO,
732                                "Setting timeout for reading a query to %d ms",
733                                c);
734                     }
735                 }
736             } else if (!strcmp(left, "idle_timeout")) {
737                 int c = atoi(right);
738                 if (c < 0) {
739                     logger(LG_INFO, "Error: idle_timeout must be >= 0");
740                 } else {
741                     g_idle_timeout_msec = c;
742                     if (c == 0) {
743                         logger(LG_INFO, "Disabled idle timeout!");
744                     } else {
745                         logger(LG_INFO, "Setting idle timeout to %d ms", c);
746                     }
747                 }
748             } else if (!strcmp(left, "service_authorization")) {
749                 if (!strcmp(right, "strict")) {
750                     g_service_authorization = AUTH_STRICT;
751                 } else if (!strcmp(right, "loose")) {
752                     g_service_authorization = AUTH_LOOSE;
753                 } else {
754                     logger(LG_INFO,
755                            "Invalid service authorization mode. Allowed are "
756                            "strict and loose.");
757                 }
758             } else if (!strcmp(left, "group_authorization")) {
759                 if (!strcmp(right, "strict")) {
760                     g_group_authorization = AUTH_STRICT;
761                 } else if (!strcmp(right, "loose")) {
762                     g_group_authorization = AUTH_LOOSE;
763                 } else {
764                     logger(LG_INFO,
765                            "Invalid group authorization mode. Allowed are "
766                            "strict and loose.");
767                 }
768             } else if (!strcmp(left, "pnp_path")) {
769                 strncpy(g_pnp_path, right, sizeof(pnp_path_storage) - 1);
770                 // make sure, that trailing slash is always there
771                 if (right[strlen(right) - 1] != '/') {
772                     strncat(g_pnp_path, "/",
773                             sizeof(pnp_path_storage) - strlen(g_pnp_path) - 1);
774                 }
775                 check_path("PNP perfdata directory", g_pnp_path);
776             } else if (!strcmp(left, "mk_inventory_path")) {
777                 strncpy(g_mk_inventory_path, right,
778                         sizeof(g_mk_inventory_path) - 1);
779                 if (right[strlen(right) - 1] != '/') {
780                     strncat(g_mk_inventory_path, "/",
781                             sizeof(g_mk_inventory_path) -
782                                 strlen(g_mk_inventory_path) -
783                                 1);  // make sure, that trailing slash is always
784                 }
785                 // there
786                 check_path("Check_MK Inventory directory", g_mk_inventory_path);
787             } else if (!strcmp(left, "data_encoding")) {
788                 if (!strcmp(right, "utf8")) {
789                     g_data_encoding = ENCODING_UTF8;
790                 } else if (!strcmp(right, "latin1")) {
791                     g_data_encoding = ENCODING_LATIN1;
792                 } else if (!strcmp(right, "mixed")) {
793                     g_data_encoding = ENCODING_MIXED;
794                 } else {
795                     logger(LG_INFO,
796                            "Invalid data_encoding %s. Allowed are utf8, latin1 "
797                            "and mixed.",
798                            right);
799                 }
800             } else if (!strcmp(left, "livecheck")) {
801                 logger(LG_INFO,
802                        "Livecheck has been removed from Livestatus. Sorry.");
803             } else if (!strcmp(left, "disable_statehist_filtering")) {
804                 g_disable_statehist_filtering = atoi(right);
805             } else {
806                 logger(LG_INFO, "Ignoring invalid option %s=%s", left, right);
807             }
808         }
809     }
810     // free(args); won't free, since we use pointers?
811 }
812 
omd_advertize()813 void omd_advertize() {
814     char *omd_site = getenv("OMD_SITE");
815     if (omd_site) {
816         if (g_debug_level > 0) {
817             logger(LG_INFO, "Running on OMD site %s. Cool.", omd_site);
818         }
819     } else {
820         logger(LG_INFO,
821                "Hint: please try out OMD - the Open Monitoring Distribution");
822         logger(LG_INFO, "Please visit OMD at http://omdistro.org");
823     }
824 }
825 
826 /* this function gets called when the module is loaded by the event broker */
827 /* cppcheck-suppress unusedFunction */
nebmodule_init(int flags,char * args,void * handle)828 int nebmodule_init(int flags __attribute__((__unused__)), char *args,
829                    void *handle) {
830     g_nagios_handle = handle;
831     livestatus_parse_arguments(args);
832     open_logfile();
833 
834     logger(LG_INFO, "Livestatus %s by Mathias Kettner. Socket: '%s'", VERSION,
835            g_socket_path);
836     logger(LG_INFO, "Please visit us at http://mathias-kettner.de/");
837 
838     omd_advertize();
839 
840     if (!open_unix_socket()) {
841         return 1;
842     }
843 
844     if (!verify_event_broker_options()) {
845         logger(LG_CRIT, "Fatal: bailing out. Please fix event_broker_options.");
846         logger(LG_CRIT,
847                "Hint: your event_broker_options are set to %d. Try setting it "
848                "to -1.",
849                event_broker_options);
850         return 1;
851     }
852     if (g_debug_level > 0) {
853         logger(LG_INFO,
854                "Your event_broker_options are sufficient for livestatus..");
855     }
856 
857     if (enable_environment_macros == 1) {
858         logger(LG_INFO,
859                "Warning: environment_macros are enabled. This might decrease "
860                "the overall nagios performance");
861     }
862 
863     store_init();
864     register_callbacks();
865 
866     /* Unfortunately, we cannot start our socket thread right now.
867        Nagios demonizes *after* having loaded the NEB modules. When
868        demonizing we are losing our thread. Therefore, we create the
869        thread the first time one of our callbacks is called. Before
870        that happens, we haven't got any data anyway... */
871 
872     logger(LG_INFO, "Finished initialization. Further log messages go to %s",
873            g_logfile_path);
874     return 0;
875 }
876 
877 /* cppcheck-suppress unusedFunction */
nebmodule_deinit(int flags,int reason)878 int nebmodule_deinit(int flags __attribute__((__unused__)),
879                      int reason __attribute__((__unused__))) {
880     logger(LG_INFO, "deinitializing");
881     terminate_threads();
882     close_unix_socket();
883     store_deinit();
884     deregister_callbacks();
885     close_logfile();
886     return 0;
887 }
888