[syslog-ng] [PATCH (3.4)] confgen: Implement a built-in system() generator

Gergely Nagy algernon at balabit.hu
Fri Jul 6 14:57:46 CEST 2012


The system SCL plugin relies on a script (generate-system-source.sh)
to generate the block system() expands into. While this is flexible
and easy to modifiy, it has the disadvantage of running an external
script at startup, which is undesirable in many situations, including
when using a strict AppArmor profile.

However, a generated system() is useful in a lot of situations,
ranging from creating portable, system-agnostic configuration files to
supporting sysvinit and systemd with the same config.

For these reasons, this patch implements a built-in system()
generator, that does not rely on the generate-system-source.sh script
at all, but does everything itself, from C.

It should be used similarly to the existing generator:

 @module confgen context(source) name(system) system(yes)

This will result in the very same system() expansion as the script's
as of this patch. The downside is that if one of the generator gets
extended, the other must be updated too, to keep them in sync.

Signed-off-by: Gergely Nagy <algernon at balabit.hu>
---
 modules/confgen/confgen-plugin.c |  174 +++++++++++++++++++++++++++++++++++++-
 scl/system/plugin.conf           |    5 ++
 2 files changed, 175 insertions(+), 4 deletions(-)

diff --git a/modules/confgen/confgen-plugin.c b/modules/confgen/confgen-plugin.c
index ffd24b2..90428b9 100644
--- a/modules/confgen/confgen-plugin.c
+++ b/modules/confgen/confgen-plugin.c
@@ -28,8 +28,13 @@
 #include "messages.h"
 #include "plugin.h"
 
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
 
 gboolean
 confgen_generate(CfgLexer *lexer, gint type, const gchar *name, CfgArgs *args, gpointer user_data)
@@ -87,10 +92,157 @@ confgen_generate(CfgLexer *lexer, gint type, const gchar *name, CfgArgs *args, g
   return TRUE;
 }
 
+static void
+confgen_sysblock_add_unix_dgram(GString *sysblock, const gchar *path,
+                                const gchar *perms)
+{
+  g_string_append_printf(sysblock, "unix-dgram(\"%s\"", path);
+  if (perms)
+    g_string_append_printf(sysblock, " perms(%s)", perms);
+  g_string_append(sysblock, ");\n");
+}
+
+static void
+confgen_sysblock_add_file(GString *sysblock, const gchar *path,
+                          gint follow_freq, const gchar *prg_override,
+                          const gchar *flags)
+{
+  g_string_append_printf(sysblock, "file(\"%s\"", path);
+  if (follow_freq >= 0)
+    g_string_append_printf(sysblock, " follow-freq(%d)", follow_freq);
+  if (prg_override)
+    g_string_append_printf(sysblock, " program-override(\"%s\")", prg_override);
+  if (flags)
+    g_string_append_printf(sysblock, " flags(%s)", flags);
+  g_string_append(sysblock, ");\n");
+}
+
+static void
+confgen_sysblock_add_module(GString *sysblock, const gchar *mod)
+{
+  g_string_append_printf(sysblock, "@module %s\n", mod);
+}
+
+static void
+confgen_sysblock_add_sun_streams(GString *sysblock, const gchar *path,
+                                 const gchar *door)
+{
+  g_string_append_printf(sysblock, "sun-streams(\"%s\"", path);
+  if (door)
+    g_string_append_printf(sysblock, " door(\"%s\")", door);
+  g_string_append(sysblock, ");\n");
+}
+
+static void
+confgen_sysblock_add_pipe(GString *sysblock, const gchar *path, gint pad_size)
+{
+  g_string_append_printf(sysblock, "pipe(\"%s\"", path);
+  if (pad_size >= 0)
+    g_string_append_printf(sysblock, " pad_size(%d)", pad_size);
+  g_string_append(sysblock, ");\n");
+}
+
+gboolean
+confgen_generate_system(CfgLexer *lexer, gint type, const gchar *name,
+                        CfgArgs *args, gpointer user_data)
+{
+  gchar buf[256];
+  GString *sysblock;
+  struct utsname u;
+
+  g_snprintf(buf, sizeof(buf), "%s confgen %s", cfg_lexer_lookup_context_name_by_type(type), name);
+  if (!cfg_args_validate(args, NULL, buf))
+    {
+      msg_error("confgen: confgen invocations do not process arguments, but your argument list is not empty",
+                evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(type)),
+                evt_tag_str("block", name),
+                NULL);
+      return FALSE;
+    }
+
+  sysblock = g_string_sized_new(1024);
+
+  if (uname(&u) != 0)
+    {
+      msg_error("confgen: Cannot get information about the running kernel",
+                evt_tag_errno("error", errno),
+                NULL);
+      return FALSE;
+    }
+
+  if (strcmp(u.sysname, "Linux") == 0)
+    {
+      char *log = "/dev/log";
+
+      if (getenv("LISTEN_FDS") != NULL)
+        {
+          struct stat sbuf;
+
+          if (stat("/run/systemd/journal/syslog", &sbuf) == 0)
+            {
+              if (S_ISSOCK(sbuf.st_mode))
+                log = "/run/systemd/journal/syslog";
+            }
+        }
+
+      confgen_sysblock_add_unix_dgram(sysblock, log, NULL);
+      confgen_sysblock_add_file(sysblock, "/proc/kmsg", -1, "kernel", "kernel");
+    }
+  else if (strcmp(u.sysname, "SunOS") == 0)
+    {
+      confgen_sysblock_add_module(sysblock, "afstreams");
+
+      if (strcmp(u.release, "5.8") == 0)
+        confgen_sysblock_add_sun_streams(sysblock, "/dev/log", NULL);
+      else if (strcmp(u.release, "5.9") == 0)
+        confgen_sysblock_add_sun_streams(sysblock, "/dev/log", "/etc/.syslog_door");
+      else
+        confgen_sysblock_add_sun_streams(sysblock, "/dev/log", "/var/run/syslog_door");
+    }
+  else if (strcmp(u.sysname, "FreeBSD") == 0)
+    {
+      confgen_sysblock_add_unix_dgram(sysblock, "/var/run/log", NULL);
+      confgen_sysblock_add_unix_dgram(sysblock, "/var/run/logpriv", "0600");
+      confgen_sysblock_add_file(sysblock, "/dev/klog", 0, "kernel", "no-parse");
+    }
+  else if (strcmp(u.sysname, "GNU/kFreeBSD") == 0)
+    {
+      confgen_sysblock_add_unix_dgram(sysblock, "/var/run/log", NULL);
+      confgen_sysblock_add_file(sysblock, "/dev/klog", 0, "kernel", NULL);
+    }
+  else if (strcmp(u.sysname, "HP-UX") == 0)
+    {
+      confgen_sysblock_add_pipe(sysblock, "/dev/pipe", 2048);
+    }
+  else if (strcmp(u.sysname, "AIX") == 0 ||
+           strcmp(u.sysname, "OSF1") == 0 ||
+           strncmp(u.sysname, "CYGWIN", 6) == 0)
+    {
+      confgen_sysblock_add_unix_dgram(sysblock, "/dev/log", NULL);
+    }
+  else
+    {
+      msg_error("system(): Error detecting platform, unable to define the system() source. "
+                "Please send your system information to the developers!",
+                evt_tag_str("sysname", u.sysname),
+                evt_tag_str("release", u.release),
+                NULL);
+      return FALSE;
+    }
+
+  if (!cfg_lexer_include_buffer(lexer, buf, sysblock->str, sysblock->len))
+    {
+      g_string_free(sysblock, TRUE);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 gboolean
 confgen_module_init(GlobalConfig *cfg, CfgArgs *args)
 {
-  const gchar *name, *context, *exec;
+  const gchar *name, *context, *exec, *sys;
 
   name = cfg_args_get(args, "name");
   if (!name)
@@ -107,13 +259,27 @@ confgen_module_init(GlobalConfig *cfg, CfgArgs *args)
       return FALSE;
     }
   exec = cfg_args_get(args, "exec");
-  if (!exec)
+  sys = cfg_args_get(args, "system");
+
+  if (!exec && !sys)
+    {
+      msg_error("confgen: exec or system argument expected",
+                NULL);
+      return FALSE;
+    }
+
+  if (exec && sys)
     {
-      msg_error("confgen: exec argument expected",
+      msg_error("confgen: exec and system arguments are mutually excluse",
                 NULL);
       return FALSE;
     }
-  cfg_lexer_register_block_generator(cfg->lexer, cfg_lexer_lookup_context_type_by_name(context), name, confgen_generate, g_strdup(exec), g_free);
+
+  if (exec)
+    cfg_lexer_register_block_generator(cfg->lexer, cfg_lexer_lookup_context_type_by_name(context), name, confgen_generate, g_strdup(exec), g_free);
+  if (sys)
+    cfg_lexer_register_block_generator(cfg->lexer, cfg_lexer_lookup_context_type_by_name(context),
+                                       name, confgen_generate_system, NULL, NULL);
   return TRUE;
 }
 
diff --git a/scl/system/plugin.conf b/scl/system/plugin.conf
index 5ba652e..d150fee 100644
--- a/scl/system/plugin.conf
+++ b/scl/system/plugin.conf
@@ -21,3 +21,8 @@
 #############################################################################
 
 @module confgen context(source) name(system) exec("`scl-root`/system/generate-system-source.sh")
+
+# To use a built-in discovery system, that does not rely on a script,
+# comment out the line above, and uncomment the next one:
+
+#@module confgen context(source) name(system) system(yes)
-- 
1.7.10




More information about the syslog-ng mailing list