summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org>2006-05-23 09:00:01 +0000
committer/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org>2006-05-23 09:00:01 +0000
commit325b7d44124f57674dcaa4088e67238996a5a03b (patch)
treebbfb3034b35a7c2784691eaf49d235748bc608ab
parent62defdbdb365c325795b83845f266410cf7c1076 (diff)
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)
-rw-r--r--filter/Makefile.am5
-rw-r--r--filter/ulogd_filter_PRINTFLOW.c66
-rw-r--r--include/ulogd/Makefile.am2
-rw-r--r--include/ulogd/printflow.h9
-rw-r--r--input/flow/ulogd_inpflow_NFCT.c8
-rw-r--r--output/ulogd_output_LOGEMU.c5
-rw-r--r--output/ulogd_output_SYSLOG.c2
-rw-r--r--ulogd.conf.in4
-rw-r--r--util/printflow.c150
9 files changed, 246 insertions, 5 deletions
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 <philipc@snapgear.com>
+ *
+ * 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 <ulogd/ulogd.h>
+#include <ulogd/printflow.h>
+
+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 <philipc@snapgear.com>
+ *
+ * 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 <string.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <ulogd/ulogd.h>
+#include <ulogd/printflow.h>
+
+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;
+}