2
* Copyright (c) 2002-2009 BalaBit IT Ltd, Budapest, Hungary
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 as published
6
* by the Free Software Foundation.
8
* Note that this permission is granted for only version 2 of the GPL.
10
* As an additional exemption you are allowed to compile & link against the
11
* OpenSSL libraries as published by the OpenSSL project. See the file
12
* COPYING for details.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
#include "syslog-ng.h"
36
#include "timeutils.h"
39
#include <openssl/ssl.h>
40
#include <openssl/rand.h>
44
#include <sys/types.h>
60
static gchar *cfgfilename = PATH_SYSLOG_NG_CONF;
61
static gchar *install_dat_filename = PATH_INSTALL_DAT;
62
static gchar *installer_version = NULL;
63
static const gchar *persist_file = PATH_PERSIST_CONFIG;
64
static gboolean syntax_only = FALSE;
65
static gboolean seed_rng = FALSE;
66
static gboolean display_version = FALSE;
67
static gchar *ctlfilename = PATH_CONTROL_SOCKET;
69
static volatile sig_atomic_t sig_hup_received = FALSE;
70
static volatile sig_atomic_t sig_term_received = FALSE;
71
static volatile sig_atomic_t sig_child_received = FALSE;
74
sig_hup_handler(int signo)
76
sig_hup_received = TRUE;
80
sig_term_handler(int signo)
82
sig_term_received = TRUE;
86
sig_child_handler(int signo)
88
sig_child_received = TRUE;
96
memset(&sa, 0, sizeof(sa));
97
sa.sa_handler = SIG_IGN;
98
sigaction(SIGPIPE, &sa, NULL);
99
sa.sa_handler = sig_hup_handler;
100
sigaction(SIGHUP, &sa, NULL);
101
sa.sa_handler = sig_term_handler;
102
sigaction(SIGTERM, &sa, NULL);
103
sa.sa_handler = sig_term_handler;
104
sigaction(SIGINT, &sa, NULL);
105
sa.sa_handler = sig_child_handler;
106
sigaction(SIGCHLD, &sa, NULL);
110
stats_timer(gpointer st)
112
stats_generate_log();
116
static GStaticMutex main_loop_lock = G_STATIC_MUTEX_INIT;
117
static GMainLoop *main_loop = NULL;
118
static GPollFunc system_poll_func = NULL;
121
main_loop_wakeup(void)
123
g_static_mutex_lock(&main_loop_lock);
125
g_main_context_wakeup(g_main_loop_get_context(main_loop));
126
g_static_mutex_unlock(&main_loop_lock);
130
main_context_poll(GPollFD *ufds, guint nfsd, gint timeout_)
132
gint ret = (*system_poll_func)(ufds, nfsd, timeout_);
133
update_g_current_time();
138
main_loop_run(GlobalConfig **cfg)
141
guint stats_timer_id = 0;
144
msg_notice("syslog-ng starting up",
145
evt_tag_str("version", VERSION),
147
main_loop = g_main_loop_new(NULL, TRUE);
148
if ((*cfg)->stats_freq > 0)
149
stats_timer_id = g_timeout_add((*cfg)->stats_freq * 1000, stats_timer, NULL);
151
control_init(ctlfilename, g_main_loop_get_context(main_loop));
153
system_poll_func = g_main_context_get_poll_func(g_main_loop_get_context(main_loop));
154
g_main_context_set_poll_func(g_main_loop_get_context(main_loop), main_context_poll);
155
while (g_main_loop_is_running(main_loop))
157
if ((*cfg)->time_sleep > 0)
161
ts.tv_sec = (*cfg)->time_sleep / 1000;
162
ts.tv_nsec = ((*cfg)->time_sleep % 1000) * 1E6;
164
nanosleep(&ts, NULL);
166
g_main_context_iteration(g_main_loop_get_context(main_loop), TRUE);
167
if (sig_hup_received)
170
sigaddset(&ss, SIGHUP);
171
sigprocmask(SIG_BLOCK, &ss, NULL);
172
sig_hup_received = FALSE;
174
/* this may handle multiple SIGHUP signals, however it doesn't
175
* really matter if we received only a single or multiple SIGHUPs
176
* until we make sure that we handle the last one. Since we
177
* blocked the SIGHUP signal and reset sig_hup_received to FALSE,
178
* we can be sure that if we receive an additional SIGHUP during
179
* signal processing we get the new one when we finished this, and
180
* handle that one as well. */
182
app_pre_config_loaded();
183
(*cfg) = cfg_reload_config(cfgfilename, (*cfg));
184
app_post_config_loaded();
185
msg_notice("Configuration reload request received, reloading configuration",
187
reset_cached_hostname();
188
if ((*cfg)->stats_freq > 0)
190
if (stats_timer_id != 0)
191
g_source_remove(stats_timer_id);
192
stats_timer_id = g_timeout_add((*cfg)->stats_freq * 1000, stats_timer, NULL);
194
stats_cleanup_orphans();
195
sigprocmask(SIG_UNBLOCK, &ss, NULL);
197
if (sig_term_received)
199
msg_info("Termination requested via signal, terminating", NULL);
200
sig_term_received = FALSE;
203
if (sig_child_received)
209
sigaddset(&ss, SIGCHLD);
210
sigprocmask(SIG_BLOCK, &ss, NULL);
211
sig_child_received = FALSE;
213
/* this may handle multiple SIGCHLD signals, however it doesn't
214
* matter if one or multiple SIGCHLD was received assuming that
215
* all exited child process are waited for */
219
pid = waitpid(-1, &status, WNOHANG);
220
child_manager_sigchild(pid, status);
223
sigprocmask(SIG_UNBLOCK, &ss, NULL);
227
msg_notice("syslog-ng shutting down",
228
evt_tag_str("version", VERSION),
231
while (g_main_context_iteration(NULL, FALSE) && iters < 3)
235
g_static_mutex_lock(&main_loop_lock);
236
g_main_loop_unref(main_loop);
238
g_static_mutex_unlock(&main_loop_lock);
250
RAND_file_name(rnd_file, sizeof(rnd_file));
252
RAND_load_file(rnd_file, -1);
255
SSL_load_error_strings();
256
SSLeay_add_all_algorithms();
266
RAND_file_name(rnd_file, sizeof(rnd_file));
268
RAND_write_file(rnd_file);
283
static GOptionEntry syslogng_options[] =
285
{ "cfgfile", 'f', 0, G_OPTION_ARG_STRING, &cfgfilename, "Set config file name, default=" PATH_SYSLOG_NG_CONF, "<config>" },
286
{ "persist-file", 'R', 0, G_OPTION_ARG_STRING, &persist_file, "Set the name of the persistent configuration file, default=" PATH_PERSIST_CONFIG, "<fname>" },
287
{ "syntax-only", 's', 0, G_OPTION_ARG_NONE, &syntax_only, "Only read and parse config file", NULL},
288
{ "version", 'V', 0, G_OPTION_ARG_NONE, &display_version, "Display version number (" PACKAGE " " VERSION ")", NULL },
289
{ "seed", 'S', 0, G_OPTION_ARG_NONE, &seed_rng, "Seed the RNG using ~/.rnd or $RANDFILE", NULL},
290
{ "control", 'c', 0, G_OPTION_ARG_STRING, &ctlfilename, "Set syslog-ng control socket, default=" PATH_CONTROL_SOCKET, "<ctlpath>" },
292
{ "yydebug", 'y', 0, G_OPTION_ARG_NONE, &yydebug, "Enable configuration parser debugging", NULL },
298
* Returns: exit code to be returned to the calling process.
301
initial_init(GlobalConfig **cfg)
308
*cfg = cfg_new(cfgfilename);
319
cfg_persist_config_load(*cfg, persist_file);
328
#define INSTALL_DAT_INSTALLER_VERSION "INSTALLER_VERSION"
331
get_installer_version(gchar **inst_version)
334
gboolean result = FALSE;
335
FILE *f_install = fopen(install_dat_filename, "r");
340
while (fgets(line, sizeof(line), f_install) != NULL)
342
if (strncmp(line, INSTALL_DAT_INSTALLER_VERSION, strlen(INSTALL_DAT_INSTALLER_VERSION)) == 0)
344
gchar *pos = strchr(line, '=');
347
*inst_version = strdup(pos+1);
357
#define ON_OFF_STR(x) (x ? "on" : "off")
363
if (!get_installer_version(&installer_version) || installer_version==NULL)
365
installer_version=VERSION;
367
printf(PACKAGE " " VERSION "\n"
368
"Installer-Version: %s\n"
369
"Revision: " SOURCE_REVISION "\n"
370
"Compile-Date: " __DATE__ " " __TIME__ "\n"
371
"Enable-Threads: %s\n"
374
"Enable-Memtrace: %s\n"
375
"Enable-Sun-STREAMS: %s\n"
376
"Enable-Sun-Door: %s\n"
378
"Enable-Spoof-Source: %s\n"
379
"Enable-TCP-Wrapper: %s\n"
382
"Enable-Linux-Caps: %s\n"
385
ON_OFF_STR(ENABLE_THREADS),
386
ON_OFF_STR(ENABLE_DEBUG),
387
ON_OFF_STR(ENABLE_GPROF),
388
ON_OFF_STR(ENABLE_MEMTRACE),
389
ON_OFF_STR(ENABLE_SUN_STREAMS),
390
ON_OFF_STR(ENABLE_SUN_DOOR),
391
ON_OFF_STR(ENABLE_IPV6),
392
ON_OFF_STR(ENABLE_SPOOF_SOURCE),
393
ON_OFF_STR(ENABLE_TCP_WRAPPER),
394
ON_OFF_STR(ENABLE_SSL),
395
ON_OFF_STR(ENABLE_SQL),
396
ON_OFF_STR(ENABLE_LINUX_CAPS),
397
ON_OFF_STR(ENABLE_PCRE));
401
main(int argc, char *argv[])
406
GError *error = NULL;
408
z_mem_trace_init("syslog-ng.trace");
410
g_process_set_argv_space(argc, (gchar **) argv);
412
/* NOTE: polling /proc/kmsg requires cap_sys_admin, otherwise it'll always
413
* indicate readability. Enabling/disabling cap_sys_admin on every poll
414
* invocation seems to be too expensive. So I enable it for now. */
416
g_process_set_caps("cap_net_bind_service,cap_net_broadcast,cap_net_raw,"
417
"cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner=p "
419
ctx = g_option_context_new("syslog-ng");
420
g_process_add_option_group(ctx);
421
msg_add_option_group(ctx);
422
g_option_context_add_main_entries(ctx, syslogng_options, NULL);
423
if (!g_option_context_parse(ctx, &argc, &argv, &error))
425
fprintf(stderr, "Error parsing command line arguments: %s", error ? error->message : "Invalid arguments");
426
g_option_context_free(ctx);
429
g_option_context_free(ctx);
432
fprintf(stderr, "Excess number of arguments\n");
447
if (syntax_only || debug_flag)
449
g_process_set_mode(G_PM_FOREGROUND);
452
g_process_set_name("syslog-ng");
454
/* in this case we switch users early while retaining a limited set of
455
* credentials in order to initialize/reinitialize the configuration.
458
rc = initial_init(&cfg);
462
g_process_startup_failed(rc, TRUE);
468
g_process_startup_failed(0, TRUE);
470
g_process_startup_ok();
473
/* we are running as a non-root user from this point */
475
app_post_daemonized();
476
app_post_config_loaded();
477
/* from now on internal messages are written to the system log as well */
478
msg_syslog_started();
480
rc = main_loop_run(&cfg);
486
cfg_persist_config_save(cfg, persist_file);