~ubuntu-branches/ubuntu/oneiric/syslog-ng/oneiric

« back to all changes in this revision

Viewing changes to src/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2011-05-16 22:02:46 UTC
  • mfrom: (26.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110516220246-nknmeu831n49bx1z
Tags: 3.2.4-1
* New upstream release, fixing infinite loop via PCRE and global. No CVE
  number yet, Vigil@nce id is 10648.
* Remove all patches, they were applied upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2002-2009 BalaBit IT Ltd, Budapest, Hungary
3
 
 *
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.
7
 
 *
8
 
 * Note that this permission is granted for only version 2 of the GPL.
9
 
 *
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.
13
 
 *
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.
18
 
 *
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.
22
 
 */
23
 
  
24
 
#include "syslog-ng.h"
25
 
#include "cfg.h"
26
 
#include "messages.h"
27
 
#include "memtrace.h"
28
 
#include "children.h"
29
 
#include "misc.h"
30
 
#include "stats.h"
31
 
#include "apphook.h"
32
 
#include "alarms.h"
33
 
#include "logqueue.h"
34
 
#include "gprocess.h"
35
 
#include "control.h"
36
 
#include "timeutils.h"
37
 
 
38
 
#if ENABLE_SSL
39
 
#include <openssl/ssl.h>
40
 
#include <openssl/rand.h>
41
 
#endif
42
 
 
43
 
 
44
 
#include <sys/types.h>
45
 
#include <stdio.h>
46
 
#include <stdlib.h>
47
 
#include <string.h>
48
 
 
49
 
#include <signal.h>
50
 
#include <unistd.h>
51
 
#include <fcntl.h>
52
 
#include <sys/wait.h>
53
 
 
54
 
#include <grp.h>
55
 
 
56
 
#if HAVE_GETOPT_H
57
 
#include <getopt.h>
58
 
#endif
59
 
 
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;
68
 
 
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;
72
 
 
73
 
static void 
74
 
sig_hup_handler(int signo)
75
 
{
76
 
  sig_hup_received = TRUE;
77
 
}
78
 
 
79
 
static void
80
 
sig_term_handler(int signo)
81
 
{
82
 
  sig_term_received = TRUE;
83
 
}
84
 
 
85
 
static void
86
 
sig_child_handler(int signo)
87
 
{
88
 
  sig_child_received = TRUE;
89
 
}
90
 
 
91
 
static void
92
 
setup_signals(void)
93
 
{
94
 
  struct sigaction sa;
95
 
  
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);
107
 
}
108
 
 
109
 
gboolean
110
 
stats_timer(gpointer st)
111
 
{
112
 
  stats_generate_log();
113
 
  return TRUE;
114
 
}
115
 
 
116
 
static GStaticMutex main_loop_lock = G_STATIC_MUTEX_INIT;
117
 
static GMainLoop *main_loop = NULL;
118
 
static GPollFunc system_poll_func = NULL;
119
 
 
120
 
void
121
 
main_loop_wakeup(void)
122
 
{
123
 
  g_static_mutex_lock(&main_loop_lock);
124
 
  if (main_loop)
125
 
    g_main_context_wakeup(g_main_loop_get_context(main_loop));
126
 
  g_static_mutex_unlock(&main_loop_lock);
127
 
}
128
 
 
129
 
gint
130
 
main_context_poll(GPollFD *ufds, guint nfsd, gint timeout_)
131
 
{
132
 
  gint ret = (*system_poll_func)(ufds, nfsd, timeout_);
133
 
  update_g_current_time();
134
 
  return ret;
135
 
}
136
 
 
137
 
int 
138
 
main_loop_run(GlobalConfig **cfg)
139
 
{
140
 
  gint iters;
141
 
  guint stats_timer_id = 0;
142
 
  sigset_t ss;
143
 
 
144
 
  msg_notice("syslog-ng starting up", 
145
 
             evt_tag_str("version", VERSION),
146
 
             NULL);
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);
150
 
    
151
 
  control_init(ctlfilename, g_main_loop_get_context(main_loop));
152
 
 
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))
156
 
    {
157
 
      if ((*cfg)->time_sleep > 0)
158
 
        {
159
 
          struct timespec ts;
160
 
          
161
 
          ts.tv_sec = (*cfg)->time_sleep / 1000;
162
 
          ts.tv_nsec = ((*cfg)->time_sleep % 1000) * 1E6;
163
 
          
164
 
          nanosleep(&ts, NULL);
165
 
        }
166
 
      g_main_context_iteration(g_main_loop_get_context(main_loop), TRUE);
167
 
      if (sig_hup_received)
168
 
        {
169
 
          sigemptyset(&ss);
170
 
          sigaddset(&ss, SIGHUP);
171
 
          sigprocmask(SIG_BLOCK, &ss, NULL);
172
 
          sig_hup_received = FALSE;
173
 
 
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. */
181
 
 
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", 
186
 
                       NULL);
187
 
          reset_cached_hostname();
188
 
          if ((*cfg)->stats_freq > 0)
189
 
            {
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);
193
 
            }
194
 
          stats_cleanup_orphans();
195
 
          sigprocmask(SIG_UNBLOCK, &ss, NULL);
196
 
        }
197
 
      if (sig_term_received)
198
 
        {
199
 
          msg_info("Termination requested via signal, terminating", NULL);
200
 
          sig_term_received = FALSE;
201
 
          break;
202
 
        }
203
 
      if (sig_child_received)
204
 
        {
205
 
          pid_t pid;
206
 
          int status;
207
 
 
208
 
          sigemptyset(&ss);
209
 
          sigaddset(&ss, SIGCHLD);
210
 
          sigprocmask(SIG_BLOCK, &ss, NULL);
211
 
          sig_child_received = FALSE;
212
 
 
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 */
216
 
 
217
 
          do
218
 
            {
219
 
              pid = waitpid(-1, &status, WNOHANG);
220
 
              child_manager_sigchild(pid, status);
221
 
            }
222
 
          while (pid > 0);
223
 
          sigprocmask(SIG_UNBLOCK, &ss, NULL);
224
 
        }
225
 
    }
226
 
  control_destroy();
227
 
  msg_notice("syslog-ng shutting down", 
228
 
             evt_tag_str("version", VERSION),
229
 
             NULL);
230
 
  iters = 0;
231
 
  while (g_main_context_iteration(NULL, FALSE) && iters < 3)
232
 
    {
233
 
      iters++;
234
 
    }
235
 
  g_static_mutex_lock(&main_loop_lock);
236
 
  g_main_loop_unref(main_loop);
237
 
  main_loop = NULL;
238
 
  g_static_mutex_unlock(&main_loop_lock);
239
 
  return 0;
240
 
}
241
 
 
242
 
#if ENABLE_SSL
243
 
static void
244
 
tls_init(void)
245
 
{
246
 
  char rnd_file[256];
247
 
  
248
 
  if (seed_rng)
249
 
    {
250
 
      RAND_file_name(rnd_file, sizeof(rnd_file));
251
 
      if (rnd_file[0])
252
 
        RAND_load_file(rnd_file, -1);
253
 
    }
254
 
  SSL_library_init();
255
 
  SSL_load_error_strings();
256
 
  SSLeay_add_all_algorithms();
257
 
}
258
 
 
259
 
static void
260
 
tls_deinit(void)
261
 
{
262
 
  char rnd_file[256];
263
 
  
264
 
  if (seed_rng)
265
 
    {
266
 
      RAND_file_name(rnd_file, sizeof(rnd_file));
267
 
      if (rnd_file[0])
268
 
        RAND_write_file(rnd_file);
269
 
    }
270
 
}
271
 
#else
272
 
 
273
 
#define tls_init()
274
 
#define tls_deinit()
275
 
 
276
 
#endif
277
 
 
278
 
#ifdef YYDEBUG
279
 
extern int yydebug;
280
 
#endif
281
 
 
282
 
 
283
 
static GOptionEntry syslogng_options[] = 
284
 
{
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>" },
291
 
#ifdef YYDEBUG
292
 
  { "yydebug",           'y',         0, G_OPTION_ARG_NONE, &yydebug, "Enable configuration parser debugging", NULL },
293
 
#endif
294
 
  { NULL },
295
 
};
296
 
 
297
 
/* 
298
 
 * Returns: exit code to be returned to the calling process.
299
 
 */
300
 
int 
301
 
initial_init(GlobalConfig **cfg)
302
 
{
303
 
  
304
 
  app_startup();
305
 
  setup_signals();
306
 
 
307
 
  tls_init();
308
 
  *cfg = cfg_new(cfgfilename);
309
 
  if (!(*cfg))
310
 
    {
311
 
      return 1;
312
 
    }
313
 
 
314
 
  if (syntax_only)
315
 
    {
316
 
      return 0;
317
 
    }
318
 
 
319
 
  cfg_persist_config_load(*cfg, persist_file);
320
 
 
321
 
  if (!cfg_init(*cfg))
322
 
    {
323
 
      return 2;
324
 
    }
325
 
  return 0;
326
 
}
327
 
 
328
 
#define INSTALL_DAT_INSTALLER_VERSION "INSTALLER_VERSION"
329
 
 
330
 
gboolean
331
 
get_installer_version(gchar **inst_version)
332
 
{
333
 
  gchar line[1024];
334
 
  gboolean result = FALSE;
335
 
  FILE *f_install = fopen(install_dat_filename, "r");
336
 
 
337
 
  if (!f_install)
338
 
    return FALSE;
339
 
 
340
 
  while (fgets(line, sizeof(line), f_install) != NULL)
341
 
    {
342
 
      if (strncmp(line, INSTALL_DAT_INSTALLER_VERSION, strlen(INSTALL_DAT_INSTALLER_VERSION)) == 0)
343
 
        {
344
 
          gchar *pos = strchr(line, '=');
345
 
          if (pos)
346
 
            {
347
 
              *inst_version = strdup(pos+1);
348
 
              result = TRUE;
349
 
              break;
350
 
            }
351
 
        }
352
 
    }
353
 
  fclose(f_install);
354
 
  return result;
355
 
}
356
 
 
357
 
#define ON_OFF_STR(x) (x ? "on" : "off")
358
 
 
359
 
 
360
 
void
361
 
version(void)
362
 
{
363
 
  if (!get_installer_version(&installer_version) || installer_version==NULL)
364
 
    {
365
 
      installer_version=VERSION;
366
 
    }
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"
372
 
         "Enable-Debug: %s\n"
373
 
         "Enable-GProf: %s\n"
374
 
         "Enable-Memtrace: %s\n"
375
 
         "Enable-Sun-STREAMS: %s\n"
376
 
         "Enable-Sun-Door: %s\n"
377
 
         "Enable-IPv6: %s\n"
378
 
         "Enable-Spoof-Source: %s\n"
379
 
         "Enable-TCP-Wrapper: %s\n"
380
 
         "Enable-SSL: %s\n"
381
 
         "Enable-SQL: %s\n"
382
 
         "Enable-Linux-Caps: %s\n"
383
 
         "Enable-Pcre: %s\n",
384
 
         installer_version,
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));
398
 
}
399
 
 
400
 
int 
401
 
main(int argc, char *argv[])
402
 
{
403
 
  GlobalConfig *cfg;
404
 
  gint rc;
405
 
  GOptionContext *ctx;
406
 
  GError *error = NULL;
407
 
 
408
 
  z_mem_trace_init("syslog-ng.trace");
409
 
 
410
 
  g_process_set_argv_space(argc, (gchar **) argv);
411
 
  
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. */
415
 
  
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 "
418
 
                     "cap_sys_admin=ep");
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))
424
 
    {
425
 
      fprintf(stderr, "Error parsing command line arguments: %s", error ? error->message : "Invalid arguments");
426
 
      g_option_context_free(ctx);
427
 
      return 1;
428
 
    }
429
 
  g_option_context_free(ctx);
430
 
  if (argc > 1)
431
 
    {
432
 
      fprintf(stderr, "Excess number of arguments\n");
433
 
      return 1;
434
 
    }
435
 
 
436
 
  if (display_version)
437
 
    {
438
 
      version();
439
 
      return 0;
440
 
    }
441
 
 
442
 
  if (debug_flag)
443
 
    {
444
 
      log_stderr = TRUE;
445
 
    }
446
 
 
447
 
  if (syntax_only || debug_flag)
448
 
    {
449
 
      g_process_set_mode(G_PM_FOREGROUND);
450
 
    }
451
 
 
452
 
  g_process_set_name("syslog-ng");
453
 
  
454
 
  /* in this case we switch users early while retaining a limited set of
455
 
   * credentials in order to initialize/reinitialize the configuration.
456
 
   */
457
 
  g_process_start();
458
 
  rc = initial_init(&cfg);
459
 
  
460
 
  if (rc)
461
 
    {
462
 
      g_process_startup_failed(rc, TRUE);
463
 
      return rc;
464
 
    }
465
 
  else
466
 
    {
467
 
      if (syntax_only)
468
 
        g_process_startup_failed(0, TRUE);
469
 
      else
470
 
        g_process_startup_ok();
471
 
    }
472
 
 
473
 
  /* we are running as a non-root user from this point */
474
 
  
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();
479
 
  
480
 
  rc = main_loop_run(&cfg);
481
 
 
482
 
  cfg_deinit(cfg);
483
 
  
484
 
  if (cfg->persist)
485
 
    {
486
 
      cfg_persist_config_save(cfg, persist_file);
487
 
    }
488
 
 
489
 
  cfg_free(cfg);
490
 
  
491
 
  app_shutdown();
492
 
  tls_deinit();
493
 
  z_mem_trace_dump();
494
 
  g_process_finish();
495
 
  return rc;
496
 
}
497