From 0e75d6dba81445f611b03b0157322c003fcdb8e2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 17 Jan 2010 22:34:06 +0100 Subject: output: add new plugin XML to output logs in XML This patch adds XML that allows to log information in XML for ulogd2. It supports packet and flow-based accounting. Signed-off-by: Pablo Neira Ayuso --- output/ulogd_output_XML.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 output/ulogd_output_XML.c (limited to 'output/ulogd_output_XML.c') diff --git a/output/ulogd_output_XML.c b/output/ulogd_output_XML.c new file mode 100644 index 0000000..fcc130d --- /dev/null +++ b/output/ulogd_output_XML.c @@ -0,0 +1,241 @@ +/* ulogd_XML.c. + * + * ulogd output target for XML logging. + * + * (C) 2010 by Pablo Neira Ayuso + * + * 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 + */ + +#include +#include +#include +#include +#include +#include + +#ifndef ULOGD_XML_DEFAULT_DIR +#define ULOGD_XML_DEFAULT_DIR "/var/log/" +#endif + +enum { + KEY_CT, + KEY_PCKT, +}; + +static struct ulogd_key xml_inp[] = { + [KEY_CT] = { + .type = ULOGD_RET_RAW, + .flags = ULOGD_RETF_NONE | ULOGD_KEYF_OPTIONAL, + .name = "ct", + }, + [KEY_PCKT] = { + .type = ULOGD_RET_RAW, + .flags = ULOGD_RETF_NONE | ULOGD_KEYF_OPTIONAL, + .name = "raw", + }, +}; + +enum { + CFG_XML_DIR, + CFG_XML_SYNC, + CFG_XML_STDOUT, +}; + +static struct config_keyset xml_kset = { + .num_ces = 3, + .ces = { + [CFG_XML_DIR] = { + .key = "directory", + .type = CONFIG_TYPE_STRING, + .options = CONFIG_OPT_NONE, + .u = { .string = ULOGD_XML_DEFAULT_DIR }, + }, + [CFG_XML_SYNC] = { + .key = "sync", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u = { .value = 0 }, + }, + [CFG_XML_STDOUT] = { + .key = "stdout", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u = { .value = 0 }, + }, + }, +}; + +struct xml_priv { + FILE *of; +}; + +static int +xml_output_flow(struct ulogd_key *inp, char *buf, ssize_t size) +{ + struct nf_conntrack *ct = ikey_get_ptr(&inp[KEY_CT]); + int tmp; + + tmp = nfct_snprintf(buf, size, ct, 0, NFCT_O_XML, + NFCT_OF_SHOW_LAYER3 | NFCT_OF_ID | NFCT_OF_TIME); + if (tmp < 0 || tmp >= size) + return -1; + + return 0; +} + +static int +xml_output_packet(struct ulogd_key *inp, char *buf, ssize_t size) +{ + struct nflog_data *ldata = ikey_get_ptr(&inp[KEY_PCKT]); + int tmp; + + tmp = nflog_snprintf_xml(buf, size, ldata, NFLOG_XML_ALL); + if (tmp < 0 || tmp >= size) + return -1; + + return 0; +} + +static int xml_output(struct ulogd_pluginstance *upi) +{ + struct ulogd_key *inp = upi->input.keys; + struct xml_priv *opi = (struct xml_priv *) &upi->private; + static char buf[4096]; + int ret = -1; + + if (pp_is_valid(inp, KEY_CT)) + ret = xml_output_flow(inp, buf, sizeof(buf)); + else if (pp_is_valid(inp, KEY_PCKT)) + ret = xml_output_packet(inp, buf, sizeof(buf)); + + if (ret < 0) + return ULOGD_IRET_ERR; + + fprintf(opi->of, "%s\n", buf); + if (upi->config_kset->ces[CFG_XML_SYNC].u.value != 0) + fflush(opi->of); + + return ULOGD_IRET_OK; +} + +static int xml_configure(struct ulogd_pluginstance *upi, + struct ulogd_pluginstance_stack *stack) +{ + int ret; + + ret = config_parse_file(upi->id, upi->config_kset); + if (ret < 0) + return ret; + + return 0; +} + +static int xml_fini(struct ulogd_pluginstance *pi) +{ + struct xml_priv *op = (struct xml_priv *) &pi->private; + /* XXX: provide generic function to get the input plugin. */ + struct ulogd_pluginstance *input_plugin = + llist_entry(pi->stack->list.next, + struct ulogd_pluginstance, list); + + /* the initial tag depends on the source. */ + if (input_plugin->plugin->output.type & ULOGD_DTYPE_FLOW) + fprintf(op->of, "\n"); + else if (input_plugin->plugin->output.type & ULOGD_DTYPE_RAW) + fprintf(op->of, "\n"); + + if (op->of != stdout) + fclose(op->of); + + return 0; +} + +static int xml_start(struct ulogd_pluginstance *upi) +{ + struct xml_priv *op = (struct xml_priv *) &upi->private; + char buf[PATH_MAX], filename[FILENAME_MAX]; + time_t now; + struct tm *tm; + int ret; + + if (upi->config_kset->ces[CFG_XML_STDOUT].u.value != 0) { + op->of = stdout; + } else { + now = time(NULL); + tm = localtime(&now); + ret = snprintf(filename, sizeof(filename), + "ulogd-%.2d%.2d%.4d-%.2d%.2d%.2d.xml", + tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + if (ret == -1 || ret >= (int)sizeof(filename)) + return -1; + + ret = snprintf(buf, sizeof(buf), "%s/%s", + upi->config_kset->ces[CFG_XML_DIR].u.string, + filename); + if (ret == -1 || ret >= (int)sizeof(buf)) + return -1; + + op->of = fopen(buf, "a"); + if (!op->of) { + ulogd_log(ULOGD_FATAL, "can't open XML file: %s\n", + strerror(errno)); + return -1; + } + } + fprintf(op->of, "\n"); + + struct ulogd_pluginstance *input_plugin = + llist_entry(upi->stack->list.next, + struct ulogd_pluginstance, list); + + if (input_plugin->plugin->output.type & ULOGD_DTYPE_FLOW) + fprintf(op->of, "\n"); + else if (input_plugin->plugin->output.type & ULOGD_DTYPE_RAW) + fprintf(op->of, "\n"); + + if (upi->config_kset->ces[CFG_XML_SYNC].u.value != 0) + fflush(op->of); + + return 0; +} + +static struct ulogd_plugin xml_plugin = { + .name = "XML", + .input = { + .keys = xml_inp, + .num_keys = ARRAY_SIZE(xml_inp), + .type = ULOGD_DTYPE_FLOW, + }, + .output = { + .type = ULOGD_DTYPE_SINK, + }, + .config_kset = &xml_kset, + .priv_size = sizeof(struct xml_priv), + + .configure = &xml_configure, + .start = &xml_start, + .stop = &xml_fini, + .interp = &xml_output, + .version = ULOGD_VERSION, +}; + +void __attribute__ ((constructor)) init(void); + +void init(void) +{ + ulogd_register_plugin(&xml_plugin); +} -- cgit v1.2.3