summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
6 files changed, 112 insertions, 6 deletions
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!");