From 325b7d44124f57674dcaa4088e67238996a5a03b Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Tue, 23 May 2006 09:00:01 +0000 Subject: Add a printflow plugin is similar to the PRINTPKT plugin, but for flows. It's output is compatible with the SYSLOG and LOGEMU plugins. (Philip Craig) --- filter/Makefile.am | 5 +- filter/ulogd_filter_PRINTFLOW.c | 66 ++++++++++++++++++ include/ulogd/Makefile.am | 2 +- include/ulogd/printflow.h | 9 +++ input/flow/ulogd_inpflow_NFCT.c | 8 +++ output/ulogd_output_LOGEMU.c | 5 +- output/ulogd_output_SYSLOG.c | 2 +- ulogd.conf.in | 4 ++ util/printflow.c | 150 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 246 insertions(+), 5 deletions(-) create mode 100644 filter/ulogd_filter_PRINTFLOW.c create mode 100644 include/ulogd/printflow.h create mode 100644 util/printflow.c diff --git a/filter/Makefile.am b/filter/Makefile.am index 8c2a37d..b3207f9 100644 --- a/filter/Makefile.am +++ b/filter/Makefile.am @@ -5,7 +5,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include noinst_HEADERS = rtnl.h iftable.h pkglib_LTLIBRARIES = ulogd_filter_IFINDEX.la ulogd_filter_PWSNIFF.la \ - ulogd_filter_PRINTPKT.la + ulogd_filter_PRINTPKT.la ulogd_filter_PRINTFLOW.la ulogd_filter_IFINDEX_la_SOURCES = ulogd_filter_IFINDEX.c rtnl.c iftable.c ulogd_filter_IFINDEX_la_LDFLAGS = -module @@ -15,3 +15,6 @@ ulogd_filter_PWSNIFF_la_LDFLAGS = -module ulogd_filter_PRINTPKT_la_SOURCES = ulogd_filter_PRINTPKT.c ../util/printpkt.c ulogd_filter_PRINTPKT_la_LDFLAGS = -module + +ulogd_filter_PRINTFLOW_la_SOURCES = ulogd_filter_PRINTFLOW.c ../util/printflow.c +ulogd_filter_PRINTFLOW_la_LDFLAGS = -module diff --git a/filter/ulogd_filter_PRINTFLOW.c b/filter/ulogd_filter_PRINTFLOW.c new file mode 100644 index 0000000..181c09e --- /dev/null +++ b/filter/ulogd_filter_PRINTFLOW.c @@ -0,0 +1,66 @@ +/* ulogd_filter_PRINTFLOW.c, Version $Revision: 1.1 $ + * + * This target produces entries similar to the LOG target, but for flows. + * + * (C) 2006 by Philip Craig + * + * 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 + +static struct ulogd_key printflow_outp[] = { + { + .type = ULOGD_RET_STRING, + .flags = ULOGD_RETF_NONE, + .name = "print", + }, +}; + +static int printflow_interp(struct ulogd_pluginstance *upi) +{ + struct ulogd_key *inp = upi->input.keys; + struct ulogd_key *ret = upi->output.keys; + static char buf[4096]; + + printflow_print(inp, buf); + ret[0].u.value.ptr = buf; + ret[0].flags |= ULOGD_RETF_VALID; + return 0; +} + +static struct ulogd_plugin printflow_plugin = { + .name = "PRINTFLOW", + .input = { + .keys = printflow_keys, + .num_keys = ARRAY_SIZE(printflow_keys), + .type = ULOGD_DTYPE_FLOW, + }, + .output = { + .keys = printflow_outp, + .num_keys = ARRAY_SIZE(printflow_outp), + .type = ULOGD_DTYPE_FLOW, + }, + .interp = &printflow_interp, + .version = ULOGD_VERSION, +}; + +void __attribute__ ((constructor)) init(void); + +void init(void) +{ + ulogd_register_plugin(&printflow_plugin); +} diff --git a/include/ulogd/Makefile.am b/include/ulogd/Makefile.am index 0933390..2a3a03d 100644 --- a/include/ulogd/Makefile.am +++ b/include/ulogd/Makefile.am @@ -1,2 +1,2 @@ -noinst_HEADERS = conffile.h db.h ipfix_protocol.h linuxlist.h ulogd.h printpkt.h +noinst_HEADERS = conffile.h db.h ipfix_protocol.h linuxlist.h ulogd.h printpkt.h printflow.h diff --git a/include/ulogd/printflow.h b/include/ulogd/printflow.h new file mode 100644 index 0000000..7343a23 --- /dev/null +++ b/include/ulogd/printflow.h @@ -0,0 +1,9 @@ +#ifndef _PRINTFLOW_H +#define _PRINTFLOW_H + +#define FLOW_IDS 10 +extern struct ulogd_key printflow_keys[FLOW_IDS]; + +int printflow_print(struct ulogd_key *res, char *buf); + +#endif diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c index c97c7bc..34b49be 100644 --- a/input/flow/ulogd_inpflow_NFCT.c +++ b/input/flow/ulogd_inpflow_NFCT.c @@ -244,6 +244,11 @@ static struct ulogd_key nfct_okeys[] = { .field_id = IPFIX_flowEndSeconds, }, }, + { + .type = ULOGD_RET_BOOL, + .flags = ULOGD_RETF_NONE, + .name = "dir", + }, }; static struct ct_htable *htable_alloc(int htable_size, int prealloc) @@ -424,6 +429,9 @@ static int propagate_ct_flow(struct ulogd_pluginstance *upi, ret[14].flags |= ULOGD_RETF_VALID; } + ret[15].u.value.b = (dir == NFCT_DIR_ORIGINAL) ? 0 : 1; + ret[15].flags |= ULOGD_RETF_VALID; + ulogd_propagate_results(upi); return 0; diff --git a/output/ulogd_output_LOGEMU.c b/output/ulogd_output_LOGEMU.c index a224d7b..c18aad7 100644 --- a/output/ulogd_output_LOGEMU.c +++ b/output/ulogd_output_LOGEMU.c @@ -55,6 +55,7 @@ static struct ulogd_key logemu_inp[] = { }, { .type = ULOGD_RET_UINT32, + .flags = ULOGD_KEYF_OPTIONAL, .name = "oob.time.sec", }, }; @@ -91,7 +92,7 @@ static int _output_logemu(struct ulogd_pluginstance *upi) char *tmp; time_t now; - if (res[1].u.source->flags & ULOGD_RETF_VALID) + if (res[1].u.source && (res[1].u.source->flags & ULOGD_RETF_VALID)) now = (time_t) res[1].u.source->u.value.ui32; else now = time(NULL); @@ -187,7 +188,7 @@ static struct ulogd_plugin logemu_plugin = { .input = { .keys = logemu_inp, .num_keys = ARRAY_SIZE(logemu_inp), - .type = ULOGD_DTYPE_PACKET, + .type = ULOGD_DTYPE_PACKET | ULOGD_DTYPE_FLOW, }, .output = { .type = ULOGD_DTYPE_SINK, diff --git a/output/ulogd_output_SYSLOG.c b/output/ulogd_output_SYSLOG.c index 8b89295..2959a29 100644 --- a/output/ulogd_output_SYSLOG.c +++ b/output/ulogd_output_SYSLOG.c @@ -163,7 +163,7 @@ static struct ulogd_plugin syslog_plugin = { .input = { .keys = syslog_inp, .num_keys = ARRAY_SIZE(syslog_inp), - .type = ULOGD_DTYPE_PACKET, + .type = ULOGD_DTYPE_PACKET | ULOGD_DTYPE_FLOW, }, .output = { .type = ULOGD_DTYPE_SINK, diff --git a/ulogd.conf.in b/ulogd.conf.in index 6bd61e4..0a3e791 100644 --- a/ulogd.conf.in +++ b/ulogd.conf.in @@ -36,6 +36,7 @@ plugin="@libdir@/ulogd/ulogd_inppkt_NFLOG.so" plugin="@libdir@/ulogd/ulogd_inpflow_NFCT.so" plugin="@libdir@/ulogd/ulogd_filter_IFINDEX.so" plugin="@libdir@/ulogd/ulogd_filter_PRINTPKT.so" +plugin="@libdir@/ulogd/ulogd_filter_PRINTFLOW.so" plugin="@libdir@/ulogd/ulogd_output_LOGEMU.so" plugin="@libdir@/ulogd/ulogd_output_OPRINT.so" plugin="@libdir@/ulogd/ulogd_raw2packet_BASE.so" @@ -43,6 +44,9 @@ plugin="@libdir@/ulogd/ulogd_raw2packet_BASE.so" # this is a stack for packet-based logging via LOGEMU #stack=log1:NFLOG,base1:BASE,ifi1:IFINDEX,print1:PRINTPKT,emu1:LOGEMU +# this is a stack for flow-based logging via LOGEMU +#stack=ct1:NFCT,print1:PRINTFLOW,emu1:LOGEMU + # this is a stack for flow-based logging via OPRINT #stack=ct1:NFCT,op1:OPRINT diff --git a/util/printflow.c b/util/printflow.c new file mode 100644 index 0000000..aa354d4 --- /dev/null +++ b/util/printflow.c @@ -0,0 +1,150 @@ +/* printflow.c + * + * build something looking like an iptables LOG message, but for flows + * + * (C) 2006 by Philip Craig + * + * 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 + * + * $Id: printflow.c,v 1.1 2006/05/16 01:57:31 philipc Exp $ + * + */ + +#include +#include +#include +#include +#include +#include + +struct ulogd_key printflow_keys[] = { + { + .type = ULOGD_RET_IPADDR, + .flags = ULOGD_RETF_NONE, + .name = "ip.saddr", + }, + { + .type = ULOGD_RET_IPADDR, + .flags = ULOGD_RETF_NONE, + .name = "ip.daddr", + }, + { + .type = ULOGD_RET_UINT8, + .flags = ULOGD_RETF_NONE, + .name = "ip.protocol", + }, + { + .type = ULOGD_RET_UINT16, + .flags = ULOGD_RETF_NONE, + .name = "l4.sport", + }, + { + .type = ULOGD_RET_UINT16, + .flags = ULOGD_RETF_NONE, + .name = "l4.dport", + }, + { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "raw.pktlen", + }, + { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "raw.pktcount", + }, + { + .type = ULOGD_RET_UINT8, + .flags = ULOGD_RETF_NONE, + .name = "icmp.code", + }, + { + .type = ULOGD_RET_UINT8, + .flags = ULOGD_RETF_NONE, + .name = "icmp.type", + }, + { + .type = ULOGD_RET_BOOL, + .flags = ULOGD_RETF_NONE, + .name = "dir", + }, +}; +int printflow_keys_num = sizeof(printflow_keys)/sizeof(*printflow_keys); + +#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) + +#define pp_print(buf_cur, label, res, x, type) \ + if (pp_is_valid(res, x)) \ + buf_cur += sprintf(buf_cur, label"=%u ", GET_VALUE(res, x).type); + +int printflow_print(struct ulogd_key *res, char *buf) +{ + char *buf_cur = buf; + + if (pp_is_valid(res, 9)) + buf_cur += sprintf(buf_cur, "DIR=%s ", + GET_VALUE(res, 9).b ? "REPLY" : "ORIG "); + + if (pp_is_valid(res, 0)) + buf_cur += sprintf(buf_cur, "SRC=%s ", inet_ntoa( + (struct in_addr) {htonl(GET_VALUE(res, 0).ui32)})); + + if (pp_is_valid(res, 1)) + buf_cur += sprintf(buf_cur, "DST=%s ", inet_ntoa( + (struct in_addr) {htonl(GET_VALUE(res, 1).ui32)})); + + if (!pp_is_valid(res, 2)) + goto out; + + switch (GET_VALUE(res, 2).ui8) { + case IPPROTO_TCP: + buf_cur += sprintf(buf_cur, "PROTO=TCP "); + pp_print(buf_cur, "SPT", res, 3, ui16); + pp_print(buf_cur, "DPT", res, 4, ui16); + break; + + case IPPROTO_UDP: + buf_cur += sprintf(buf_cur, "PROTO=UDP "); + pp_print(buf_cur, "SPT", res, 3, ui16); + pp_print(buf_cur, "DPT", res, 4, ui16); + break; + + case IPPROTO_ICMP: + buf_cur += sprintf(buf_cur, "PROTO=ICMP "); + pp_print(buf_cur, "TYPE", res, 7, ui8); + pp_print(buf_cur, "CODE", res, 8, ui8); + break; + + case IPPROTO_ESP: + buf_cur += sprintf(buf_cur, "PROTO=ESP "); + break; + + case IPPROTO_AH: + buf_cur += sprintf(buf_cur, "PROTO=AH "); + break; + + default: + pp_print(buf_cur, "PROTO", res, 2, ui8); + break; + } + +out: + pp_print(buf_cur, "PKTS", res, 6, ui32); + pp_print(buf_cur, "BYTES", res, 5, ui32); + strcat(buf_cur, "\n"); + + return 0; +} -- cgit v1.2.3