summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--doc/stats/conntrackd.conf10
-rw-r--r--include/buffer.h18
-rw-r--r--include/conntrackd.h3
-rw-r--r--include/log.h8
-rw-r--r--src/Makefile.am2
-rw-r--r--src/buffer.c67
-rw-r--r--src/log.c28
-rw-r--r--src/read_config_lex.l1
-rw-r--r--src/read_config_yy.y8
-rw-r--r--src/stats-mode.c12
11 files changed, 151 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 82072f4..ed21d7f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -26,6 +26,7 @@ o add support for related conntracks (requires Linux kernel >= 2.6.22)
o show error and warning messages to stderr
o hash lookup speedups based on comments from netdev's discussions
o add support for connection logging to the statistics mode via Logfile
+o implement buffered connection logging to improve performance
o minor irrelevant fixes for uncommon error paths and fix several typos
o detach daemon from its terminal (Ben Lenitz <BLentz@channing-bete.com>)
o obsolete `-S' option: Use information provided by the config file
diff --git a/doc/stats/conntrackd.conf b/doc/stats/conntrackd.conf
index 4bc5642..8f899b4 100644
--- a/doc/stats/conntrackd.conf
+++ b/doc/stats/conntrackd.conf
@@ -59,6 +59,16 @@ Stats {
LogFile on
#
+ # Set Logfile buffer size. Default is 0.
+ # You can set the size of the connection logging buffer size. This
+ # value determines how often the logging information is written to
+ # the harddisk. High values improves performances. If your firewall
+ # is very busy and you need connection logging, use a big buffer.
+ # Default buffer size is 0 that means direct write through.
+ #
+ #LogFileBufferSize 4096
+
+ #
# Enable connection logging via Syslog. Default is off.
# Syslog: on, off or a facility name (daemon (default) or local0..7)
# If you set the facility, use the same as in the General clause,
diff --git a/include/buffer.h b/include/buffer.h
new file mode 100644
index 0000000..5b854f3
--- /dev/null
+++ b/include/buffer.h
@@ -0,0 +1,18 @@
+#ifndef _BUFFER_H_
+#define _BUFFER_H_
+
+struct buffer {
+ unsigned char *data;
+ unsigned int size;
+ unsigned int cur_size;
+};
+
+struct buffer *buffer_create(unsigned int size);
+int buffer_add(struct buffer *b, void *data, unsigned int size);
+void buffer_flush(struct buffer *b,
+ void (*cb)(void *buffer_data,
+ void *data),
+ void *data);
+unsigned int buffer_size(struct buffer *b);
+
+#endif
diff --git a/include/conntrackd.h b/include/conntrackd.h
index a4a91ea..3bfcf18 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include "cache.h"
+#include "buffer.h"
#include "debug.h"
#include <signal.h>
#include "state_helper.h"
@@ -93,6 +94,7 @@ struct ct_conf {
struct {
char logfile[FILENAME_MAXLEN];
int syslog_facility;
+ unsigned int buffer_size;
} stats;
};
@@ -136,6 +138,7 @@ struct ct_sync_state {
struct ct_stats_state {
struct cache *cache; /* internal events cache (netlink) */
+ struct buffer *buffer_log;
};
union ct_state {
diff --git a/include/log.h b/include/log.h
index 467ae8f..b5bbddb 100644
--- a/include/log.h
+++ b/include/log.h
@@ -1,9 +1,15 @@
#ifndef _LOG_H_
#define _LOG_H_
+#include <stdio.h>
+
+struct buffer;
+struct nf_conntrack;
+
int init_log();
void dlog(FILE *fd, int priority, char *format, ...);
-void dlog_ct(FILE *fd, struct nf_conntrack *ct);
+void dlog_buffered_ct(FILE *fd, struct buffer *b, struct nf_conntrack *ct);
+void dlog_buffered_ct_flush(void *buffer_data, void *data);
void close_log();
#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 62a7467..a7e82cf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,7 +10,7 @@ conntrack_SOURCES = conntrack.c
conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_icmp.la
conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@
-conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c \
+conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c buffer.c \
local.c log.c mcast.c netlink.c \
ignore_pool.c \
cache.c cache_iterators.c \
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 0000000..3283c15
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,67 @@
+/*
+ * (C) 2006-2008 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "buffer.h"
+
+struct buffer *buffer_create(unsigned int size)
+{
+ struct buffer *b;
+
+ b = malloc(sizeof(struct buffer));
+ if (b == NULL)
+ return NULL;
+ memset(b, 0, sizeof(struct buffer));
+
+ b->size = size;
+
+ b->data = malloc(size);
+ if (b->data == NULL) {
+ free(b);
+ return NULL;
+ }
+ memset(b->data, 0, size);
+
+ return b;
+}
+
+int buffer_add(struct buffer *b, void *data, unsigned int size)
+{
+ if (b->size - b->cur_size < size) {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ memcpy(b->data + b->cur_size, data, size);
+ b->cur_size += size;
+}
+
+void buffer_flush(struct buffer *b,
+ void (*cb)(void *buffer_data, void *data),
+ void *data)
+{
+ cb(b->data, data);
+ b->cur_size = 0;
+ memset(b->data, 0, b->size);
+}
+
+unsigned int buffer_size(struct buffer *b)
+{
+ return b->size;
+}
diff --git a/src/log.c b/src/log.c
index a4d51ec..3e3dd12 100644
--- a/src/log.c
+++ b/src/log.c
@@ -22,6 +22,7 @@
#include <time.h>
#include <stdarg.h>
#include <string.h>
+#include "buffer.h"
#include "conntrackd.h"
int init_log(void)
@@ -94,7 +95,15 @@ void dlog(FILE *fd, int priority, char *format, ...)
}
}
-void dlog_ct(FILE *fd, struct nf_conntrack *ct)
+void dlog_buffered_ct_flush(void *buffer_data, void *data)
+{
+ FILE *fd = data;
+
+ fprintf(fd, "%s", buffer_data);
+ fflush(fd);
+}
+
+void dlog_buffered_ct(FILE *fd, struct buffer *b, struct nf_conntrack *ct)
{
time_t t;
char buf[1024];
@@ -107,8 +116,21 @@ void dlog_ct(FILE *fd, struct nf_conntrack *ct)
nfct_snprintf(buf+strlen(buf), 1024-strlen(buf), ct, 0, 0, 0);
if (fd) {
- fprintf(fd, "%s\n", buf);
- fflush(fd);
+ snprintf(buf+strlen(buf), 1024-strlen(buf), "\n");
+ /* zero size buffer: force fflush */
+ if (buffer_size(b) == 0) {
+ fprintf(fd, "%s", buf);
+ fflush(fd);
+ }
+
+ if (buffer_add(b, buf, strlen(buf)) == -1) {
+ buffer_flush(b, dlog_buffered_ct_flush, fd);
+ if (buffer_add(b, buf, strlen(buf)) == -1) {
+ /* buffer too small, catacrocket! */
+ fprintf(fd, "%s", buf);
+ fflush(fd);
+ }
+ }
}
if (CONFIG(stats).syslog_facility != -1)
diff --git a/src/read_config_lex.l b/src/read_config_lex.l
index 847ec74..0acd98c 100644
--- a/src/read_config_lex.l
+++ b/src/read_config_lex.l
@@ -102,6 +102,7 @@ ftfw [F|f][T|t][F|f][W|w]
"TIME_WAIT" { return T_TIME_WAIT; }
"CLOSE" { return T_CLOSE; }
"LISTEN" { return T_LISTEN; }
+"LogFileBufferSize" { return T_STAT_BUFFER_SIZE; }
{is_on} { return T_ON; }
{is_off} { return T_OFF; }
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index 9cb304a..bbc5115 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -49,7 +49,7 @@ struct ct_conf conf;
%token T_REPLICATE T_FOR T_IFACE
%token T_ESTABLISHED T_SYN_SENT T_SYN_RECV T_FIN_WAIT
%token T_CLOSE_WAIT T_LAST_ACK T_TIME_WAIT T_CLOSE T_LISTEN
-%token T_SYSLOG T_WRITE_THROUGH
+%token T_SYSLOG T_WRITE_THROUGH T_STAT_BUFFER_SIZE
%token <string> T_IP T_PATH_VAL
@@ -580,6 +580,7 @@ stat_line: stat_logfile_bool
| stat_logfile_path
| stat_syslog_bool
| stat_syslog_facility
+ | buffer_size
;
stat_logfile_bool : T_LOG T_ON
@@ -638,6 +639,11 @@ stat_syslog_facility : T_SYSLOG T_STRING
"values, defaulting to General.\n");
};
+buffer_size: T_STAT_BUFFER_SIZE T_NUMBER
+{
+ conf.stats.buffer_size = $2;
+};
+
%%
int
diff --git a/src/stats-mode.c b/src/stats-mode.c
index e817c4e..05a1b2c 100644
--- a/src/stats-mode.c
+++ b/src/stats-mode.c
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include "cache.h"
+#include "log.h"
#include "conntrackd.h"
#include <libnfnetlink/libnfnetlink.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
@@ -37,6 +38,12 @@ static int init_stats(void)
}
memset(state.stats, 0, sizeof(struct ct_stats_state));
+ STATE_STATS(buffer_log) = buffer_create(CONFIG(stats).buffer_size);
+ if (!STATE_STATS(buffer_log)) {
+ dlog(STATE(log), LOG_ERR, "can't allocate stats buffer");
+ return -1;
+ }
+
STATE_STATS(cache) = cache_create("stats",
LIFETIME,
CONFIG(family),
@@ -53,6 +60,9 @@ static int init_stats(void)
static void kill_stats()
{
cache_destroy(STATE_STATS(cache));
+ buffer_flush(STATE_STATS(buffer_log),
+ dlog_buffered_ct_flush,
+ STATE(stats_log));
}
/* handler for requests coming via UNIX socket */
@@ -172,7 +182,7 @@ static int event_destroy_stats(struct nf_conntrack *ct)
if (cache_del(STATE_STATS(cache), ct)) {
debug_ct(ct, "cache destroy");
- dlog_ct(STATE(stats_log), ct);
+ dlog_buffered_ct(STATE(stats_log), STATE_STATS(buffer_log), ct);
return 1;
} else {
debug_ct(ct, "can't destroy!");