summaryrefslogtreecommitdiffstats
path: root/ulogd.c
diff options
context:
space:
mode:
authorlaforge <laforge>2005-10-02 16:59:48 +0000
committerlaforge <laforge>2005-10-02 16:59:48 +0000
commit778a2f3ddcd69804ff5e948b8dd119609356501b (patch)
tree39d283e3075ea4c5b9ae6b1059d5ab8daeaae37a /ulogd.c
parentb9792bc2f2a4ddb0c88817ae6da698c3f608f388 (diff)
first step towards automake
Diffstat (limited to 'ulogd.c')
-rw-r--r--ulogd.c1008
1 files changed, 0 insertions, 1008 deletions
diff --git a/ulogd.c b/ulogd.c
deleted file mode 100644
index af6a8f7..0000000
--- a/ulogd.c
+++ /dev/null
@@ -1,1008 +0,0 @@
-/* ulogd, Version $LastChangedRevision$
- *
- * $Id$
- *
- * unified network logging daemon for Linux.
- *
- * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Modifications:
- * 14 Jun 2001 Martin Josefsson <gandalf@wlug.westbo.se>
- * - added SIGHUP handler for logfile cycling
- *
- * 10 Feb 2002 Alessandro Bono <a.bono@libero.it>
- * - added support for non-fork mode
- * - added support for logging to stdout
- *
- * 09 Sep 2003 Magnus Boden <sarek@ozaba.cx>
- * - added support for more flexible multi-section conffile
- *
- * 20 Apr 2004 Nicolas Pougetoux <nicolas.pougetoux@edelweb.fr>
- * - added suppurt for seteuid()
- *
- * 22 Jul 2004 Harald Welte <laforge@gnumonks.org>
- * - major restructuring for flow accounting / ipfix work
- *
- * 03 Oct 2004 Harald Welte <laforge@gnumonks.org>
- * - further unification towards generic network event logging
- * and support for lnstat
- *
- * 17 Apr 2005 Harald Welte <laforge@gnumonks.org>
- * -
- */
-
-#define ULOGD_VERSION "2.00alpha"
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-#include <ctype.h>
-#include <signal.h>
-#include <dlfcn.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <grp.h>
-#include <libipulog/libipulog.h>
-#include <ulogd/conffile.h>
-#include <ulogd/ulogd.h>
-#include "select.h"
-#ifdef DEBUG
-#define DEBUGP(format, args...) fprintf(stderr, format, ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
-/* default config parameters, if not changed in configfile */
-#ifndef ULOGD_LOGFILE_DEFAULT
-#define ULOGD_LOGFILE_DEFAULT "/var/log/ulogd.log"
-#endif
-
-/* where to look for the config file */
-#ifndef ULOGD_CONFIGFILE
-#define ULOGD_CONFIGFILE "/etc/ulogd.conf"
-#endif
-
-#define COPYRIGHT \
- "Copyright (C) 2000-2005 Harald Welte <laforge@netfilter.org>\n"
-
-/* global variables */
-static FILE *logfile = NULL; /* logfile pointer */
-static int loglevel = 1; /* current loglevel */
-static char *ulogd_configfile = ULOGD_CONFIGFILE;
-
-/* linked list for all registered interpreters */
-//static struct ulog_interpreter *ulogd_interpreters;
-
-/* linked list for all registered plugins */
-static LIST_HEAD(ulogd_plugins);
-static LIST_HEAD(ulogd_pi_stacks);
-
-#if 0
-/***********************************************************************
- * INTERPRETER AND KEY HASH FUNCTIONS (new in 0.9)
- ***********************************************************************/
-
-/* We keep hashtables of interpreters and registered keys. The hash-tables
- * are allocated dynamically at program load time. You may control the
- e allocation granularity of both hashes (i.e. the amount of hashtable
- * entries are allocated at one time) through modification of the constants
- * INTERH_ALLOC_GRAN and KEYH_ALLOC_GRAN
- */
-
-/* allocation granularity */
-#define INTERH_ALLOC_GRAN 5
-
-/* hashtable for all registered interpreters */
-static struct ulogd_interpreter **ulogd_interh;
-
-/* current hashtable size */
-static unsigned int ulogd_interh_ids_alloc;
-
-/* total number of registered ids */
-static unsigned int ulogd_interh_ids;
-
-/* allocate a new interpreter id and write it into the interpreter struct */
-static unsigned int interh_allocid(struct ulogd_interpreter *ip)
-{
- unsigned int id;
-
- id = ++ulogd_interh_ids;
-
- if (id >= ulogd_interh_ids_alloc) {
- if (!ulogd_interh)
- ulogd_interh = (struct ulogd_interpreter **)
- malloc(INTERH_ALLOC_GRAN *
- sizeof(struct ulogd_interpreter));
- else
- ulogd_interh = (struct ulogd_interpreter **)
- realloc(ulogd_interh,
- (INTERH_ALLOC_GRAN +
- ulogd_interh_ids_alloc) *
- sizeof(struct ulogd_interpreter));
-
- ulogd_interh_ids_alloc += INTERH_ALLOC_GRAN;
- }
-
- ip->id = id;
- ulogd_interh[id] = ip;
- return id;
-}
-
-/* get interpreter id by name */
-unsigned int interh_getid(const char *name)
-{
- unsigned int i;
- for (i = 1; i <= ulogd_interh_ids; i++)
- if (!strcmp(name, (ulogd_interh[i])->name))
- return i;
-
- return 0;
-}
-
-#ifdef DEBUG
-/* dump out the contents of the interpreter hash */
-static void interh_dump(void)
-{
- unsigned int i;
-
- for (i = 1; i <= ulogd_interh_ids; i++)
- ulogd_log(ULOGD_DEBUG, "ulogd_interh[%d] = %s\n",
- i, (ulogd_interh[i])->name);
-
-}
-#endif
-
-/* key hash allocation granularity */
-#define KEYH_ALLOC_GRAN 20
-
-/* hash table for key ids */
-struct ulogd_keyh_entry *ulogd_keyh;
-
-/* current size of the hashtable */
-static unsigned int ulogd_keyh_ids_alloc;
-
-/* total number of registered keys */
-static unsigned int ulogd_keyh_ids;
-
-/* allocate a new key_id */
-static unsigned int keyh_allocid(struct ulogd_interpreter *ip, unsigned int offset,
- const char *name)
-{
- unsigned int id;
-
- id = ++ulogd_keyh_ids;
-
- if (id >= ulogd_keyh_ids_alloc) {
- if (!ulogd_keyh) {
- ulogd_keyh = (struct ulogd_keyh_entry *)
- malloc(KEYH_ALLOC_GRAN *
- sizeof(struct ulogd_keyh_entry));
- if (!ulogd_keyh) {
- ulogd_log(ULOGD_ERROR, "OOM!\n");
- return 0;
- }
- } else {
- ulogd_keyh = (struct ulogd_keyh_entry *)
- realloc(ulogd_keyh, (KEYH_ALLOC_GRAN
- +ulogd_keyh_ids_alloc) *
- sizeof(struct ulogd_keyh_entry));
-
- if (!ulogd_keyh) {
- ulogd_log(ULOGD_ERROR, "OOM!\n");
- return 0;
- }
- }
-
- ulogd_keyh_ids_alloc += KEYH_ALLOC_GRAN;
- }
-
- ulogd_keyh[id].interp = ip;
- ulogd_keyh[id].offset = offset;
- ulogd_keyh[id].name = name;
-
- return id;
-}
-
-#ifdef DEBUG
-/* dump the keyhash to standard output */
-static void keyh_dump(void)
-{
- unsigned int i;
-
- printf("dumping keyh\n");
- for (i = 1; i <= ulogd_keyh_ids; i++)
- printf("ulogd_keyh[%lu] = %s:%u\n", i,
- ulogd_keyh[i].interp->name, ulogd_keyh[i].offset);
-}
-#endif
-
-/* get keyid by name */
-unsigned int keyh_getid(const char *name)
-{
- unsigned int i;
- for (i = 1; i <= ulogd_keyh_ids; i++)
- if (!strcmp(name, ulogd_keyh[i].name))
- return i;
-
- return 0;
-}
-
-/* get key name by keyid */
-char *keyh_getname(unsigned int id)
-{
- if (id > ulogd_keyh_ids) {
- ulogd_log(ULOGD_NOTICE,
- "keyh_getname called with invalid id%u\n", id);
- return NULL;
- }
-
- return ulogd_keyh[id].interp->name;
-}
-
-/* get result for given key id. does not check if result valid */
-struct ulogd_iret *keyh_getres(unsigned int id)
-{
- struct ulogd_iret *ret;
-
- if (id > ulogd_keyh_ids) {
- ulogd_log(ULOGD_NOTICE,
- "keyh_getres called with invalid id %d\n", id);
- return NULL;
- }
-
- ret = &ulogd_keyh[id].interp->result[ulogd_keyh[id].offset];
-
- return ret;
-}
-
-/***********************************************************************
- * INTERPRETER MANAGEMENT
- ***********************************************************************/
-
-/* try to lookup a registered interpreter for a given name */
-static struct ulogd_interpreter *find_interpreter(const char *name)
-{
- unsigned int id;
-
- id = interh_getid(name);
- if (!id)
- return NULL;
-
- return ulogd_interh[id];
-}
-
-/* the function called by all interpreter plugins for registering their
- * target. */
-void register_interpreter(struct ulogd_interpreter *me)
-{
- unsigned int i;
-
- /* check if we already have an interpreter with this name */
- if (find_interpreter(me->name)) {
- ulogd_log(ULOGD_NOTICE,
- "interpreter `%s' already registered\n", me->name);
- return;
- }
-
- ulogd_log(ULOGD_INFO, "registering interpreter `%s'\n", me->name);
-
- /* allocate a new interpreter id for it */
- if (!interh_allocid(me)) {
- ulogd_log(ULOGD_ERROR, "unable to obtain interh_id for "
- "interpreter '%s'\n", me->name);
- return;
- }
-
- /* - allocate one keyh_id for each result of this interpreter
- * - link the elements to each other */
- for (i = 0; i < me->key_num; i++) {
- if (!keyh_allocid(me, i, me->result[i].key)) {
- ulogd_log(ULOGD_ERROR, "unable to obtain keyh_id "
- "for interpreter %s, key %d", me->name,
- me->result[i].key);
- continue;
- }
- if (i != me->key_num - 1)
- me->result[i].next = &me->result[i+1];
- }
-
- /* all work done, we can prepend the new interpreter to the list */
- if (ulogd_interpreters)
- me->result[me->key_num - 1].next =
- &ulogd_interpreters->result[0];
- me->next = ulogd_interpreters;
- ulogd_interpreters = me;
-}
-#endif
-
-/***********************************************************************
- * PLUGIN MANAGEMENT
- ***********************************************************************/
-
-/* try to lookup a registered plugin for a given name */
-static struct ulogd_plugin *find_plugin(const char *name)
-{
- struct ulogd_plugin *pl;
-
- list_for_each_entry(pl, &ulogd_plugins, list) {
- if (strcmp(name, pl->name) == 0)
- return pl;
- }
-
- return NULL;
-}
-
-/* the function called by all plugins for registering themselves */
-void register_plugin(struct ulogd_plugin *me)
-{
- if (find_plugin(me->name)) {
- ulogd_log(ULOGD_NOTICE, "plugin `%s' already registered\n",
- me->name);
- exit(EXIT_FAILURE);
- }
- ulogd_log(ULOGD_NOTICE, "registering plugin `%s'\n", me->name);
- list_add(&me->list, &ulogd_plugins);
-}
-
-/***********************************************************************
- * MAIN PROGRAM
- ***********************************************************************/
-
-/* log message to the logfile */
-void __ulogd_log(int level, char *file, int line, const char *format, ...)
-{
- char *timestr;
- va_list ap;
- time_t tm;
- FILE *outfd;
-
- /* log only messages which have level at least as high as loglevel */
- if (level < loglevel)
- return;
-
- if (logfile)
- outfd = logfile;
- else
- outfd = stderr;
-
- va_start(ap, format);
-
- tm = time(NULL);
- timestr = ctime(&tm);
- timestr[strlen(timestr)-1] = '\0';
- fprintf(outfd, "%s <%1.1d> %s:%d ", timestr, level, file, line);
-
- vfprintf(outfd, format, ap);
- va_end(ap);
-
- /* flush glibc's buffer */
- fflush(outfd);
-}
-
-/* propagate results to all downstream plugins in the stack */
-void ulogd_propagate_results(struct ulogd_pluginstance *pi)
-{
- struct ulogd_pluginstance *cur = pi;
- /* iterate over remaining plugin stack */
- list_for_each_entry_continue(cur, &pi->stack->list, list) {
- int ret;
-
- ret = cur->plugin->interp(cur);
- switch (ret) {
- case ULOGD_IRET_ERR:
- ulogd_log(ULOGD_NOTICE,
- "error during propagate_results\n");
- /* fallthrough */
- case ULOGD_IRET_STOP:
- /* we shall abort further iteration of the stack */
- return;
- case ULOGD_IRET_OK:
- /* we shall continue travelling down the stack */
- continue;
- default:
- ulogd_log(ULOGD_NOTICE,
- "unknown return value `%d' from plugin %s\n",
- ret, cur->plugin->name);
- break;
- }
- }
-}
-
-#if 0
-/* clean results (set all values to 0 and free pointers) */
-static void clean_results(struct ulogd_iret *ret)
-{
- struct ulogd_iret *r;
-
- for (r = ret; r; r = r->next) {
- if (r->flags & ULOGD_RETF_FREE) {
- free(r->value.ptr);
- r->value.ptr = NULL;
- }
- memset(&r->value, 0, sizeof(r->value));
- r->flags &= ~ULOGD_RETF_VALID;
- }
-}
-#endif
-
-static struct ulogd_pluginstance *
-pluginstance_alloc_init(struct ulogd_plugin *pl, char *pi_id,
- struct ulogd_pluginstance_stack *stack)
-{
- unsigned int size;
- struct ulogd_pluginstance *pi;
- void *ptr;
-
- size = sizeof(struct ulogd_pluginstance);
- size += pl->priv_size;
- size += sizeof(struct config_keyset);
- size += pl->config_kset->num_ces * sizeof(struct config_entry);
- size += pl->input.num_keys * sizeof(struct ulogd_key);
- size += pl->output.num_keys * sizeof(struct ulogd_key);
- pi = malloc(size);
- if (!pi)
- return NULL;
-
- /* initialize */
- memset(pi, 0, size);
- INIT_LIST_HEAD(&pi->list);
- pi->plugin = pl;
- pi->stack = stack;
- memcpy(pi->id, pi_id, sizeof(pi->id));
-
- ptr = (void *)pi + sizeof(*pi);
-
- ptr += pl->priv_size;
- /* copy config keys */
- pi->config_kset = ptr;
- pi->config_kset->num_ces = pl->config_kset->num_ces;
- memcpy(pi->config_kset->ces, pl->config_kset->ces,
- pi->config_kset->num_ces * sizeof(struct config_entry));
-
- /* copy input keys */
- ptr += sizeof(struct config_keyset);
- ptr += pi->config_kset->num_ces * sizeof(struct config_entry);
- pi->input = ptr;
- memcpy(pi->input, pl->input.keys,
- pl->input.num_keys * sizeof(struct ulogd_key));
-
- /* copy input keys */
- ptr += pl->input.num_keys * sizeof(struct ulogd_key);
- pi->output = ptr;
- memcpy(pi->output, pl->output.keys,
- pl->output.num_keys * sizeof(struct ulogd_key));
-
- return pi;
-}
-
-
-/* plugin loader to dlopen() a plugins */
-static int load_plugin(char *file)
-{
- if (!dlopen(file, RTLD_NOW)) {
- ulogd_log(ULOGD_ERROR, "load_plugins: '%s': %s\n", file,
- dlerror());
- return 1;
- }
- return 0;
-}
-
-/* find an output key in a given stack, starting at 'start' */
-static struct ulogd_key *
-find_okey_in_stack(char *name,
- struct ulogd_pluginstance_stack *stack,
- struct ulogd_pluginstance *start)
-{
- struct ulogd_pluginstance *pi;
-
- list_for_each_entry_reverse(pi, &start->list, list) {
- int i;
-
- if ((void *)&pi->list == stack)
- return NULL;
-
- for (i = 0; i < pi->plugin->output.num_keys; i++) {
- struct ulogd_key *okey = &pi->output[i];
- if (!strcmp(name, okey->name))
- return okey;
- }
- }
-
- return NULL;
-}
-
-/* resolve key connections from bottom to top of stack */
-static int
-create_stack_resolve_keys(struct ulogd_pluginstance_stack *stack)
-{
- int i = 0;
- struct ulogd_pluginstance *pi_cur;
-
- /* PASS 2: */
- ulogd_log(ULOGD_DEBUG, "connecting input/output keys of stack:\n");
- list_for_each_entry_reverse(pi_cur, &stack->list, list) {
- struct ulogd_pluginstance *pi_prev =
- list_entry(pi_cur->list.prev,
- struct ulogd_pluginstance,
- list);
- if (i == 0) {
- /* first round: output plugin */
- if (pi_cur->plugin->output.type != ULOGD_DTYPE_SINK) {
- ulogd_log(ULOGD_ERROR, "last plugin in stack "
- "has to be output plugin\n");
- return -EINVAL;
- }
- /* continue further down */
- } /* no "else' since first could be the last one, too ! */
-
- if (&pi_prev->list == &stack->list) {
- /* this is the last one in the stack */
- if (pi_cur->plugin->input.type != ULOGD_DTYPE_SOURCE) {
- ulogd_log(ULOGD_ERROR, "first plugin in stack "
- "has to be source plugin\n");
- return -EINVAL;
- }
- /* no need to match keys */
- } else {
- int j;
-
- /* not the last one in the stack */
- if (pi_cur->plugin->input.type !=
- pi_prev->plugin->output.type) {
- ulogd_log(ULOGD_ERROR, "type mismatch between "
- "%s and %s in stack\n",
- pi_cur->plugin->name,
- pi_prev->plugin->name);
- }
- /* call plugin to tell us which keys it requires in
- * given configuration */
- if (pi_cur->plugin->configure) {
- int ret = pi_cur->plugin->configure(pi_cur,
- stack);
- if (ret < 0) {
- ulogd_log(ULOGD_ERROR, "error during "
- "configure of plugin %s\n",
- pi_cur->plugin->name);
- return ret;
- }
- }
-
- for (j = 0; j < pi_cur->plugin->input.num_keys; j++) {
- struct ulogd_key *okey;
- struct ulogd_key *ikey =
- &pi_cur->plugin->input.keys[i];
-
- /* skip those marked as 'inactive' by
- * pl->configure() */
- if (ikey->flags & ULOGD_KEYF_INACTIVE)
- continue;
-
- if (ikey->u.source) {
- ulogd_log(ULOGD_ERROR, "key `%s' "
- "already has source\n",
- ikey->name);
- return -EINVAL;
- }
-
- okey = find_okey_in_stack(ikey->name,
- stack, pi_cur);
- if (!okey &&
- !(ikey->flags & ULOGD_KEYF_OPTIONAL)) {
- ulogd_log(ULOGD_ERROR, "cannot find "
- "key `%s' in stack\n",
- ikey->name);
- return -EINVAL;
- }
-
- ikey->u.source = okey;
- }
- }
- }
-
- return 0;
-}
-
-/* create a new stack of plugins */
-static int create_stack(char *option)
-{
- struct ulogd_pluginstance_stack *stack;
- char *buf = strdup(option);
- char *tok;
- int ret;
-
- if (!buf) {
- ulogd_log(ULOGD_ERROR, "");
- return 1;
- }
-
- stack = malloc(sizeof(*stack));
- if (!stack)
- return -ENOMEM;
- INIT_LIST_HEAD(&stack->list);
-
- ulogd_log(ULOGD_DEBUG, "building new pluginstance stack:\n");
-
- /* PASS 1: find and instanciate plugins of stack, link them together */
- for (tok = strtok(buf, ",\n"); tok; tok = strtok(NULL, ",\n")) {
- char *plname, *equals;
- char pi_id[ULOGD_MAX_KEYLEN];
- struct ulogd_pluginstance *pi;
- struct ulogd_plugin *pl;
-
- /* parse token into sub-tokens */
- equals = strchr(tok, '=');
- if (!equals || (equals - tok >= ULOGD_MAX_KEYLEN)) {
- ulogd_log(ULOGD_ERROR, "syntax error while parsing `%s'"
- "of line `%s'\n", tok, buf);
- free(stack);
- return -EINVAL;
- }
- strncpy(pi_id, tok, ULOGD_MAX_KEYLEN-1);
- pi_id[equals-tok] = '\0';
- plname = equals+1;
-
- /* find matching plugin */
- pl = find_plugin(plname);
- if (!pl) {
- ulogd_log(ULOGD_ERROR, "can't find requested plugin "
- "%s\n", plname);
- free(stack);
- return -ENODEV;
- }
-
- /* allocate */
- pi = pluginstance_alloc_init(pl, pi_id, stack);
- if (!pi) {
- ulogd_log(ULOGD_ERROR,
- "unable to allocate pluginstance for %s\n",
- pi_id);
- free(stack);
- return -ENOMEM;
- }
-
- /* FIXME: call constructor routine from end to beginning,
- * fix up input/output keys */
-
- ulogd_log(ULOGD_DEBUG, "pushing `%s' on stack\n", pl->name);
- list_add(&pi->list, &stack->list);
- }
-
- ret = create_stack_resolve_keys(stack);
- if (ret < 0) {
- free(stack);
- return ret;
- }
-
- /* add head of pluginstance stack to list of stacks */
- list_add(&stack->stack_list, &ulogd_pi_stacks);
- return 0;
-}
-
-
-static int ulogd_main_loop(void)
-{
- int ret = 0;
-
- while (1) {
- ret = ulogd_select_main();
- if (ret == 0)
- continue;
-
- if (ret < 0) {
- if (errno == -EINTR)
- continue;
- else {
- ulogd_log(ULOGD_ERROR, "select returned %s\n",
- strerror(errno));
- break;
- }
- }
- }
-
- return ret;
-}
-
-/* open the logfile */
-static int logfile_open(const char *name)
-{
- if (!strcmp(name,"stdout")) {
- logfile = stdout;
- } else {
- logfile = fopen(name, "a");
- if (!logfile) {
- fprintf(stderr, "ERROR: can't open logfile %s: %s\n",
- name, strerror(errno));
- exit(2);
- }
- }
- ulogd_log(ULOGD_INFO, "ulogd Version %s starting\n", ULOGD_VERSION);
- return 0;
-}
-
-/* wrapper to handle conffile error codes */
-static int parse_conffile(const char *section, struct config_keyset *ce)
-{
- int err;
-
- err = config_parse_file(section, ce);
-
- switch(err) {
- case 0:
- return 0;
- break;
- case -ERROPEN:
- ulogd_log(ULOGD_ERROR,
- "unable to open configfile: %s\n",
- ulogd_configfile);
- break;
- case -ERRMAND:
- ulogd_log(ULOGD_ERROR,
- "mandatory option \"%s\" not found\n",
- config_errce->key);
- break;
- case -ERRMULT:
- ulogd_log(ULOGD_ERROR,
- "option \"%s\" occurred more than once\n",
- config_errce->key);
- break;
- case -ERRUNKN:
- ulogd_log(ULOGD_ERROR,
- "unknown config key \"%s\"\n",
- config_errce->key);
- break;
- case -ERRSECTION:
- ulogd_log(ULOGD_ERROR,
- "section \"%s\" not found\n", section);
- break;
- }
- return 1;
-
-}
-
-
-static struct config_keyset ulogd_kset = {
- .num_ces = 4,
- .ces = {
- {
- .key = "logfile",
- .type = CONFIG_TYPE_STRING,
- .options = CONFIG_OPT_NONE,
- .u.string = ULOGD_LOGFILE_DEFAULT,
- },
- {
- .key = "plugin",
- .type = CONFIG_TYPE_CALLBACK,
- .options = CONFIG_OPT_MULTI,
- .u.parser = &load_plugin,
- },
- {
- .key = "loglevel",
- .type = CONFIG_TYPE_INT,
- .options = CONFIG_OPT_NONE,
- .u.value = 1,
- },
- {
- .key = "stack",
- .type = CONFIG_TYPE_CALLBACK,
- .options = CONFIG_OPT_NONE,
- .u.parser = &create_stack,
- },
- },
-};
-
-#define logfile_ce ulogd_kset.ces[0]
-#define plugin_ce ulogd_kset.ces[1]
-#define loglevel_ce ulogd_kset.ces[2]
-#define stack_ce ulogd_kset.ces[3]
-
-
-static void deliver_signal_pluginstances(int signal)
-{
- struct ulogd_pluginstance_stack *stack;
- struct ulogd_pluginstance *pi;
-
- list_for_each_entry(stack, &ulogd_pi_stacks, stack_list) {
- list_for_each_entry(pi, &stack->list, list) {
- if (pi->plugin->signal)
- (*pi->plugin->signal)(pi, signal);
- }
- }
-}
-
-static void sigterm_handler(int signal)
-{
-
- ulogd_log(ULOGD_NOTICE, "sigterm received, exiting\n");
-
- deliver_signal_pluginstances(signal);
-
- if (logfile != stdout)
- fclose(logfile);
-
- exit(0);
-}
-
-static void signal_handler(int signal)
-{
- ulogd_log(ULOGD_NOTICE, "signal received, calling pluginstances\n");
-
- deliver_signal_pluginstances(signal);
-
- /* reopen logfile */
- if (logfile != stdout) {
- fclose(logfile);
- logfile = fopen(logfile_ce.u.string, "a");
- if (!logfile)
- sigterm_handler(signal);
- }
-}
-
-static void print_usage(void)
-{
- /* FIXME */
- printf("ulogd Version %s\n", ULOGD_VERSION);
- printf(COPYRIGHT);
- printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n");
- printf("Parameters:\n");
- printf("\t-h --help\tThis help page\n");
- printf("\t-V --version\tPrint version information\n");
- printf("\t-d --daemon\tDaemonize (fork into background)\n");
- printf("\t-c --configfile\tUse alternative Configfile\n");
- printf("\t-u --uid\tChange UID/GID\n");
-}
-
-static struct option opts[] = {
- { "version", 0, NULL, 'V' },
- { "daemon", 0, NULL, 'd' },
- { "help", 0, NULL, 'h' },
- { "configfile", 1, NULL, 'c'},
- { "uid", 1, NULL, 'u' },
- { 0 }
-};
-
-int main(int argc, char* argv[])
-{
- int argch;
- int daemonize = 0;
- int change_uid = 0;
- char *user = NULL;
- struct passwd *pw;
- uid_t uid = 0;
- gid_t gid = 0;
-
-
- while ((argch = getopt_long(argc, argv, "c:dh::Vu:", opts, NULL)) != -1) {
- switch (argch) {
- default:
- case '?':
- if (isprint(optopt))
- fprintf(stderr, "Unknown option `-%c'.\n",
- optopt);
- else
- fprintf(stderr, "Unknown option character "
- "`\\x%x'.\n", optopt);
-
- print_usage();
- exit(1);
- break;
- case 'h':
- print_usage();
- exit(0);
- break;
- case 'd':
- daemonize = 1;
- break;
- case 'V':
- printf("ulogd Version %s\n", ULOGD_VERSION);
- printf(COPYRIGHT);
- exit(0);
- break;
- case 'c':
- ulogd_configfile = optarg;
- break;
- case 'u':
- change_uid = 1;
- user = strdup(optarg);
- pw = getpwnam(user);
- if (!pw) {
- printf("Unknown user %s.\n", user);
- free(user);
- exit(1);
- }
- uid = pw->pw_uid;
- gid = pw->pw_gid;
- break;
- }
- }
-
- if (config_register_file(ulogd_configfile)) {
- ulogd_log(ULOGD_FATAL, "error registering configfile \"%s\"\n",
- ulogd_configfile);
- exit(1);
- }
-
- /* parse config file */
- if (parse_conffile("global", &ulogd_kset)) {
- ulogd_log(ULOGD_FATAL, "parse_conffile\n");
- exit(1);
- }
-
- if (change_uid) {
- ulogd_log(ULOGD_NOTICE, "Changing UID / GID\n");
- if (setgid(gid)) {
- ulogd_log(ULOGD_FATAL, "can't set GID %u\n", gid);
- ipulog_perror(NULL);
- exit(1);
- }
- if (setegid(gid)) {
- ulogd_log(ULOGD_FATAL, "can't sett effective GID %u\n",
- gid);
- ipulog_perror(NULL);
- exit(1);
- }
- if (initgroups(user, gid)) {
- ulogd_log(ULOGD_FATAL, "can't set user secondary GID\n");
- ipulog_perror(NULL);
- exit(1);
- }
- if (setuid(uid)) {
- ulogd_log(ULOGD_FATAL, "can't set UID %u\n", uid);
- ipulog_perror(NULL);
- exit(1);
- }
- if (seteuid(uid)) {
- ulogd_log(ULOGD_FATAL, "can't set effective UID %u\n",
- uid);
- ipulog_perror(NULL);
- exit(1);
- }
- }
-
- logfile_open(logfile_ce.u.string);
-
-#ifdef DEBUG
- /* dump key and interpreter hash */
- interh_dump();
- keyh_dump();
-#endif
- if (daemonize){
- if (fork()) {
- exit(0);
- }
- if (logfile != stdout)
- fclose(stdout);
- fclose(stderr);
- fclose(stdin);
- setsid();
- }
-
- signal(SIGTERM, &sigterm_handler);
- signal(SIGHUP, &signal_handler);
-
- ulogd_log(ULOGD_NOTICE,
- "initialization finished, entering main loop\n");
-
- ulogd_main_loop();
-
- /* hackish, but result is the same */
- sigterm_handler(SIGTERM);
- return(0);
-}