From 5ba28a98cfef1ed7cb7445916a11ca88982d506f Mon Sep 17 00:00:00 2001 From: laforge Date: Sun, 2 Oct 2005 16:41:03 +0000 Subject: too many changes to comment on. ulogd now compiles again. --- ARCHITECTURE | 17 ++ Makefile.in | 10 +- include/ulogd/ulogd.h | 48 ++++- input/packet/ulogd_inppkt_NFLOG.c | 3 +- output/ulogd_output_LOGEMU.c | 74 ++++--- select.c | 46 +++-- select.h | 2 + ulogd.c | 401 ++++++++++++++++++++++++-------------- util/printpkt.c | 187 ++++++++++-------- 9 files changed, 492 insertions(+), 296 deletions(-) create mode 100644 select.h diff --git a/ARCHITECTURE b/ARCHITECTURE index c9264b3..f825a0a 100644 --- a/ARCHITECTURE +++ b/ARCHITECTURE @@ -60,3 +60,20 @@ Architecture of ulogd2 - problems: - multiple interpreters can return same value (i.e. sport/dport) - some outputs/filters will require _ALL_ keys (e.g. OPRINT) + +Plugin stack building + +- start at final output plugin in stack. + - pass list of input keys to previous plugin in stack + - next plugin in stack verifies that it can provide those keys, + and determines it's required input keys. pass them to next plugin + +if current plugin cannot support this key, a plugin further up the stack could! +two-pass approach: +1) connect next<->prev pointers so plugin stack is known +2) start from output plugin and go upwards + +- list of "can provide" keys should be per instance, since configuration + parameters could determine the possible keys. -LATER + + diff --git a/Makefile.in b/Makefile.in index 21069eb..1661f72 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,12 +17,12 @@ endif ifeq (x@HAVE_PCAP_H@,x) else -SUBDIRS+=pcap +SUBDIRS+=output/pcap endif -ULOGD_VERSION=1.10 -OLD_ULOGD_VERSION=1.09 +ULOGD_VERSION=2.00 +OLD_ULOGD_VERSION=1.23 # Normally You should not need to change anything below @@ -56,8 +56,8 @@ diff: $(RELEASE_DIR)/ulogd-$(ULOGD_VERSION).tar.bz2 recurse: @for d in $(SUBDIRS); do if ! make -C $$d; then exit 1; fi; done -ulogd: ulogd.c $(LIBIPULOG) include/ulogd/ulogd.h conffile/conffile.o $(LIBIPULOG)/libipulog.a ulogd.conf - $(CC) $(CFLAGS) -rdynamic $< conffile/conffile.o $(LIBIPULOG)/libipulog.a -o $@ $(LIBS) +ulogd: ulogd.c select.c conffile/conffile.o + $(CC) $(CFLAGS) -rdynamic $^ conffile/conffile.o -o $@ $(LIBS) edit = sed -e 's,@libdir\@,$(ULOGD_LIB_PATH),g' diff --git a/include/ulogd/ulogd.h b/include/ulogd/ulogd.h index 1000fb1..13da05b 100644 --- a/include/ulogd/ulogd.h +++ b/include/ulogd/ulogd.h @@ -19,6 +19,9 @@ #include /* need this because of extension-sighandler */ #include +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + + /* All types with MSB = 1 make use of value.ptr * other types use one of the union's member */ @@ -51,6 +54,10 @@ #define ULOGD_RETF_NEEDED 0x0004 /* this parameter is actually needed * by some downstream plugin */ +#define ULOGD_KEYF_OPTIONAL 0x0100 /* this key is optional */ +#define ULOGD_KEYF_INACTIVE 0x0200 /* marked as inactive (i.e. totally + to be ignored by everyone */ + /* maximum length of ulogd key */ #define ULOGD_MAX_KEYLEN 32 @@ -61,7 +68,7 @@ #define ULOGD_ERROR 7 /* error condition, requires user action */ #define ULOGD_FATAL 8 /* fatal, program aborted */ -extern FILE *logfile; +//extern FILE *logfile; /* ulogd data type */ enum ulogd_dtype { @@ -79,7 +86,7 @@ struct ulogd_key { struct ulogd_key *next; /* length of the returned value (only for lengthed types */ u_int32_t len; - /* type of the returned value (ULOGD_IRET_...) */ + /* type of the returned value (ULOGD_DTYPE_...) */ u_int16_t type; /* flags (i.e. free, ...) */ u_int16_t flags; @@ -109,6 +116,7 @@ struct ulogd_key { } u; }; +struct ulogd_pluginstance_stack; struct ulogd_pluginstance; struct ulogd_plugin { /* global list of plugins */ @@ -137,23 +145,36 @@ struct ulogd_plugin { /* function to call for each packet */ int (*interp)(struct ulogd_pluginstance *instance); + int (*configure)(struct ulogd_pluginstance *instance, + struct ulogd_pluginstance_stack *stack); + /* function to construct a new pluginstance */ - struct ulogd_pluginstance *(*constructor)(struct ulogd_plugin *pl); + int (*start)(struct ulogd_pluginstance *pi); /* function to destruct an existing pluginstance */ - int (*destructor)(struct ulogd_pluginstance *instance); + int (*stop)(struct ulogd_pluginstance *pi); + + /* function to receive a signal */ + void (*signal)(struct ulogd_pluginstance *pi, int signal); /* configuration parameters */ struct config_keyset *config_kset; + + /* size of instance->priv */ + unsigned int priv_size; }; +#define ULOGD_IRET_ERR -1 +#define ULOGD_IRET_STOP -2 +#define ULOGD_IRET_OK 0 + /* an instance of a plugin, element in a stack */ struct ulogd_pluginstance { - /* global list of pluginstance stacks. only valid for first item */ - struct list_head stack_list; /* local list of plugins in this stack */ struct list_head list; - /* plugin (master) */ + /* plugin */ struct ulogd_plugin *plugin; + /* stack that we're part of */ + struct ulogd_pluginstance_stack *stack; /* name / id of this instance*/ char id[ULOGD_MAX_KEYLEN]; /* per-instance input keys */ @@ -161,11 +182,19 @@ struct ulogd_pluginstance { /* per-instance output keys */ struct ulogd_key *output; /* per-instance config parameters (array) */ - struct config_entry *config_kset; + struct config_keyset *config_kset; /* private data */ char private[0]; }; +struct ulogd_pluginstance_stack { + /* global list of pluginstance stacks */ + struct list_head stack_list; + /* list of plugins in this stack */ + struct list_head list; + char *name; +}; + /* entries of the key hash */ struct ulogd_keyh_entry { struct ulogd_plugin *interp; /* interpreter for this key */ @@ -177,6 +206,8 @@ struct ulogd_keyh_entry { * PUBLIC INTERFACE ***********************************************************************/ +void ulogd_propagate_results(struct ulogd_pluginstance *pi); + /* register a new interpreter plugin */ void ulogd_register_plugin(struct ulogd_plugin *me); @@ -219,6 +250,7 @@ extern struct ulogd_keyh_entry *ulogd_keyh; struct ulogd_fd { struct list_head list; int fd; /* file descriptor */ + unsigned int flags; unsigned int when; int (*cb)(int fd, unsigned int what, void *data); void *data; /* void * to pass to callback */ diff --git a/input/packet/ulogd_inppkt_NFLOG.c b/input/packet/ulogd_inppkt_NFLOG.c index dfdb194..8592ac2 100644 --- a/input/packet/ulogd_inppkt_NFLOG.c +++ b/input/packet/ulogd_inppkt_NFLOG.c @@ -32,7 +32,7 @@ struct nful_input { /* configuration entries */ static struct config_keyset libulog_kset = { - .num_ces = 10, + .num_ces = 3, .ces = { { .key = "bufsize", @@ -52,7 +52,6 @@ static struct config_keyset libulog_kset = { .options = CONFIG_OPT_NONE, .u.value = NFLOG_RMEM_DEFAULT, }, - } }; #define bufsiz_ce(x) (x[0]) diff --git a/output/ulogd_output_LOGEMU.c b/output/ulogd_output_LOGEMU.c index 7cea20d..01d8c60 100644 --- a/output/ulogd_output_LOGEMU.c +++ b/output/ulogd_output_LOGEMU.c @@ -41,16 +41,6 @@ #define ULOGD_LOGEMU_SYNC_DEFAULT 0 #endif -#define NIPQUAD(addr) \ - ((unsigned char *)&addr)[0], \ - ((unsigned char *)&addr)[1], \ - ((unsigned char *)&addr)[2], \ - ((unsigned char *)&addr)[3] - -struct ulogd_key logemu_inp[] = { - -}; - static struct config_keyset logemu_kset = { .num_ces = 2, .ces = { @@ -70,13 +60,12 @@ static struct config_keyset logemu_kset = { }; struct logemu_instance { - struct ulogd_pluginstance upi; FILE *of; }; static int _output_logemu(struct ulogd_pluginstance *upi) { - struct logemu_instance *li = (struct logemu_instance *) upi; + struct logemu_instance *li = (struct logemu_instance *) &upi->private; struct ulogd_key *res = upi->input; static char buf[4096]; @@ -84,7 +73,7 @@ static int _output_logemu(struct ulogd_pluginstance *upi) fprintf(li->of, "%s", buf); - if (upi->configs[1].u.value) + if (upi->config_kset->ces[1].u.value) fflush(li->of); return 0; @@ -92,17 +81,16 @@ static int _output_logemu(struct ulogd_pluginstance *upi) static void signal_handler_logemu(struct ulogd_pluginstance *pi, int signal) { - struct logemu_instance *li = (struct logemu_instance *) pi; + struct logemu_instance *li = (struct logemu_instance *) &pi->private; switch (signal) { case SIGHUP: ulogd_log(ULOGD_NOTICE, "syslogemu: reopening logfile\n"); fclose(li->of); - li->of = fopen(pi->configs[0].u.string, "a"); + li->of = fopen(pi->config_kset->ces[0].u.string, "a"); if (!li->of) { - ulogd_log(ULOGD_FATAL, "can't open syslogemu: %s\n", + ulogd_log(ULOGD_ERROR, "can't reopen syslogemu: %s\n", strerror(errno)); - exit(2); } break; default: @@ -111,38 +99,30 @@ static void signal_handler_logemu(struct ulogd_pluginstance *pi, int signal) } -static struct ulogd_pluginstance *init_logemu(struct ulogd_plugin *pl) +static int start_logemu(struct ulogd_pluginstance *pi) { - struct logemu_instance *li = malloc(sizeof(*li)); - - if (!li) - return NULL; - - memset(li, 0, sizeof(*li)); - li->upi.plugin = pl; - /* FIXME: upi->input = NULL; */ - li->upi.output = NULL; + struct logemu_instance *li = (struct logemu_instance *) &pi->private; #ifdef DEBUG_LOGEMU li->of = stdout; #else - li->of = fopen(li->upi.configs[0].u.string, "a"); + li->of = fopen(pi->config_kset->ces[0].u.string, "a"); if (!li->of) { ulogd_log(ULOGD_FATAL, "can't open syslogemu: %s\n", strerror(errno)); - exit(2); + return errno; } #endif if (printpkt_init()) { ulogd_log(ULOGD_ERROR, "can't resolve all keyhash id's\n"); - exit(1); + return -EINVAL; } - return &li->upi; + return 0; } static int fini_logemu(struct ulogd_pluginstance *pi) { - struct logemu_instance *li = (struct logemu_instance *) pi; + struct logemu_instance *li = (struct logemu_instance *) &pi->private; if (li->of != stdout) fclose(li->of); @@ -150,27 +130,39 @@ static int fini_logemu(struct ulogd_pluginstance *pi) { return 0; } +static int configure_logemu(struct ulogd_pluginstance *pi, + struct ulogd_pluginstance_stack *stack) +{ + /* we should actually parse our logfile section here */ + + return 0; +} + static struct ulogd_plugin logemu_plugin = { .name = "LOGEMU", .input = { - .keys = &logemu_inp, - .num_keys = FIXME, + .keys = printpkt_keys, + .num_keys = ARRAY_SIZE(printpkt_keys), .type = ULOGD_DTYPE_PACKET, }, .output = { .type = ULOGD_DTYPE_SINK, }, - .constructor = &init_logemu, - .destructor = &fini_logemu, - .interp = &_output_logemu, - .signal = &signal_handler_logemu, - .config_kset = &logemu_kset, + .config_kset = &logemu_kset, + .priv_size = sizeof(struct logemu_instance), + + .configure = &configure_logemu, + .start = &start_logemu, + .stop = &fini_logemu, + + .interp = &_output_logemu, + .signal = &signal_handler_logemu, }; void _init(void) { /* FIXME: error handling */ - config_parse_file("LOGEMU", &syslsync_ce); + config_parse_file("LOGEMU", &logemu_kset); - register_output(&logemu_op); + ulogd_register_plugin(&logemu_plugin); } diff --git a/select.c b/select.c index cf459ba..7d7bff9 100644 --- a/select.c +++ b/select.c @@ -21,8 +21,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -static maxfd = 0; -static list_head ulogd_fds; +#include +#include +#include + +static int maxfd = 0; +static LIST_HEAD(ulogd_fds); int ulogd_register_fd(struct ulogd_fd *fd) { @@ -40,42 +44,56 @@ int ulogd_register_fd(struct ulogd_fd *fd) /* Register FD */ if (fd->fd > maxfd) maxfd = fd->fd; - return list_add_tail(&fd->list, &ulogd_fds); + list_add_tail(&fd->list, &ulogd_fds); + + return 0; } -int ulogd_unregister_fd(struct ulogd_fd *fd) +void ulogd_unregister_fd(struct ulogd_fd *fd) { - return list_del(&fd->list); + list_del(&fd->list); } int ulogd_select_main() { struct ulogd_fd *ufd; - fd_set readset, writeset; + fd_set readset, writeset, exceptset; int i; FD_ZERO(&readset); FD_ZERO(&writeset); + FD_ZERO(&exceptset); /* prepare read and write fdsets */ - list_for_each_entry(&ulogd_fds, ufd, list) { - if (ufd->flags & ULOGD_FD_F_READ) + list_for_each_entry(ufd, &ulogd_fds, list) { + if (ufd->when & ULOGD_FD_READ) FD_SET(ufd->fd, &readset); - if (ufd->flags & UlOGD_FD_F_WRITE) + if (ufd->when & ULOGD_FD_WRITE) FD_SET(ufd->fd, &writeset); + + if (ufd->when & ULOGD_FD_EXCEPT) + FD_SET(ufd->fd, &exceptset); } i = select(maxfd, &readset, &writeset, NULL, NULL); if (i > 0) { /* call registered callback functions */ - list_for_each_entry(&ulogd_fds, ufd, list) { + list_for_each_entry(ufd, &ulogd_fds, list) { + int flags = 0; + if (FD_ISSET(ufd->fd, &readset)) - ret = ufd->cb(ufd->fd, UFD_FD_F_READ, - ufd->data); + flags |= ULOGD_FD_READ; + if (FD_ISSET(ufd->fd, &writeset)) - ret = ufd->cb(ufd->fd, UFD_FD_F_WRITE, - ufd->data); + flags |= ULOGD_FD_WRITE; + + if (FD_ISSET(ufd->fd, &exceptset)) + flags |= ULOGD_FD_EXCEPT; + + if (flags) + ufd->cb(ufd->fd, flags, ufd->data); } } + return i; } diff --git a/select.h b/select.h new file mode 100644 index 0000000..bcfb66d --- /dev/null +++ b/select.h @@ -0,0 +1,2 @@ + +extern int ulogd_select_main(); diff --git a/ulogd.c b/ulogd.c index 5252925..af6a8f7 100644 --- a/ulogd.c +++ b/ulogd.c @@ -63,6 +63,7 @@ #include #include #include +#include "select.h" #ifdef DEBUG #define DEBUGP(format, args...) fprintf(stderr, format, ## args) #else @@ -79,6 +80,9 @@ #define ULOGD_CONFIGFILE "/etc/ulogd.conf" #endif +#define COPYRIGHT \ + "Copyright (C) 2000-2005 Harald Welte \n" + /* global variables */ static FILE *logfile = NULL; /* logfile pointer */ static int loglevel = 1; /* current loglevel */ @@ -88,10 +92,10 @@ static char *ulogd_configfile = ULOGD_CONFIGFILE; //static struct ulog_interpreter *ulogd_interpreters; /* linked list for all registered plugins */ -static struct ulogd_plugin *ulogd_plugins; +static LIST_HEAD(ulogd_plugins); static LIST_HEAD(ulogd_pi_stacks); -static LIST_HEAD(ulogd_fds); +#if 0 /*********************************************************************** * INTERPRETER AND KEY HASH FUNCTIONS (new in 0.9) ***********************************************************************/ @@ -103,7 +107,7 @@ static LIST_HEAD(ulogd_fds); * INTERH_ALLOC_GRAN and KEYH_ALLOC_GRAN */ -/* allocation granularith */ +/* allocation granularity */ #define INTERH_ALLOC_GRAN 5 /* hashtable for all registered interpreters */ @@ -327,6 +331,7 @@ void register_interpreter(struct ulogd_interpreter *me) me->next = ulogd_interpreters; ulogd_interpreters = me; } +#endif /*********************************************************************** * PLUGIN MANAGEMENT @@ -335,11 +340,11 @@ void register_interpreter(struct ulogd_interpreter *me) /* try to lookup a registered plugin for a given name */ static struct ulogd_plugin *find_plugin(const char *name) { - struct ulogd_plugin *ptr; + struct ulogd_plugin *pl; - for (ptr = ulogd_outputs; ptr; ptr = ptr->next) { - if (strcmp(name, ptr->name) == 0) - return ptr; + list_for_each_entry(pl, &ulogd_plugins, list) { + if (strcmp(name, pl->name) == 0) + return pl; } return NULL; @@ -354,8 +359,7 @@ void register_plugin(struct ulogd_plugin *me) exit(EXIT_FAILURE); } ulogd_log(ULOGD_NOTICE, "registering plugin `%s'\n", me->name); - me->next = ulogd_plugins; - ulogd_plugins = me; + list_add(&me->list, &ulogd_plugins); } /*********************************************************************** @@ -393,16 +397,36 @@ void __ulogd_log(int level, char *file, int line, const char *format, ...) fflush(outfd); } -/* propagate results to all registered output plugins */ -static void propagate_results(struct ulogd_iret *ret) +/* propagate results to all downstream plugins in the stack */ +void ulogd_propagate_results(struct ulogd_pluginstance *pi) { - struct ulogd_plugin *p; - - for (p = ulogd_outputs; p; p = p->next) { - (*p->output)(ret); + 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) { @@ -417,35 +441,54 @@ static void clean_results(struct ulogd_iret *ret) r->flags &= ~ULOGD_RETF_VALID; } } - - +#endif static struct ulogd_pluginstance * pluginstance_alloc_init(struct ulogd_plugin *pl, char *pi_id, - struct ulogd_pluginstance *stack) + struct ulogd_pluginstance_stack *stack) { - unsigned int ce_size; - struct ulogd_pluginstance *pi = malloc(sizeof(struct ulogd_pluginstance)+len); + 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, sizeof(struct ulogd_pluginstance)+len); + 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.num_ces = pl->config_kset->num_ces; - ce_size = pl->config_kset->num_ces*sizeof(struct config_entry); - pi->config_kset.ces = malloc(ce_size); - if (!pi->config_kset.ces) { - free(pi); - return NULL; - } - memcpy(pi->config_kset.ces, pl->config_kset->ces, ce_size); + 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)); - /* FIXME: allocate input and output keys ?*/ + /* 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; } @@ -462,20 +505,142 @@ static int load_plugin(char *file) 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 = NULL; + struct ulogd_pluginstance_stack *stack; char *buf = strdup(option); char *tok; + int ret; if (!buf) { - ulogd_log(ULOGD_EROR, ""); + 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]; @@ -487,88 +652,62 @@ static int create_stack(char *option) 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", ); - return 1; + "%s\n", plname); + free(stack); + return -ENODEV; } /* allocate */ - pi = ulogd_pluginstance_alloc_init(pl, pi_id, stack); + pi = pluginstance_alloc_init(pl, pi_id, stack); if (!pi) { ulogd_log(ULOGD_ERROR, "unable to allocate pluginstance for %s\n", pi_id); - return 1; + 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); - if (!stack) - stack = pi; - else - list_add(&pi->list, &stack->list); + list_add(&pi->list, &stack->list); } - ulogd_log(ULOGD_DEBUG, "connecting input/output keys of stack:\n"); - list_for_each_entry() { - + 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; } - -int ulogd_register_fd(struct ulogd_fd *ufd) -{ - list_add(&ufd->list, &ulogd_fds); -} - -void ulogd_unregister_fd(struct ulogd_fd *ufd) -{ - list_del(&ufd->list); -} + static int ulogd_main_loop(void) { - fd_set read_fd, write_fd, except_fd; - unsigned int hifd; - struct ulogd_fd *ufd; int ret = 0; while (1) { - FD_ZERO(&read_fd); - FD_ZERO(&write_fd); - FD_ZERO(&except_fd); - hifd = 0; - list_for_each_entry(ufd, &ulogd_fds, list) { - if (ufd->when & ULOGD_FD_READ) - FD_SET(ufd->fd, &read_fd); - if (ufd->when & ULOGD_FD_WRITE) - FD_SET(ufd->fd, &write_fd); - if (ufd->when & ULOGD_FD_EXCEPT) - FD_SET(ufd->fd, &except_fd); - - if (ufd->fd > hifd) - hifd = ufd; - } - - ret = select(hifd+1, &read_fd, &write_fd, &except_fd, NULL); + ret = ulogd_select_main(); if (ret == 0) continue; if (ret < 0) { - if (errno = -EINTR) + if (errno == -EINTR) continue; else { ulogd_log(ULOGD_ERROR, "select returned %s\n", @@ -576,19 +715,6 @@ static int ulogd_main_loop(void) break; } } - - list_for_each_entry(ufd, &ulogd_fds, list) { - unsigned int what = 0; - if (FD_ISSET(ufd->fd, &read_fd)) - what |= ULOGD_FD_READ; - if (FD_ISSET(ufd->fd, &write_fd)) - what |= ULOGD_FD_WRITE; - if (FD_ISSET(ufd->fd, &except_fd)) - what |= ULOGD_FD_EXCEPT; - - if (what & ufd->when) - ufd->cb(ufd->fd, what, ufd->data); - } } return ret; @@ -651,51 +777,50 @@ static int parse_conffile(const char *section, struct config_keyset *ce) } -/* configuration directives of the main program */ -static struct config_entry ulogd_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, - }, -}; static struct config_keyset ulogd_kset = { - .ces = &ulogd_ces, - .num_ces = sizeof(ulogd_ces)/sizeof(struct config_entry), + .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_ces[0] -#define plugin_ce ulogd_ces[1] -#define loglevel_ce ulogd_ces[2] -#define stack_ce ulogd_ces[3] +#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, *pi; + struct ulogd_pluginstance_stack *stack; + struct ulogd_pluginstance *pi; - list_for_each_entry(stack, &ulogd_pi_stack, stack_list) { - list_for_each_entry(pi, stack, list) { + 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); } @@ -724,7 +849,7 @@ static void signal_handler(int signal) /* reopen logfile */ if (logfile != stdout) { fclose(logfile); - logfile = fopen(logf_ce.u.string, "a"); + logfile = fopen(logfile_ce.u.string, "a"); if (!logfile) sigterm_handler(signal); } @@ -734,8 +859,7 @@ static void print_usage(void) { /* FIXME */ printf("ulogd Version %s\n", ULOGD_VERSION); - printf("Copyright (C) 2000-2005 Harald Welte " - "\n"); + printf(COPYRIGHT); printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); printf("Parameters:\n"); printf("\t-h --help\tThis help page\n"); @@ -756,7 +880,6 @@ static struct option opts[] = { int main(int argc, char* argv[]) { - int len; int argch; int daemonize = 0; int change_uid = 0; @@ -764,8 +887,6 @@ int main(int argc, char* argv[]) struct passwd *pw; uid_t uid = 0; gid_t gid = 0; - ulog_packet_msg_t *upkt; - ulog_output_t *p; while ((argch = getopt_long(argc, argv, "c:dh::Vu:", opts, NULL)) != -1) { @@ -773,9 +894,11 @@ int main(int argc, char* argv[]) default: case '?': if (isprint(optopt)) - fprintf(stderr, "Unknown option `-%c'.\n", optopt); + fprintf(stderr, "Unknown option `-%c'.\n", + optopt); else - fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); + fprintf(stderr, "Unknown option character " + "`\\x%x'.\n", optopt); print_usage(); exit(1); @@ -789,8 +912,7 @@ int main(int argc, char* argv[]) break; case 'V': printf("ulogd Version %s\n", ULOGD_VERSION); - printf("Copyright (C) 2000-2005 Harald Welte " - "\n"); + printf(COPYRIGHT); exit(0); break; case 'c': @@ -854,14 +976,7 @@ int main(int argc, char* argv[]) } } - logfile_open(logf_ce.u.string); - -#if 0 - for (p = ulogd_outputs; p; p = p->next) { - if (p->init) - (*p->init)(); - } -#endif + logfile_open(logfile_ce.u.string); #ifdef DEBUG /* dump key and interpreter hash */ diff --git a/util/printpkt.c b/util/printpkt.c index a8c09a2..cb4db7d 100644 --- a/util/printpkt.c +++ b/util/printpkt.c @@ -54,46 +54,52 @@ struct intr_id { static char hostname[HOST_NAME_MAX+1]; #define INTR_IDS 35 -static struct intr_id intr_ids[INTR_IDS] = { - { "oob.time.sec", 0 }, - { "oob.prefix", 0 }, - { "oob.in", 0 }, - { "oob.out", 0 }, - { "raw.mac", 0 }, - { "ip.saddr", 0 }, - { "ip.daddr", 0 }, - { "ip.totlen", 0 }, - { "ip.tos", 0 }, - { "ip.ttl", 0 }, - { "ip.id", 0 }, - { "ip.fragoff", 0 }, - { "ip.protocol", 0 }, - { "tcp.sport", 0 }, - { "tcp.dport", 0 }, - { "tcp.seq", 0 }, - { "tcp.ackseq", 0 }, - { "tcp.window", 0 }, - { "tcp.urg", 0 }, - { "tcp.ack", 0 }, - { "tcp.psh", 0 }, - { "tcp.rst", 0 }, - { "tcp.syn", 0 }, - { "tcp.fin", 0 }, - { "tcp.urgp", 0 }, - { "udp.sport", 0 }, - { "udp.dport", 0 }, - { "udp.len", 0 }, - { "icmp.type", 0 }, - { "icmp.code", 0 }, - { "icmp.echoid", 0 }, - { "icmp.echoseq", 0 }, - { "icmp.gateway", 0 }, - { "icmp.fragmtu", 0 }, - { "ahesp.spi", 0 }, +static struct ulogd_key printpkt_keys[INTR_IDS] = { + { .name = "oob.time.sec", }, + { .name = "oob.prefix", }, + { .name = "oob.in", }, + { .name = "oob.out", }, + { .name = "raw.mac", }, + { .name = "ip.saddr", }, + { .name = "ip.daddr", }, + { .name = "ip.totlen", }, + { .name = "ip.tos", }, + { .name = "ip.ttl", }, + { .name = "ip.id", }, + { .name = "ip.fragoff", }, + { .name = "ip.protocol", }, + { .name = "tcp.sport", }, + { .name = "tcp.dport", }, + { .name = "tcp.seq", }, + { .name = "tcp.ackseq", }, + { .name = "tcp.window", }, + { .name = "tcp.urg", }, + { .name = "tcp.ack", }, + { .name = "tcp.psh", }, + { .name = "tcp.rst", }, + { .name = "tcp.syn", }, + { .name = "tcp.fin", }, + { .name = "tcp.urgp", }, + { .name = "udp.sport", }, + { .name = "udp.dport", }, + { .name = "udp.len", }, + { .name = "icmp.type", }, + { .name = "icmp.code", }, + { .name = "icmp.echoid", }, + { .name = "icmp.echoseq", }, + { .name = "icmp.gateway", }, + { .name = "icmp.fragmtu", }, + { .name = "ahesp.spi", }, }; +#define GET_VALUE(res, x) (res[x].u.source->u.value) +#define GET_FLAGS(res, x) (res[x].u.source->flags) +#define pp_is_valid(res, x) (GET_FLAGS(res, x) & ULOGD_RETF_VALID) + +#if 0 #define GET_VALUE(x) ulogd_keyh[intr_ids[x].id].interp->result[ulogd_keyh[intr_ids[x].id].offset].value #define GET_FLAGS(x) ulogd_keyh[intr_ids[x].id].interp->result[ulogd_keyh[intr_ids[x].id].offset].flags +#endif int printpkt_print(struct ulogd_key *res, char *buf, int prefix) { @@ -104,7 +110,11 @@ int printpkt_print(struct ulogd_key *res, char *buf, int prefix) char *buf_cur = buf; if (prefix) { - now = (time_t) GET_VALUE(0).ui32; + if (pp_is_valid(res, 0)) + now = (time_t) GET_VALUE(res, 0).ui32; + else + now = (time_t) 0; + timestr = ctime(&now) + 4; /* truncate time */ @@ -119,73 +129,82 @@ int printpkt_print(struct ulogd_key *res, char *buf, int prefix) buf_cur += sprintf(buf_cur, "%.15s %s", timestr, hostname); } - if (*(char *) GET_VALUE(1).ptr) - buf_cur += sprintf(buf_cur, " %s", (char *) GET_VALUE(1).ptr); + if (pp_is_valid(res, 1)) + buf_cur += sprintf(buf_cur, " %s", (char *) GET_VALUE(res, 1).ptr); - buf_cur += sprintf(buf_cur," IN=%s OUT=%s ", - (char *) GET_VALUE(2).ptr, - (char *) GET_VALUE(3).ptr); + if (pp_is_valid(res, 2) && pp_is_valid(res, 3)) { + buf_cur += sprintf(buf_cur," IN=%s OUT=%s ", + (char *) GET_VALUE(res, 2).ptr, + (char *) GET_VALUE(res, 3).ptr); + } /* FIXME: configurable */ - buf_cur += sprintf(buf_cur, "MAC=%s ", - (GET_FLAGS(4) & ULOGD_RETF_VALID) ? (char *) GET_VALUE(4).ptr : ""); - - buf_cur += sprintf(buf_cur, "SRC=%s ", - inet_ntoa((struct in_addr) {htonl(GET_VALUE(5).ui32)})); - buf_cur += sprintf(buf_cur, "DST=%s ", - inet_ntoa((struct in_addr) {htonl(GET_VALUE(6).ui32)})); - + if (pp_is_valid(res, 4)) + buf_cur += sprintf(buf_cur, "MAC=%s ", + (char *) GET_VALUE(res, 4).ptr); + else + buf_cur += sprintf(buf_cur, "MAC= "); + + if (pp_is_valid(res, 5)) + buf_cur += sprintf(buf_cur, "SRC=%s ", inet_ntoa( + (struct in_addr) {htonl(GET_VALUE(res, 5).ui32)})); + + if (pp_is_valid(res, 6)) + buf_cur += sprintf(buf_cur, "DST=%s ", inet_ntoa( + (struct in_addr) {htonl(GET_VALUE(res, 6).ui32)})); + + /* FIXME: add pp_is_valid calls to remainder of file */ buf_cur += sprintf(buf_cur,"LEN=%u TOS=%02X PREC=0x%02X TTL=%u ID=%u ", - GET_VALUE(7).ui16, GET_VALUE(8).ui8 & IPTOS_TOS_MASK, - GET_VALUE(8).ui8 & IPTOS_PREC_MASK, GET_VALUE(9).ui8, - GET_VALUE(10).ui16); + GET_VALUE(res, 7).ui16, GET_VALUE(res, 8).ui8 & IPTOS_TOS_MASK, + GET_VALUE(res, 8).ui8 & IPTOS_PREC_MASK, GET_VALUE(res, 9).ui8, + GET_VALUE(res, 10).ui16); - if (GET_VALUE(10).ui16 & IP_RF) + if (GET_VALUE(res, 10).ui16 & IP_RF) buf_cur += sprintf(buf_cur, "CE "); - if (GET_VALUE(11).ui16 & IP_DF) + if (GET_VALUE(res, 11).ui16 & IP_DF) buf_cur += sprintf(buf_cur, "DF "); - if (GET_VALUE(11).ui16 & IP_MF) + if (GET_VALUE(res, 11).ui16 & IP_MF) buf_cur += sprintf(buf_cur, "MF "); - if (GET_VALUE(11).ui16 & IP_OFFMASK) + if (GET_VALUE(res, 11).ui16 & IP_OFFMASK) buf_cur += sprintf(buf_cur, "FRAG:%u ", - GET_VALUE(11).ui16 & IP_OFFMASK); + GET_VALUE(res, 11).ui16 & IP_OFFMASK); - switch (GET_VALUE(12).ui8) { + switch (GET_VALUE(res, 12).ui8) { case IPPROTO_TCP: buf_cur += sprintf(buf_cur, "PROTO=TCP "); buf_cur += sprintf(buf_cur, "SPT=%u DPT=%u ", - GET_VALUE(13).ui16, GET_VALUE(14).ui16); + GET_VALUE(res, 13).ui16, GET_VALUE(res, 14).ui16); /* FIXME: config */ buf_cur += sprintf(buf_cur, "SEQ=%u ACK=%u ", - GET_VALUE(15).ui32, GET_VALUE(16).ui32); + GET_VALUE(res, 15).ui32, GET_VALUE(res, 16).ui32); - buf_cur += sprintf(buf_cur, "WINDOW=%u ", GET_VALUE(17).ui16); + buf_cur += sprintf(buf_cur, "WINDOW=%u ", GET_VALUE(res, 17).ui16); // buf_cur += sprintf(buf_cur, "RES=0x%02x ", - if (GET_VALUE(18).b) + if (GET_VALUE(res, 18).b) buf_cur += sprintf(buf_cur, "URG "); - if (GET_VALUE(19).b) + if (GET_VALUE(res, 19).b) buf_cur += sprintf(buf_cur, "ACK "); - if (GET_VALUE(20).b) + if (GET_VALUE(res, 20).b) buf_cur += sprintf(buf_cur, "PSH "); - if (GET_VALUE(21).b) + if (GET_VALUE(res, 21).b) buf_cur += sprintf(buf_cur, "RST "); - if (GET_VALUE(22).b) + if (GET_VALUE(res, 22).b) buf_cur += sprintf(buf_cur, "SYN "); - if (GET_VALUE(23).b) + if (GET_VALUE(res, 23).b) buf_cur += sprintf(buf_cur, "FIN "); - buf_cur += sprintf(buf_cur, "URGP=%u ", GET_VALUE(24).ui16); + buf_cur += sprintf(buf_cur, "URGP=%u ", GET_VALUE(res, 24).ui16); break; case IPPROTO_UDP: @@ -193,48 +212,48 @@ int printpkt_print(struct ulogd_key *res, char *buf, int prefix) buf_cur += sprintf(buf_cur, "PROTO=UDP "); buf_cur += sprintf(buf_cur, "SPT=%u DPT=%u LEN=%u ", - GET_VALUE(25).ui16, GET_VALUE(26).ui16, - GET_VALUE(27).ui16); + GET_VALUE(res, 25).ui16, GET_VALUE(res, 26).ui16, + GET_VALUE(res, 27).ui16); break; case IPPROTO_ICMP: buf_cur += sprintf(buf_cur, "PROTO=ICMP "); buf_cur += sprintf(buf_cur, "TYPE=%u CODE=%u ", - GET_VALUE(28).ui8, GET_VALUE(29).ui8); + GET_VALUE(res, 28).ui8, GET_VALUE(res, 29).ui8); - switch (GET_VALUE(28).ui8) { + switch (GET_VALUE(res, 28).ui8) { case ICMP_ECHO: case ICMP_ECHOREPLY: buf_cur += sprintf(buf_cur, "ID=%u SEQ=%u ", - GET_VALUE(30).ui16, - GET_VALUE(31).ui16); + GET_VALUE(res, 30).ui16, + GET_VALUE(res, 31).ui16); break; case ICMP_PARAMETERPROB: buf_cur += sprintf(buf_cur, "PARAMETER=%u ", - GET_VALUE(32).ui32 >> 24); + GET_VALUE(res, 32).ui32 >> 24); break; case ICMP_REDIRECT: - buf_cur += sprintf(buf_cur, "GATEWAY=%s ", inet_ntoa((struct in_addr) {htonl(GET_VALUE(32).ui32)})); + buf_cur += sprintf(buf_cur, "GATEWAY=%s ", inet_ntoa((struct in_addr) {htonl(GET_VALUE(res, 32).ui32)})); break; case ICMP_DEST_UNREACH: - if (GET_VALUE(29).ui8 == ICMP_FRAG_NEEDED) + if (GET_VALUE(res, 29).ui8 == ICMP_FRAG_NEEDED) buf_cur += sprintf(buf_cur, "MTU=%u ", - GET_VALUE(33).ui16); + GET_VALUE(res, 33).ui16); break; } break; case IPPROTO_ESP: case IPPROTO_AH: - buf_cur += sprintf(buf_cur, "PROTO=%s ", GET_VALUE(12).ui8 == IPPROTO_ESP ? "ESP" : "AH"); + buf_cur += sprintf(buf_cur, "PROTO=%s ", GET_VALUE(res, 12).ui8 == IPPROTO_ESP ? "ESP" : "AH"); /* FIXME: "INCOMPLETE [%u bytes]" in case of short pkt */ - if (intr_ids[34].id > 0) { - buf_cur += sprintf(buf_cur, "SPI=0x%x ", GET_VALUE(34).ui32); + if (pp_is_valid(res, 34)) { + buf_cur += sprintf(buf_cur, "SPI=0x%x ", GET_VALUE(res, 34).ui32); } break; default: - buf_cur += sprintf(buf_cur, "PROTO=%u ", GET_VALUE(11).ui8); + buf_cur += sprintf(buf_cur, "PROTO=%u ", GET_VALUE(res, 11).ui8); } strcat(buf_cur, "\n"); @@ -244,6 +263,7 @@ int printpkt_print(struct ulogd_key *res, char *buf, int prefix) /* get all key id's for the keys we are intrested in */ static int get_ids(void) { +#if 0 int i; struct intr_id *cur_id; @@ -257,6 +277,7 @@ static int get_ids(void) return 1; } } +#endif return 0; } -- cgit v1.2.3