diff options
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | doc/stats/conntrackd.conf | 10 | ||||
-rw-r--r-- | include/buffer.h | 18 | ||||
-rw-r--r-- | include/conntrackd.h | 3 | ||||
-rw-r--r-- | include/log.h | 8 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/buffer.c | 67 | ||||
-rw-r--r-- | src/log.c | 28 | ||||
-rw-r--r-- | src/read_config_lex.l | 1 | ||||
-rw-r--r-- | src/read_config_yy.y | 8 | ||||
-rw-r--r-- | src/stats-mode.c | 12 |
11 files changed, 151 insertions, 7 deletions
@@ -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; +} @@ -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!"); |